wj-elements 0.3.7 → 0.4.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.
Files changed (45) hide show
  1. package/dist/base-path.js +16 -2
  2. package/dist/base-path.js.map +1 -1
  3. package/dist/{icon-DVyMc4Wv.js → icon-CReYMzAK.js} +2 -2
  4. package/dist/{icon-DVyMc4Wv.js.map → icon-CReYMzAK.js.map} +1 -1
  5. package/dist/localize.js +15 -2
  6. package/dist/localize.js.map +1 -1
  7. package/dist/packages/localize/localize.d.ts +15 -2
  8. package/dist/packages/translations/en-gb.d.ts +1 -0
  9. package/dist/packages/translations/sk-sk.d.ts +1 -0
  10. package/dist/packages/utils/permissions.d.ts +9 -9
  11. package/dist/packages/wje-accordion/accordion.element.d.ts +3 -6
  12. package/dist/packages/wje-accordion-item/accordion-item.element.d.ts +27 -6
  13. package/dist/packages/wje-animation/animation.element.d.ts +10 -2
  14. package/dist/packages/wje-aside/aside.element.d.ts +10 -6
  15. package/dist/packages/wje-avatar/avatar.element.d.ts +19 -11
  16. package/dist/packages/wje-carousel/carousel.element.d.ts +78 -3
  17. package/dist/packages/wje-carousel-item/carousel-item.element.d.ts +5 -0
  18. package/dist/packages/wje-select/select.element.d.ts +7 -0
  19. package/dist/permissions.js +7 -7
  20. package/dist/permissions.js.map +1 -1
  21. package/dist/wje-accordion-item.js +18 -18
  22. package/dist/wje-accordion-item.js.map +1 -1
  23. package/dist/wje-accordion.js.map +1 -1
  24. package/dist/wje-animation.js +1 -1
  25. package/dist/wje-animation.js.map +1 -1
  26. package/dist/wje-aside.js +1 -1
  27. package/dist/wje-aside.js.map +1 -1
  28. package/dist/wje-avatar.js.map +1 -1
  29. package/dist/wje-button.js +1 -1
  30. package/dist/wje-carousel-item.js +19 -1
  31. package/dist/wje-carousel-item.js.map +1 -1
  32. package/dist/wje-carousel.js +208 -57
  33. package/dist/wje-carousel.js.map +1 -1
  34. package/dist/wje-element.js +4 -4
  35. package/dist/wje-element.js.map +1 -1
  36. package/dist/wje-file-upload-item.js +1 -1
  37. package/dist/wje-icon.js +1 -1
  38. package/dist/wje-img-comparer.js +1 -1
  39. package/dist/wje-master.js +5 -3
  40. package/dist/wje-master.js.map +1 -1
  41. package/dist/wje-option.js +1 -1
  42. package/dist/wje-pagination.js +1 -1
  43. package/dist/wje-select.js +41 -4
  44. package/dist/wje-select.js.map +1 -1
  45. package/package.json +4 -3
package/dist/base-path.js CHANGED
@@ -1,4 +1,19 @@
1
1
  let basePath = "";
2
+ function resolveBasePathFromModuleUrl() {
3
+ var _a;
4
+ if (typeof ((_a = import.meta) == null ? void 0 : _a.url) !== "string" || import.meta.url === "") {
5
+ return "";
6
+ }
7
+ try {
8
+ return new URL(
9
+ /* @vite-ignore */
10
+ ".",
11
+ import.meta.url
12
+ ).href;
13
+ } catch {
14
+ return "";
15
+ }
16
+ }
2
17
  function setBasePath(path) {
3
18
  basePath = path;
4
19
  }
@@ -9,8 +24,7 @@ function getBasePath(appendedPath = "") {
9
24
  if (basePathScript) {
10
25
  setBasePath(basePathScript.dataset.basePath || "");
11
26
  } else {
12
- const path = "";
13
- setBasePath(path.split("/").slice(0, -1).join("/"));
27
+ setBasePath(resolveBasePathFromModuleUrl());
14
28
  }
15
29
  }
16
30
  const subPath = appendedPath.replace(/^\//, "");
@@ -1 +1 @@
1
- {"version":3,"file":"base-path.js","sources":["../packages/utils/base-path.js"],"sourcesContent":["let basePath = '';\n\n/**\n * Sets the base path for the application.\n * @param {string} path The base path to be set.\n * @returns {void} This function does not return anything.\n */\nexport function setBasePath(path) {\n basePath = path;\n}\n\n/**\n * Returns the base path of the application, optionally appending a specified relative path.\n * If the base path has not been set, it determines the base path from the first script element\n * with a `base-path` attribute or generates it based on the current script location.\n * @param {string} [appendedPath] The relative path to append to the base path. Defaults to an empty string.\n * @returns {string} The complete base path, with the appended relative path if specified.\n */\nexport function getBasePath(appendedPath = '') {\n if (!basePath) {\n const scripts = [...document.getElementsByTagName('script')];\n const basePathScript = scripts.find(script => script.hasAttribute('data-base-path'));\n\n if (basePathScript) {\n setBasePath(basePathScript.dataset.basePath || '');\n } else {\n const path = '';\n\n setBasePath(path.split('/').slice(0, -1).join('/'));\n }\n }\n\n const subPath = appendedPath.replace(/^\\//, '');\n\n return basePath.replace(/\\/$/, '') + (appendedPath ? '/' + subPath : '');\n}"],"names":[],"mappings":"AAAA,IAAI,WAAW;AAOR,SAAS,YAAY,MAAM;AAChC,aAAW;AACb;AASO,SAAS,YAAY,eAAe,IAAI;AAC7C,MAAI,CAAC,UAAU;AACb,UAAM,UAAU,CAAC,GAAG,SAAS,qBAAqB,QAAQ,CAAC;AAC3D,UAAM,iBAAiB,QAAQ,KAAK,YAAU,OAAO,aAAa,gBAAgB,CAAC;AAEnF,QAAI,gBAAgB;AAClB,kBAAY,eAAe,QAAQ,YAAa,EAAE;AAAA,IACpD,OAAO;AACL,YAAM,OAAO;AAEb,kBAAY,KAAK,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC;AAAA,IACpD;AAAA,EACF;AAEA,QAAM,UAAU,aAAa,QAAQ,OAAO,EAAE;AAE9C,SAAO,SAAS,QAAQ,OAAO,EAAE,KAAK,eAAe,MAAM,UAAU;AACvE;"}
1
+ {"version":3,"file":"base-path.js","sources":["../packages/utils/base-path.js"],"sourcesContent":["let basePath = '';\n\nfunction resolveBasePathFromModuleUrl() {\n if (typeof import.meta?.url !== 'string' || import.meta.url === '') {\n return '';\n }\n\n try {\n return new URL(/* @vite-ignore */ '.', import.meta.url).href;\n } catch {\n return '';\n }\n}\n\n/**\n * Sets the base path for the application.\n * @param {string} path The base path to be set.\n * @returns {void} This function does not return anything.\n */\nexport function setBasePath(path) {\n basePath = path;\n}\n\n/**\n * Returns the base path of the application, optionally appending a specified relative path.\n * If the base path has not been set, it determines the base path from the first script element\n * with a `base-path` attribute or generates it based on the current script location.\n * @param {string} [appendedPath] The relative path to append to the base path. Defaults to an empty string.\n * @returns {string} The complete base path, with the appended relative path if specified.\n */\nexport function getBasePath(appendedPath = '') {\n if (!basePath) {\n const scripts = [...document.getElementsByTagName('script')];\n const basePathScript = scripts.find(script => script.hasAttribute('data-base-path'));\n\n if (basePathScript) {\n setBasePath(basePathScript.dataset.basePath || '');\n } else {\n setBasePath(resolveBasePathFromModuleUrl());\n }\n }\n\n const subPath = appendedPath.replace(/^\\//, '');\n\n return basePath.replace(/\\/$/, '') + (appendedPath ? '/' + subPath : '');\n}\n"],"names":[],"mappings":"AAAA,IAAI,WAAW;AAEf,SAAS,+BAA+B;AAFxC;AAGE,MAAI,SAAO,wCAAa,SAAQ,YAAY,YAAY,QAAQ,IAAI;AAClE,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,IAAI;AAAA;AAAA,MAAuB;AAAA,MAAK,YAAY;AAAA,IAAG,EAAE;AAAA,EAC1D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,YAAY,MAAM;AAChC,aAAW;AACb;AASO,SAAS,YAAY,eAAe,IAAI;AAC7C,MAAI,CAAC,UAAU;AACb,UAAM,UAAU,CAAC,GAAG,SAAS,qBAAqB,QAAQ,CAAC;AAC3D,UAAM,iBAAiB,QAAQ,KAAK,YAAU,OAAO,aAAa,gBAAgB,CAAC;AAEnF,QAAI,gBAAgB;AAClB,kBAAY,eAAe,QAAQ,YAAa,EAAE;AAAA,IACpD,OAAO;AACL,kBAAY,6BAA4B,CAAE;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,UAAU,aAAa,QAAQ,OAAO,EAAE;AAE9C,SAAO,SAAS,QAAQ,OAAO,EAAE,KAAK,eAAe,MAAM,UAAU;AACvE;"}
@@ -128,7 +128,7 @@ const getNamedUrl = (iconName, libraryName = "default", filled = false) => {
128
128
  let url = library.resolver(iconName, filled ? "filled" : "outline");
129
129
  return url;
130
130
  };
131
- const styles = "/*\n[ WJ Icon ]\n*/\n\n:host {\n width: var(--wje-icon-size);\n height: var(--wje-icon-size);\n display: block;\n}\n\n.native-icon {\n display: flex;\n align-items: center;\n}\n\nsvg {\n width: 100%;\n height: 100%;\n stroke-width: var(--wje-icon-stroke);\n color: var(--wje-icon-color);\n}\n\n/*STROKE*/\n:host([stroke='1']) {\n --wje-icon-stroke: 1;\n}\n\n:host([stroke='1.25']) {\n --wje-icon-stroke: 1.25;\n}\n\n:host([stroke='1.5']) {\n --wje-icon-stroke: 1.5;\n}\n\n:host([stroke='1.75']) {\n --wje-icon-stroke: 1.75;\n}\n\n:host([stroke='2']) {\n --wje-icon-stroke: 2;\n}\n\n/*SIZE*/\n:host([size='2x-small']) {\n --wje-icon-size: var(--wje-size-2x-small);\n}\n\n:host([size='x-small']) {\n --wje-icon-size: var(--wje-size-x-small);\n}\n\n:host([size='small']) {\n --wje-icon-size: var(--wje-size-small);\n}\n\n:host([size='medium']) {\n --wje-icon-size: var(--wje-size-medium);\n}\n\n:host([size='large']) {\n --wje-icon-size: var(--wje-size-large);\n}\n\n:host([size='x-large']) {\n --wje-icon-size: var(--wje-size-x-large);\n}\n\n:host([size='2x-large']) {\n --wje-icon-size: var(--wje-size-2x-large);\n}\n\n:host([size='3x-large']) {\n --wje-icon-size: var(--wje-size-3x-large);\n}\n\n:host([size='4x-large']) {\n --wje-icon-size: var(--wje-size-4x-large);\n}\n\n/*COLOR*/\n:host([color='primary']) .native-icon {\n color: var(--wje-color-primary-9);\n}\n\n:host([color='complete']) .native-icon {\n color: var(--wje-color-complete-9);\n}\n\n:host([color='success']) .native-icon {\n color: var(--wje-color-success-9);\n}\n\n:host([color='warning']) .native-icon {\n color: var(--wje-color-warning-9);\n}\n\n:host([color='danger']) .native-icon {\n color: var(--wje-color-danger-9);\n}\n\n:host([color='info']) .native-icon {\n color: var(--wje-color-info-9);\n}\n\n:host([color='menu']) .native-icon {\n color: var(--wje-color-contrast-9);\n}\n";
131
+ const styles = "/*\n[ WJ Icon ]\n*/\n\n:host {\n width: var(--wje-icon-width, var(--wje-icon-size, 1rem));\n height: var(--wje-icon-height, var(--wje-icon-size, 1rem));\n display: block;\n box-sizing: content-box !important;\n}\n\n.native-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\nsvg {\n width: 100%;\n height: 100%;\n stroke-width: var(--wje-icon-stroke);\n color: var(--wje-icon-color);\n}\n\n/*STROKE*/\n:host([stroke='1']) {\n --wje-icon-stroke: 1;\n}\n\n:host([stroke='1.25']) {\n --wje-icon-stroke: 1.25;\n}\n\n:host([stroke='1.5']) {\n --wje-icon-stroke: 1.5;\n}\n\n:host([stroke='1.75']) {\n --wje-icon-stroke: 1.75;\n}\n\n:host([stroke='2']) {\n --wje-icon-stroke: 2;\n}\n\n/*SIZE*/\n:host([size='2x-small']) {\n --wje-icon-size: var(--wje-size-2x-small);\n}\n\n:host([size='x-small']) {\n --wje-icon-size: var(--wje-size-x-small);\n}\n\n:host([size='small']) {\n --wje-icon-size: var(--wje-size-small);\n}\n\n:host([size='medium']) {\n --wje-icon-size: var(--wje-size-medium);\n}\n\n:host([size='large']) {\n --wje-icon-size: var(--wje-size-large);\n}\n\n:host([size='x-large']) {\n --wje-icon-size: var(--wje-size-x-large);\n}\n\n:host([size='2x-large']) {\n --wje-icon-size: var(--wje-size-2x-large);\n}\n\n:host([size='3x-large']) {\n --wje-icon-size: var(--wje-size-3x-large);\n}\n\n:host([size='4x-large']) {\n --wje-icon-size: var(--wje-size-4x-large);\n}\n\n/*COLOR*/\n:host([color='primary']) .native-icon {\n color: var(--wje-color-primary-9);\n}\n\n:host([color='complete']) .native-icon {\n color: var(--wje-color-complete-9);\n}\n\n:host([color='success']) .native-icon {\n color: var(--wje-color-success-9);\n}\n\n:host([color='warning']) .native-icon {\n color: var(--wje-color-warning-9);\n}\n\n:host([color='danger']) .native-icon {\n color: var(--wje-color-danger-9);\n}\n\n:host([color='info']) .native-icon {\n color: var(--wje-color-info-9);\n}\n\n:host([color='menu']) .native-icon {\n color: var(--wje-color-contrast-9);\n}\n";
132
132
  class Icon extends WJElement {
133
133
  /**
134
134
  * Creates an instance of IconElement.
@@ -242,4 +242,4 @@ export {
242
242
  registerIconLibrary as r,
243
243
  unregisterIconLibrary as u
244
244
  };
245
- //# sourceMappingURL=icon-DVyMc4Wv.js.map
245
+ //# sourceMappingURL=icon-CReYMzAK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icon-DVyMc4Wv.js","sources":["../packages/utils/icon-library.js","../packages/wje-icon/service/service.js","../packages/wje-icon/icon.element.js","../packages/wje-icon/icon.js"],"sourcesContent":["import { getBasePath } from \"./base-path.js\";\n\nlet registry = [];\n\nregisterIconLibrary(\"default\", {\n resolver: (name, style) => getBasePath(`assets/img/icons/${style}/${name}.svg`)\n});\n\nexport function getIconLibrary(name) {\n return registry.find(lib => lib.name === name);\n}\n\nexport function registerIconLibrary(name, options) {\n unregisterIconLibrary(name);\n registry.push({\n name,\n resolver: options.resolver,\n });\n}\n\nexport function unregisterIconLibrary(name) {\n registry = registry.filter(lib => lib.name !== name);\n}","import { getIconLibrary } from \"../../utils/icon-library.js\";\n\nexport const iconContent = new Map();\nconst requests = new Map();\n\nlet parser;\n\n/**\n * Validates and returns a trimmed source string if it meets the required criteria.\n * @param {string} src The source string to validate and trim.\n * @returns {string|null} The validated and trimmed source string, or `null` if invalid.\n * @example\n * getSrc(' https://example.com/image.jpg '); // Returns 'https://example.com/image.jpg'\n * getSrc('invalid-src'); // Returns null\n */\nexport const getSrc = (src) => {\n if (isStr(src)) {\n src = src.trim();\n if (isSrc(src)) {\n return src;\n }\n }\n return null;\n};\n\n/**\n * Checks if a given string is a valid source based on specific criteria.\n * @param {string} str The string to validate as a source.\n * @returns {boolean} `true` if the string is considered a valid source, `false` otherwise.\n * @example\n * isSrc('https://example.com/image.jpg'); // Returns true\n * isSrc('image.jpg'); // Returns true\n * isSrc('invalid-src'); // Returns false\n */\nexport const isSrc = (str) => str.length > 0 && /(\\/|\\.)/.test(str);\n\n/**\n * Checks if the provided URL is an SVG data URL.\n * @param {string} url The URL to check.\n * @returns {boolean} - Returns `true` if the URL starts with 'data:image/svg+xml', otherwise `false`.\n * @example\n * isSvgDataUrl('data:image/svg+xml;base64,...'); // Returns true\n * isSvgDataUrl('https://example.com/image.svg'); // Returns false\n */\nexport const isSvgDataUrl = (url) => url.startsWith('data:image/svg+xml');\n\n/**\n * Checks if the provided URL is an encoded data URL.\n * @param {string} url The URL to check.\n * @returns {boolean} - Returns `true` if the URL contains ';utf8,', otherwise `false`.\n * @example\n * isEncodedDataUrl('data:text/plain;charset=utf8,...'); // Returns true\n * isEncodedDataUrl('https://example.com/file.txt'); // Returns false\n */\nexport const isEncodedDataUrl = (url) => url.indexOf(';utf8,') !== -1;\n\n/**\n * Checks if the provided value is of string type.\n * @param {*} val The value to check.\n * @returns {boolean} - Returns `true` if the value is a string, otherwise `false`.\n * @example\n * isStr('Hello, World!'); // Returns true\n * isStr(12345); // Returns false\n */\nexport const isStr = (val) => typeof val === 'string';\n\n/**\n * Validates the provided SVG content and ensures it contains a valid SVG element.\n * @param {string} svgContent The SVG content to validate.\n * @returns {string} Returns the validated SVG content as a string if valid, otherwise an empty string.\n * @example\n * const validSvg = '&lt;svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\">&lt;/svg>';\n * validateContent(validSvg); // Returns '&lt;svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\">&lt;/svg>'\n * const invalidSvg = '&lt;div>&lt;/div>';\n * validateContent(invalidSvg); // Returns ''\n */\nexport const validateContent = (svgContent) => {\n const div = document.createElement('div');\n div.innerHTML = svgContent;\n\n const svgElm = div.firstElementChild;\n if (svgElm && svgElm.nodeName.toLowerCase() === 'svg') {\n const svgClass = svgElm.getAttribute('class') || '';\n\n if (isValid(svgElm)) {\n return div.innerHTML;\n }\n }\n return '';\n};\n\n/**\n * Validates an element to ensure it does not contain potentially unsafe content.\n * @param {Element|Node} elm The element or node to validate.\n * @returns {boolean} - Returns `true` if the element is valid, otherwise `false`.\n * @description\n * This function checks the following:\n * 1. The element is an element node (nodeType 1).\n * 2. The element is not a `&lt;script>` tag.\n * 3. The element does not contain any `on*` event handler attributes (e.g., `onclick`).\n * 4. All child nodes recursively pass the same validation.\n * @example\n * const validElement = document.createElement('div');\n * isValid(validElement); // Returns true\n *\n * const scriptElement = document.createElement('script');\n * isValid(scriptElement); // Returns false\n *\n * const divWithOnClick = document.createElement('div');\n * divWithOnClick.setAttribute('onclick', 'alert(\"hi\")');\n * isValid(divWithOnClick); // Returns false\n */\nexport const isValid = (elm) => {\n // Only element nodes\n if (elm.nodeType === 1) {\n // Check for script elements\n if (elm.nodeName.toLowerCase() === 'script') {\n return false;\n }\n\n // Check for on* attributes\n for (let i = 0; i < elm.attributes.length; i++) {\n const name = elm.attributes[i].name;\n if (isStr(name) && name.toLowerCase().indexOf('on') === 0) {\n return false;\n }\n }\n\n // Check for child nodes\n for (let i = 0; i < elm.childNodes.length; i++) {\n if (!isValid(elm.childNodes[i])) {\n return false;\n }\n }\n }\n return true;\n};\n\n/**\n * Fetches and optionally sanitizes SVG content from a given URL.\n * @param {string} url The URL of the SVG resource or data URL.\n * @param {boolean} [sanitize] Whether to sanitize the SVG content. Defaults to `true`.\n * @returns {Promise<void>} A promise that resolves when the SVG content is fetched and stored.\n * @description\n * This function performs the following:\n * - If the URL is an SVG data URL and encoded, it parses the content to extract the SVG.\n * - If the URL is a standard HTTP/HTTPS URL, it fetches the content.\n * - Optionally sanitizes the fetched SVG content.\n * - Caches the content for future use.\n * @example\n * getSvgContent('https://example.com/icon.svg').then(() => {\n * console.log('SVG content fetched and stored.');\n * });\n * @example\n * getSvgContent('data:image/svg+xml;base64,...', false).then(() => {\n * console.log('SVG data URL processed without sanitization.');\n * });\n */\nexport const getSvgContent = (url, sanitize) => {\n let req = requests.get(url);\n if (!req) {\n if (typeof fetch !== 'undefined' && typeof document !== 'undefined') {\n if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {\n if (!parser) {\n parser = new DOMParser();\n }\n const doc = parser.parseFromString(url, 'text/html');\n const svg = doc.querySelector('svg');\n if (svg) {\n iconContent.set(url, svg.outerHTML);\n }\n return Promise.resolve();\n } else {\n req = fetch(url).then((rsp) => {\n if (rsp.ok) {\n return rsp.text().then((svgContent) => {\n if (svgContent && sanitize !== false) {\n svgContent = validateContent(svgContent);\n }\n iconContent.set(url, svgContent || '');\n });\n }\n return iconContent.set(url, '');\n });\n requests.set(url, req);\n }\n } else {\n iconContent.set(url, '');\n return Promise.resolve();\n }\n }\n return req;\n};\n\n/**\n * Retrieves the URL for an icon based on its `src` or `name` attributes.\n * @param {HTMLElement} i The icon element from which to extract the URL.\n * @returns {string|null} The URL of the icon if found, or `null` if no valid URL can be determined.\n * @description\n * This function performs the following:\n * 1. Attempts to retrieve the URL from the `src` attribute using `getSrc`.\n * 2. If no `src` is provided, it falls back to the `name` attribute using `getName`.\n * 3. If a name is found, it uses `getNamedUrl` to construct the URL, considering the `filled` attribute.\n * @example\n * const iconElement = document.querySelector('wje-icon');\n * const url = getUrl(iconElement);\n * console.log(url); // Outputs the resolved URL or `null`.\n */\nexport const getUrl = (i) => {\n let url = getSrc(i.src);\n if (url) {\n return url;\n }\n\n url = getName(i.name);\n\n if (url) {\n return getNamedUrl(url, i.library, i.hasAttribute('filled'));\n }\n\n return null;\n};\n\n/**\n * Validates and returns a sanitized icon name.\n * @param {string} iconName The icon name to validate.\n * @returns {string|null} The sanitized icon name, or `null` if the input is invalid.\n * @description\n * This function checks if the provided `iconName` is a valid string:\n * - It must not be empty or contain invalid characters.\n * - Only alphanumeric characters, hyphens, and digits are allowed.\n * @example\n * const validName = getName('user-icon');\n * console.log(validName); // 'user-icon'\n * const invalidName = getName('user@icon!');\n * console.log(invalidName); // null\n */\nexport const getName = (iconName) => {\n if (!isStr(iconName) || iconName.trim() === '') {\n return null;\n }\n\n const invalidChars = iconName.replace(/[a-z]|-|\\d/gi, '');\n if (invalidChars !== '') {\n return null;\n }\n\n return iconName;\n};\n\n/**\n * Constructs the URL for a named SVG icon.\n * @param {string} iconName The name of the icon to retrieve.\n * @param {string} [libraryName] The name of the icon library to use. Defaults to \"default\".\n * @param {boolean} [filled] Whether to use the \"filled\" variant of the icon. Defaults to \"outline\" if `false`.\n * @returns {string} - The complete URL to the SVG icon.\n * @description\n * This function generates a URL for an icon based on its name and style (filled or outline).\n * It uses the base URL from the environment variable `VITE_ICON_ASSETS_URL`.\n * @example\n * const url = getNamedUrl('user-icon', 'default', true);\n * console.log(url); // 'https://example.com/filled/user-icon.svg'\n *\n * const outlineUrl = getNamedUrl('settings', 'default');\n * console.log(outlineUrl); // 'https://example.com/outline/settings.svg'\n */\nconst getNamedUrl = (iconName, libraryName = 'default', filled = false) => {\n let library = getIconLibrary(libraryName);\n let url = library.resolver(iconName, filled ? 'filled' : 'outline');\n\n return url;\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport { getSvgContent, getUrl, iconContent } from './service/service.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This element represents an icon. `IconElement` is a custom web component that represents an icon.\n * @documentation https://elements.webjet.sk/components/icon\n * @status stable\n * @augments WJElement\n * @csspart svg - The SVG part of the icon\n * @cssproperty [--wje-icon-size=1rem] - The size of the icon element\n * @cssproperty [--wje-icon-width=var(--wje-icon-size, 100%)] - The width of the icon element\n * @cssproperty [--wje-icon-height=var(--wje-icon-size, 100%)] - The height of the icon element\n * @tag wje-icon\n */\nexport default class Icon extends WJElement {\n /**\n * Creates an instance of IconElement.\n * @class\n */\n constructor() {\n super();\n }\n\n /**\n * Sets the name of the icon.\n * @type {string}\n */\n className = 'Icon';\n\n /**\n * Returns the CSS styles for the component.\n * @static\n * @returns {CSSStyleSheet}\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 ['name', 'filled', 'label'];\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n this.syncAria();\n }\n\n /**\n * Draws the component.\n * @param {object} context The context for drawing.\n * @param {object} store The store for drawing.\n * @param {object} params The parameters for drawing.\n * @returns {DocumentFragment}\n */\n draw(context, store, params) {\n let fragment = document.createDocumentFragment();\n\n this.classList.add('lazy-loaded-image', 'lazy');\n\n let native = document.createElement('div');\n native.setAttribute('part', 'native');\n native.classList.add('native-icon');\n\n this.url = getUrl(this);\n\n fragment.appendChild(native);\n\n this.native = native;\n\n return fragment;\n }\n\n /**\n * Called after the component has been drawn.\n */\n afterDraw() {\n this.syncAria();\n let lazyImageObserver = new IntersectionObserver((entries, observer) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n getSvgContent(this.url).then((svgContent) => {\n this.native.innerHTML = iconContent?.get(this.url);\n this.native.querySelector('svg')?.setAttribute('part', 'svg');\n });\n\n this.classList.remove('lazy');\n lazyImageObserver.unobserve(entry.target);\n }\n });\n });\n\n lazyImageObserver.observe(this.native);\n }\n\n /**\n * Sync ARIA attributes on host.\n */\n syncAria() {\n const ariaLabel = this.getAttribute('aria-label');\n const label = this.getAttribute('label');\n\n if (ariaLabel || label) {\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'img');\n }\n if (!ariaLabel && label) {\n this.setAriaState({ label });\n }\n this.removeAttribute('aria-hidden');\n } else {\n this.setAttribute('aria-hidden', 'true');\n }\n }\n\n /**\n * Handles attribute changes for ARIA sync.\n * @param {string} name\n * @param {string|null} oldValue\n * @param {string|null} newValue\n */\n attributeChangedCallback(name, oldValue, newValue) {\n if (super.attributeChangedCallback) {\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n if (name === 'label' && oldValue !== newValue) {\n this.syncAria();\n }\n }\n}\n","import Icon from './icon.element.js';\n\nexport default Icon;\n\nIcon.define('wje-icon', Icon);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"icon-CReYMzAK.js","sources":["../packages/utils/icon-library.js","../packages/wje-icon/service/service.js","../packages/wje-icon/icon.element.js","../packages/wje-icon/icon.js"],"sourcesContent":["import { getBasePath } from \"./base-path.js\";\n\nlet registry = [];\n\nregisterIconLibrary(\"default\", {\n resolver: (name, style) => getBasePath(`assets/img/icons/${style}/${name}.svg`)\n});\n\nexport function getIconLibrary(name) {\n return registry.find(lib => lib.name === name);\n}\n\nexport function registerIconLibrary(name, options) {\n unregisterIconLibrary(name);\n registry.push({\n name,\n resolver: options.resolver,\n });\n}\n\nexport function unregisterIconLibrary(name) {\n registry = registry.filter(lib => lib.name !== name);\n}","import { getIconLibrary } from \"../../utils/icon-library.js\";\n\nexport const iconContent = new Map();\nconst requests = new Map();\n\nlet parser;\n\n/**\n * Validates and returns a trimmed source string if it meets the required criteria.\n * @param {string} src The source string to validate and trim.\n * @returns {string|null} The validated and trimmed source string, or `null` if invalid.\n * @example\n * getSrc(' https://example.com/image.jpg '); // Returns 'https://example.com/image.jpg'\n * getSrc('invalid-src'); // Returns null\n */\nexport const getSrc = (src) => {\n if (isStr(src)) {\n src = src.trim();\n if (isSrc(src)) {\n return src;\n }\n }\n return null;\n};\n\n/**\n * Checks if a given string is a valid source based on specific criteria.\n * @param {string} str The string to validate as a source.\n * @returns {boolean} `true` if the string is considered a valid source, `false` otherwise.\n * @example\n * isSrc('https://example.com/image.jpg'); // Returns true\n * isSrc('image.jpg'); // Returns true\n * isSrc('invalid-src'); // Returns false\n */\nexport const isSrc = (str) => str.length > 0 && /(\\/|\\.)/.test(str);\n\n/**\n * Checks if the provided URL is an SVG data URL.\n * @param {string} url The URL to check.\n * @returns {boolean} - Returns `true` if the URL starts with 'data:image/svg+xml', otherwise `false`.\n * @example\n * isSvgDataUrl('data:image/svg+xml;base64,...'); // Returns true\n * isSvgDataUrl('https://example.com/image.svg'); // Returns false\n */\nexport const isSvgDataUrl = (url) => url.startsWith('data:image/svg+xml');\n\n/**\n * Checks if the provided URL is an encoded data URL.\n * @param {string} url The URL to check.\n * @returns {boolean} - Returns `true` if the URL contains ';utf8,', otherwise `false`.\n * @example\n * isEncodedDataUrl('data:text/plain;charset=utf8,...'); // Returns true\n * isEncodedDataUrl('https://example.com/file.txt'); // Returns false\n */\nexport const isEncodedDataUrl = (url) => url.indexOf(';utf8,') !== -1;\n\n/**\n * Checks if the provided value is of string type.\n * @param {*} val The value to check.\n * @returns {boolean} - Returns `true` if the value is a string, otherwise `false`.\n * @example\n * isStr('Hello, World!'); // Returns true\n * isStr(12345); // Returns false\n */\nexport const isStr = (val) => typeof val === 'string';\n\n/**\n * Validates the provided SVG content and ensures it contains a valid SVG element.\n * @param {string} svgContent The SVG content to validate.\n * @returns {string} Returns the validated SVG content as a string if valid, otherwise an empty string.\n * @example\n * const validSvg = '&lt;svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\">&lt;/svg>';\n * validateContent(validSvg); // Returns '&lt;svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\">&lt;/svg>'\n * const invalidSvg = '&lt;div>&lt;/div>';\n * validateContent(invalidSvg); // Returns ''\n */\nexport const validateContent = (svgContent) => {\n const div = document.createElement('div');\n div.innerHTML = svgContent;\n\n const svgElm = div.firstElementChild;\n if (svgElm && svgElm.nodeName.toLowerCase() === 'svg') {\n const svgClass = svgElm.getAttribute('class') || '';\n\n if (isValid(svgElm)) {\n return div.innerHTML;\n }\n }\n return '';\n};\n\n/**\n * Validates an element to ensure it does not contain potentially unsafe content.\n * @param {Element|Node} elm The element or node to validate.\n * @returns {boolean} - Returns `true` if the element is valid, otherwise `false`.\n * @description\n * This function checks the following:\n * 1. The element is an element node (nodeType 1).\n * 2. The element is not a `&lt;script>` tag.\n * 3. The element does not contain any `on*` event handler attributes (e.g., `onclick`).\n * 4. All child nodes recursively pass the same validation.\n * @example\n * const validElement = document.createElement('div');\n * isValid(validElement); // Returns true\n *\n * const scriptElement = document.createElement('script');\n * isValid(scriptElement); // Returns false\n *\n * const divWithOnClick = document.createElement('div');\n * divWithOnClick.setAttribute('onclick', 'alert(\"hi\")');\n * isValid(divWithOnClick); // Returns false\n */\nexport const isValid = (elm) => {\n // Only element nodes\n if (elm.nodeType === 1) {\n // Check for script elements\n if (elm.nodeName.toLowerCase() === 'script') {\n return false;\n }\n\n // Check for on* attributes\n for (let i = 0; i < elm.attributes.length; i++) {\n const name = elm.attributes[i].name;\n if (isStr(name) && name.toLowerCase().indexOf('on') === 0) {\n return false;\n }\n }\n\n // Check for child nodes\n for (let i = 0; i < elm.childNodes.length; i++) {\n if (!isValid(elm.childNodes[i])) {\n return false;\n }\n }\n }\n return true;\n};\n\n/**\n * Fetches and optionally sanitizes SVG content from a given URL.\n * @param {string} url The URL of the SVG resource or data URL.\n * @param {boolean} [sanitize] Whether to sanitize the SVG content. Defaults to `true`.\n * @returns {Promise<void>} A promise that resolves when the SVG content is fetched and stored.\n * @description\n * This function performs the following:\n * - If the URL is an SVG data URL and encoded, it parses the content to extract the SVG.\n * - If the URL is a standard HTTP/HTTPS URL, it fetches the content.\n * - Optionally sanitizes the fetched SVG content.\n * - Caches the content for future use.\n * @example\n * getSvgContent('https://example.com/icon.svg').then(() => {\n * console.log('SVG content fetched and stored.');\n * });\n * @example\n * getSvgContent('data:image/svg+xml;base64,...', false).then(() => {\n * console.log('SVG data URL processed without sanitization.');\n * });\n */\nexport const getSvgContent = (url, sanitize) => {\n let req = requests.get(url);\n if (!req) {\n if (typeof fetch !== 'undefined' && typeof document !== 'undefined') {\n if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {\n if (!parser) {\n parser = new DOMParser();\n }\n const doc = parser.parseFromString(url, 'text/html');\n const svg = doc.querySelector('svg');\n if (svg) {\n iconContent.set(url, svg.outerHTML);\n }\n return Promise.resolve();\n } else {\n req = fetch(url).then((rsp) => {\n if (rsp.ok) {\n return rsp.text().then((svgContent) => {\n if (svgContent && sanitize !== false) {\n svgContent = validateContent(svgContent);\n }\n iconContent.set(url, svgContent || '');\n });\n }\n return iconContent.set(url, '');\n });\n requests.set(url, req);\n }\n } else {\n iconContent.set(url, '');\n return Promise.resolve();\n }\n }\n return req;\n};\n\n/**\n * Retrieves the URL for an icon based on its `src` or `name` attributes.\n * @param {HTMLElement} i The icon element from which to extract the URL.\n * @returns {string|null} The URL of the icon if found, or `null` if no valid URL can be determined.\n * @description\n * This function performs the following:\n * 1. Attempts to retrieve the URL from the `src` attribute using `getSrc`.\n * 2. If no `src` is provided, it falls back to the `name` attribute using `getName`.\n * 3. If a name is found, it uses `getNamedUrl` to construct the URL, considering the `filled` attribute.\n * @example\n * const iconElement = document.querySelector('wje-icon');\n * const url = getUrl(iconElement);\n * console.log(url); // Outputs the resolved URL or `null`.\n */\nexport const getUrl = (i) => {\n let url = getSrc(i.src);\n if (url) {\n return url;\n }\n\n url = getName(i.name);\n\n if (url) {\n return getNamedUrl(url, i.library, i.hasAttribute('filled'));\n }\n\n return null;\n};\n\n/**\n * Validates and returns a sanitized icon name.\n * @param {string} iconName The icon name to validate.\n * @returns {string|null} The sanitized icon name, or `null` if the input is invalid.\n * @description\n * This function checks if the provided `iconName` is a valid string:\n * - It must not be empty or contain invalid characters.\n * - Only alphanumeric characters, hyphens, and digits are allowed.\n * @example\n * const validName = getName('user-icon');\n * console.log(validName); // 'user-icon'\n * const invalidName = getName('user@icon!');\n * console.log(invalidName); // null\n */\nexport const getName = (iconName) => {\n if (!isStr(iconName) || iconName.trim() === '') {\n return null;\n }\n\n const invalidChars = iconName.replace(/[a-z]|-|\\d/gi, '');\n if (invalidChars !== '') {\n return null;\n }\n\n return iconName;\n};\n\n/**\n * Constructs the URL for a named SVG icon.\n * @param {string} iconName The name of the icon to retrieve.\n * @param {string} [libraryName] The name of the icon library to use. Defaults to \"default\".\n * @param {boolean} [filled] Whether to use the \"filled\" variant of the icon. Defaults to \"outline\" if `false`.\n * @returns {string} - The complete URL to the SVG icon.\n * @description\n * This function generates a URL for an icon based on its name and style (filled or outline).\n * It uses the base URL from the environment variable `VITE_ICON_ASSETS_URL`.\n * @example\n * const url = getNamedUrl('user-icon', 'default', true);\n * console.log(url); // 'https://example.com/filled/user-icon.svg'\n *\n * const outlineUrl = getNamedUrl('settings', 'default');\n * console.log(outlineUrl); // 'https://example.com/outline/settings.svg'\n */\nconst getNamedUrl = (iconName, libraryName = 'default', filled = false) => {\n let library = getIconLibrary(libraryName);\n let url = library.resolver(iconName, filled ? 'filled' : 'outline');\n\n return url;\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport { getSvgContent, getUrl, iconContent } from './service/service.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This element represents an icon. `IconElement` is a custom web component that represents an icon.\n * @documentation https://elements.webjet.sk/components/icon\n * @status stable\n * @augments WJElement\n * @csspart svg - The SVG part of the icon\n * @cssproperty [--wje-icon-size=1rem] - The size of the icon element\n * @cssproperty [--wje-icon-width=var(--wje-icon-size, 100%)] - The width of the icon element\n * @cssproperty [--wje-icon-height=var(--wje-icon-size, 100%)] - The height of the icon element\n * @tag wje-icon\n */\nexport default class Icon extends WJElement {\n /**\n * Creates an instance of IconElement.\n * @class\n */\n constructor() {\n super();\n }\n\n /**\n * Sets the name of the icon.\n * @type {string}\n */\n className = 'Icon';\n\n /**\n * Returns the CSS styles for the component.\n * @static\n * @returns {CSSStyleSheet}\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 ['name', 'filled', 'label'];\n }\n\n /**\n * Sets up the attributes for the component.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n this.syncAria();\n }\n\n /**\n * Draws the component.\n * @param {object} context The context for drawing.\n * @param {object} store The store for drawing.\n * @param {object} params The parameters for drawing.\n * @returns {DocumentFragment}\n */\n draw(context, store, params) {\n let fragment = document.createDocumentFragment();\n\n this.classList.add('lazy-loaded-image', 'lazy');\n\n let native = document.createElement('div');\n native.setAttribute('part', 'native');\n native.classList.add('native-icon');\n\n this.url = getUrl(this);\n\n fragment.appendChild(native);\n\n this.native = native;\n\n return fragment;\n }\n\n /**\n * Called after the component has been drawn.\n */\n afterDraw() {\n this.syncAria();\n let lazyImageObserver = new IntersectionObserver((entries, observer) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n getSvgContent(this.url).then((svgContent) => {\n this.native.innerHTML = iconContent?.get(this.url);\n this.native.querySelector('svg')?.setAttribute('part', 'svg');\n });\n\n this.classList.remove('lazy');\n lazyImageObserver.unobserve(entry.target);\n }\n });\n });\n\n lazyImageObserver.observe(this.native);\n }\n\n /**\n * Sync ARIA attributes on host.\n */\n syncAria() {\n const ariaLabel = this.getAttribute('aria-label');\n const label = this.getAttribute('label');\n\n if (ariaLabel || label) {\n if (!this.hasAttribute('role')) {\n this.setAttribute('role', 'img');\n }\n if (!ariaLabel && label) {\n this.setAriaState({ label });\n }\n this.removeAttribute('aria-hidden');\n } else {\n this.setAttribute('aria-hidden', 'true');\n }\n }\n\n /**\n * Handles attribute changes for ARIA sync.\n * @param {string} name\n * @param {string|null} oldValue\n * @param {string|null} newValue\n */\n attributeChangedCallback(name, oldValue, newValue) {\n if (super.attributeChangedCallback) {\n super.attributeChangedCallback(name, oldValue, newValue);\n }\n\n if (name === 'label' && oldValue !== newValue) {\n this.syncAria();\n }\n }\n}\n","import Icon from './icon.element.js';\n\nexport default Icon;\n\nIcon.define('wje-icon', Icon);\n"],"names":[],"mappings":"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"}
package/dist/localize.js CHANGED
@@ -35,11 +35,24 @@ class LocalizerDefault {
35
35
  return langMap ? langMap[key] || key : key;
36
36
  }
37
37
  /**
38
- * Translates a key and interpolates placeholders in the format {placeholder}.
39
- * Missing params are kept as-is so untranslated placeholders stay visible.
38
+ * Translates a key and then interpolates placeholders in the format {placeholder}.
39
+ * The method first resolves the base text through `translate()`. If the result is not a string,
40
+ * it is returned unchanged. For string results, every placeholder wrapped in curly braces is matched,
41
+ * the token name is trimmed, and the value is looked up in the `params` object.
42
+ * When a matching param exists, its value is converted to a string and inserted into the translation.
43
+ * Missing or `null` params are left in their original `{placeholder}` form so unresolved tokens stay visible.
40
44
  * @param {string} key The translation key.
41
45
  * @param {object} [params] Key-value map used for interpolation. Defaults to an empty object.
42
46
  * @returns {string} Localized string with interpolated params.
47
+ * @example
48
+ * // If the translation is:
49
+ * // "personalSettings.settings.synchronization.checkbox.exportApprovedAbsence":
50
+ * // "Exportuj schválené absencie do {calendar}"
51
+ * this.localizer.translateWithParams(
52
+ * 'personalSettings.settings.synchronization.checkbox.exportApprovedAbsence',
53
+ * { calendar: 'Google kalendára' },
54
+ * );
55
+ * // Returns: 'Exportuj schválené absencie do Google kalendára'
43
56
  */
44
57
  translateWithParams(key, params = {}) {
45
58
  const translated = this.translate(key);
@@ -1 +1 @@
1
- {"version":3,"file":"localize.js","sources":["../packages/localize/localize.js","../packages/utils/localize.js"],"sourcesContent":["// export const translations = new Map();\n\nexport class LocalizerDefault {\n constructor(element) {\n this.element = element;\n\n this.lang = this.element?.lang || document.documentElement?.lang || 'en-GB';\n this.dir = this.element?.dir || document.documentElement?.dir || 'ltr';\n this.currentLang = 'en-GB';\n\n this.setLanguage();\n }\n\n get languages() {\n return window.translations;\n }\n\n // Nastavenie aktuálneho jazyka\n setLanguage() {\n if (this.languages?.has(this.lang)) {\n this.currentLang = this.lang;\n } else {\n console.error(`Language \"${this.lang}\" not loaded.`);\n }\n }\n\n convertLangCode = (lang) => lang.replace(\"-\", \"_\").replace(/_([a-z]{2})$/, (_, code) => `_${code.toUpperCase()}`);\n\n /**\n * Translates a given translation key based on the currently selected language.\n * @param {string} key The key representing the text to be translated.\n * @returns {string} The translated text if available; otherwise, returns the original key.\n */\n translate(key) {\n const langMap = this.languages?.get(this.currentLang);\n if (!langMap) return key;\n return langMap ? langMap[key] || key : key;\n }\n\n /**\n * Translates a key and interpolates placeholders in the format {placeholder}.\n * Missing params are kept as-is so untranslated placeholders stay visible.\n * @param {string} key The translation key.\n * @param {object} [params] Key-value map used for interpolation. Defaults to an empty object.\n * @returns {string} Localized string with interpolated params.\n */\n translateWithParams(key, params = {}) {\n const translated = this.translate(key);\n\n if (typeof translated !== 'string') return translated;\n\n return translated.replace(/\\{([^{}]+)\\}/g, (match, token) => {\n const value = params[token.trim()];\n return value === undefined || value === null ? match : String(value);\n });\n }\n\n /**\n * Translates a key into a localized string based on the provided count and pluralization type.\n * @param {string} key The base translation key to be used for fetching the localized string.\n * @param {number} [count] The count value used to determine the pluralization form. Defaults to 0.\n * @param {string} [type] The type of pluralization to use, such as 'cardinal' or 'ordinal'. Defaults to 'cardinal'.\n * @returns {string} The translated string, adapted to the pluralization rules and count.\n */\n translatePlural(key, count = 0, type = 'cardinal') {\n const plural = new Intl.PluralRules(this.currentLang, { type });\n const k = `${key}.${plural.select(count)}`;\n const t = this.translate(k);\n if (t !== k) return t;\n return this.translate(`${key}.other`);\n }\n\n /**\n * Formats a number according to the specified locale and formatting options.\n * @param {number} number The numeric value to format.\n * @param {object} options An object containing formatting options for the number.\n * @returns {string} The formatted number as a string.\n */\n formatNumber(number, options) {\n return new Intl.NumberFormat(this.currentLang, options).format(number);\n }\n\n /**\n * Formats a given date based on the specified options and the current language setting.\n * @param {string|Date|number} date The date to format. Can be a Date object, a timestamp, or a date string.\n * @param {object} options The formatting options to customize the output, as supported by Intl.DateTimeFormat.\n * @returns {string} The formatted date string based on the specified options and current language.\n */\n formatDate(date, options) {\n return new Intl.DateTimeFormat(this.currentLang, options).format(new Date(date));\n }\n\n /**\n * Formats a relative time string based on a given language, value, unit, and formatting options.\n * @param {string} lang The language to use for formatting. Defaults to `this.currentLang` if not provided.\n * @param {number} value The numerical value to format, representing the time difference.\n * @param {string} [unit] The unit of time to use (e.g., \"second\", \"minute\", \"hour\", \"day\", \"week\", \"month\", \"year\").\n * @param {object} [options] An object containing formatting options, such as the style for the numeric representation.\n * @returns {string} The formatted relative time string in the specified language.\n */\n relativeTime(lang, value = 0, unit = 'day', options = { numeric: 'auto' }) {\n lang = lang || this.currentLang;\n return new Intl.RelativeTimeFormat(lang, options).format(value, unit);\n }\n}\n\nexport function registerTranslation(...translation) {\n translation.forEach((t) => {\n if (!t.code) {\n console.error(\"Translation object is missing 'code' property:\", t);\n return;\n }\n\n const code = t.code.toLowerCase();\n if (window.translations.has(code)) {\n window.translations.set(code, { ...window.translations.get(code), ...t });\n } else {\n window.translations.set(code, t);\n }\n });\n}\n","import { LocalizerDefault, registerTranslation } from '../localize/localize.js';\n\nexport class Localizer extends LocalizerDefault {\n constructor(element) {\n super(element);\n }\n static registerTranslation(...translation) {\n registerTranslation(...translation);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localize.js","sources":["../packages/localize/localize.js","../packages/utils/localize.js"],"sourcesContent":["// export const translations = new Map();\n\nexport class LocalizerDefault {\n constructor(element) {\n this.element = element;\n\n this.lang = this.element?.lang || document.documentElement?.lang || 'en-GB';\n this.dir = this.element?.dir || document.documentElement?.dir || 'ltr';\n this.currentLang = 'en-GB';\n\n this.setLanguage();\n }\n\n get languages() {\n return window.translations;\n }\n\n // Nastavenie aktuálneho jazyka\n setLanguage() {\n if (this.languages?.has(this.lang)) {\n this.currentLang = this.lang;\n } else {\n console.error(`Language \"${this.lang}\" not loaded.`);\n }\n }\n\n convertLangCode = (lang) => lang.replace(\"-\", \"_\").replace(/_([a-z]{2})$/, (_, code) => `_${code.toUpperCase()}`);\n\n /**\n * Translates a given translation key based on the currently selected language.\n * @param {string} key The key representing the text to be translated.\n * @returns {string} The translated text if available; otherwise, returns the original key.\n */\n translate(key) {\n const langMap = this.languages?.get(this.currentLang);\n if (!langMap) return key;\n return langMap ? langMap[key] || key : key;\n }\n\n /**\n * Translates a key and then interpolates placeholders in the format {placeholder}.\n * The method first resolves the base text through `translate()`. If the result is not a string,\n * it is returned unchanged. For string results, every placeholder wrapped in curly braces is matched,\n * the token name is trimmed, and the value is looked up in the `params` object.\n * When a matching param exists, its value is converted to a string and inserted into the translation.\n * Missing or `null` params are left in their original `{placeholder}` form so unresolved tokens stay visible.\n * @param {string} key The translation key.\n * @param {object} [params] Key-value map used for interpolation. Defaults to an empty object.\n * @returns {string} Localized string with interpolated params.\n * @example\n * // If the translation is:\n * // \"personalSettings.settings.synchronization.checkbox.exportApprovedAbsence\":\n * // \"Exportuj schválené absencie do {calendar}\"\n * this.localizer.translateWithParams(\n * 'personalSettings.settings.synchronization.checkbox.exportApprovedAbsence',\n * { calendar: 'Google kalendára' },\n * );\n * // Returns: 'Exportuj schválené absencie do Google kalendára'\n */\n translateWithParams(key, params = {}) {\n const translated = this.translate(key);\n\n if (typeof translated !== 'string') return translated;\n\n return translated.replace(/\\{([^{}]+)\\}/g, (match, token) => {\n const value = params[token.trim()];\n return value === undefined || value === null ? match : String(value);\n });\n }\n\n /**\n * Translates a key into a localized string based on the provided count and pluralization type.\n * @param {string} key The base translation key to be used for fetching the localized string.\n * @param {number} [count] The count value used to determine the pluralization form. Defaults to 0.\n * @param {string} [type] The type of pluralization to use, such as 'cardinal' or 'ordinal'. Defaults to 'cardinal'.\n * @returns {string} The translated string, adapted to the pluralization rules and count.\n */\n translatePlural(key, count = 0, type = 'cardinal') {\n const plural = new Intl.PluralRules(this.currentLang, { type });\n const k = `${key}.${plural.select(count)}`;\n const t = this.translate(k);\n if (t !== k) return t;\n return this.translate(`${key}.other`);\n }\n\n /**\n * Formats a number according to the specified locale and formatting options.\n * @param {number} number The numeric value to format.\n * @param {object} options An object containing formatting options for the number.\n * @returns {string} The formatted number as a string.\n */\n formatNumber(number, options) {\n return new Intl.NumberFormat(this.currentLang, options).format(number);\n }\n\n /**\n * Formats a given date based on the specified options and the current language setting.\n * @param {string|Date|number} date The date to format. Can be a Date object, a timestamp, or a date string.\n * @param {object} options The formatting options to customize the output, as supported by Intl.DateTimeFormat.\n * @returns {string} The formatted date string based on the specified options and current language.\n */\n formatDate(date, options) {\n return new Intl.DateTimeFormat(this.currentLang, options).format(new Date(date));\n }\n\n /**\n * Formats a relative time string based on a given language, value, unit, and formatting options.\n * @param {string} lang The language to use for formatting. Defaults to `this.currentLang` if not provided.\n * @param {number} value The numerical value to format, representing the time difference.\n * @param {string} [unit] The unit of time to use (e.g., \"second\", \"minute\", \"hour\", \"day\", \"week\", \"month\", \"year\").\n * @param {object} [options] An object containing formatting options, such as the style for the numeric representation.\n * @returns {string} The formatted relative time string in the specified language.\n */\n relativeTime(lang, value = 0, unit = 'day', options = { numeric: 'auto' }) {\n lang = lang || this.currentLang;\n return new Intl.RelativeTimeFormat(lang, options).format(value, unit);\n }\n}\n\nexport function registerTranslation(...translation) {\n translation.forEach((t) => {\n if (!t.code) {\n console.error(\"Translation object is missing 'code' property:\", t);\n return;\n }\n\n const code = t.code.toLowerCase();\n if (window.translations.has(code)) {\n window.translations.set(code, { ...window.translations.get(code), ...t });\n } else {\n window.translations.set(code, t);\n }\n });\n}\n","import { LocalizerDefault, registerTranslation } from '../localize/localize.js';\n\nexport class Localizer extends LocalizerDefault {\n constructor(element) {\n super(element);\n }\n static registerTranslation(...translation) {\n registerTranslation(...translation);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -15,11 +15,24 @@ export class LocalizerDefault {
15
15
  */
16
16
  translate(key: string): string;
17
17
  /**
18
- * Translates a key and interpolates placeholders in the format {placeholder}.
19
- * Missing params are kept as-is so untranslated placeholders stay visible.
18
+ * Translates a key and then interpolates placeholders in the format {placeholder}.
19
+ * The method first resolves the base text through `translate()`. If the result is not a string,
20
+ * it is returned unchanged. For string results, every placeholder wrapped in curly braces is matched,
21
+ * the token name is trimmed, and the value is looked up in the `params` object.
22
+ * When a matching param exists, its value is converted to a string and inserted into the translation.
23
+ * Missing or `null` params are left in their original `{placeholder}` form so unresolved tokens stay visible.
20
24
  * @param {string} key The translation key.
21
25
  * @param {object} [params] Key-value map used for interpolation. Defaults to an empty object.
22
26
  * @returns {string} Localized string with interpolated params.
27
+ * @example
28
+ * // If the translation is:
29
+ * // "personalSettings.settings.synchronization.checkbox.exportApprovedAbsence":
30
+ * // "Exportuj schválené absencie do {calendar}"
31
+ * this.localizer.translateWithParams(
32
+ * 'personalSettings.settings.synchronization.checkbox.exportApprovedAbsence',
33
+ * { calendar: 'Google kalendára' },
34
+ * );
35
+ * // Returns: 'Exportuj schválené absencie do Google kalendára'
23
36
  */
24
37
  translateWithParams(key: string, params?: object): string;
25
38
  /**
@@ -15,4 +15,5 @@ export const enGb: {
15
15
  'wj.pagination.prev': string;
16
16
  'wj.pagination.next': string;
17
17
  'wj.pagination.last': string;
18
+ 'wj.select.empty': string;
18
19
  };
@@ -15,4 +15,5 @@ export const skSk: {
15
15
  'wj.pagination.prev': string;
16
16
  'wj.pagination.next': string;
17
17
  'wj.pagination.last': string;
18
+ 'wj.select.empty': string;
18
19
  };
@@ -1,25 +1,25 @@
1
1
  /**
2
- * PermissionsApi is a utility class for managing permissions.
2
+ * Permissions is a utility class for managing permissions.
3
3
  * It allows setting, retrieving, and checking permissions stored in the browser's local storage.
4
4
  */
5
5
  export class Permissions {
6
6
  static _permissionKey: string;
7
7
  /**
8
- * Sets the permission key for the PermissionsApi.
8
+ * Sets the permission key for the Permissions utility.
9
9
  * The key is stored internally and defaults to 'permissions' if no value is provided.
10
10
  * @param {string} value The key to set for permissions. If no value is provided, the default is 'permissions'.
11
11
  */
12
12
  static set permissionKey(value: string);
13
13
  /**
14
- * Retrieves the permission key used for accessing the permissions API.
15
- * @returns {string} The permission key associated with the PermissionsApi.
14
+ * Retrieves the permission key used for accessing the permissions utility.
15
+ * @returns {string} The permission key associated with the Permissions utility.
16
16
  */
17
17
  static get permissionKey(): string;
18
18
  /**
19
19
  * Sets the permissions by storing them in the local storage.
20
- * @param {object} value The permissions object to be stored.
20
+ * @param {Array<string>} value The permissions array to be stored.
21
21
  */
22
- static set permissions(value: object);
22
+ static set permissions(value: Array<string>);
23
23
  /**
24
24
  * Retrieves the list of permissions stored in the browser's local storage.
25
25
  * @returns {Array} An array of permissions. If no permissions are found, returns an empty array.
@@ -32,9 +32,9 @@ export class Permissions {
32
32
  */
33
33
  static includesKey(key: string): boolean;
34
34
  /**
35
- * Checks if at least one of the given permissions is fulfilled, based on the permissions available in `PermissionsApi`.
36
- * @param {Array<string>} permissions The list of permissions to check against the permissions available in `PermissionsApi`.
37
- * @returns {boolean} Returns `true` if any of the given permissions match the permissions available in `PermissionsApi`, otherwise returns `false`.
35
+ * Checks if at least one of the given permissions is fulfilled, based on the permissions available in `Permissions`.
36
+ * @param {Array<string>} permissions The list of permissions to check against the permissions available in `Permissions`.
37
+ * @returns {boolean} Returns `true` if any of the given permissions match the permissions available in `Permissions`, otherwise returns `false`.
38
38
  */
39
39
  static isPermissionFulfilled(permissions: Array<string>): boolean;
40
40
  }
@@ -4,12 +4,9 @@ import { default as WJElement } from '../wje-element/element.js';
4
4
  * @documentation https://elements.webjet.sk/components/accordion
5
5
  * @status stable
6
6
  * @augments WJElement
7
- * @attribute {boolean} multiple - The multiple attribute for the accordion.
8
- * @attribute {number} index - The index attribute for the accordion.
9
- * @attribute {boolean} disabled - The disabled attribute for the accordion.
10
- * @attribute {boolean} expanded - The expanded attribute for the accordion.
11
- * @slot - The accordion main content.
12
- * //@fires [wje-accordion-item:open] The event fired when the accordion item is opened.
7
+ * @attribute {boolean} multiple - Allows multiple accordion items to stay expanded at the same time.
8
+ * @attribute {number} index - Sets which child accordion item should start expanded based on DOM order.
9
+ * @slot default - Slot for direct `wje-accordion-item` children.
13
10
  * @tag wje-accordion
14
11
  */
15
12
  export default class Accordion extends WJElement {
@@ -4,8 +4,29 @@ import { default as WJElement } from '../wje-element/element.js';
4
4
  * @documentation https://elements.webjet.sk/components/accordion-item
5
5
  * @status stable
6
6
  * @augments WJElement
7
- * @slot - The accordion item main content.
8
- * @tag wje-accordion
7
+ * @attribute {string} color - Applies a contextual color variant such as `primary`, `success`, `danger`, `warning`, `info`, or `complete`.
8
+ * @slot headline - Slot for the clickable accordion headline content.
9
+ * @slot description - Slot for supporting text shown below the headline.
10
+ * @slot toggle - Slot for a custom toggle icon or toggle content.
11
+ * @slot content - Slot for the expandable panel body.
12
+ * @csspart native - The wrapper of the whole accordion item.
13
+ * @csspart headline - The clickable headline area.
14
+ * @csspart description - The description slot container inside the headline.
15
+ * @csspart toggle - The toggle slot container and fallback chevron area.
16
+ * @csspart content - The expandable content panel.
17
+ * @cssproperty [--wje-accordion-background=var(--wje-color-contrast-0)] - Background color of the collapsed item wrapper.
18
+ * @cssproperty [--wje-accordion-border=var(--wje-color-contrast-0)] - Border color of the collapsed item wrapper.
19
+ * @cssproperty [--wje-accordion-border-radius=var(--wje-border-radius-large)] - Border radius of the item wrapper.
20
+ * @cssproperty [--wje-accordion-background-hover=var(--wje-color-contrast-1)] - Background color used when the headline is hovered.
21
+ * @cssproperty [--wje-accordion-border-hover=var(--wje-color-contrast-2)] - Border color used when the headline is hovered.
22
+ * @cssproperty [--wje-accordion-background-expanded=var(--wje-color-contrast-0)] - Background color of the expanded item wrapper.
23
+ * @cssproperty [--wje-accordion-border-expanded=var(--wje-color-contrast-0)] - Border color of the expanded item wrapper.
24
+ * @cssproperty [--wje-accordion-headline-color=var(--wje-color-contrast-11)] - Text color of the headline area.
25
+ * @cssproperty [--wje-accordion-content-color=var(--wje-color-contrast-6)] - Text color of the expandable content area.
26
+ * @cssproperty [--wje-accordion-marker-rotate=0deg] - Rotation applied to the toggle marker icon.
27
+ * @fires wje-accordion-item:open - Dispatched when the item is expanded.
28
+ * @fires wje-accordion-item:close - Dispatched when the item is collapsed.
29
+ * @tag wje-accordion-item
9
30
  */
10
31
  export default class AccordionItem extends WJElement {
11
32
  static _instanceId: number;
@@ -33,11 +54,11 @@ export default class AccordionItem extends WJElement {
33
54
  */
34
55
  afterDraw(): void;
35
56
  /**
36
- * Method to handle the attribute changes.
57
+ * Collapses the accordion item and updates the headline ARIA state.
37
58
  */
38
- collapse: () => void;
59
+ collapse(): void;
39
60
  /**
40
- * Method to handle the attribute changes.
61
+ * Expands the accordion item and updates the headline ARIA state.
41
62
  */
42
- expand: () => void;
63
+ expand(): void;
43
64
  }
@@ -4,8 +4,16 @@ import { default as WJElement } from '../wje-element/element.js';
4
4
  * @documentation https://elements.webjet.sk/components/animation
5
5
  * @status stable
6
6
  * @augments WJElement
7
+ * @attribute {string} name - The Animate.css animation name played on the slotted element.
8
+ * @attribute {number} duration - The animation playback duration in milliseconds.
9
+ * @attribute {number} delay - The delay before the animation starts.
10
+ * @attribute {number} endDelay - The delay applied after the animation completes.
11
+ * @attribute {string} fill - The fill mode used by the animation playback.
12
+ * @attribute {string|number} iterations - The number of animation repetitions.
13
+ * @attribute {number} iterationStart - The starting offset for the first animation iteration.
14
+ * @attribute {string} direction - The playback direction of the animation.
15
+ * @attribute {string} easing - The easing function used by the animation playback.
7
16
  * @slot - The animation main content.
8
- * @cssproperty --size - The size of the avatar.
9
17
  * @tag wje-animation
10
18
  */
11
19
  export default class Animation extends WJElement {
@@ -16,7 +24,7 @@ export default class Animation extends WJElement {
16
24
  static get cssStyleSheet(): object;
17
25
  /**
18
26
  * Getter for the observed attributes.
19
- * @returns {Array} An array containing the name of the observed attribute.
27
+ * @returns {Array} An array containing the names of the observed attributes.
20
28
  */
21
29
  static get observedAttributes(): any[];
22
30
  _animations: any[];
@@ -4,12 +4,16 @@ import { default as WJElement } from '../wje-element/element.js';
4
4
  * @documentation https://elements.webjet.sk/components/aside
5
5
  * @status stable
6
6
  * @augments WJElement
7
- * @slot - The aside main content.
8
- * @cssproperty --wje-aside-width;
9
- * @cssproperty --wje-aside-top;
10
- * @cssproperty --wje-aside-border-color: var(--wje-border-color);
11
- * @cssproperty --wje-aside-border-width;
12
- * @cssproperty --wje-aside-border-style;
7
+ * @attribute {string} width - Sets the width of the aside column, typically through a CSS length or design token.
8
+ * @attribute {string} top - Sets the top offset used together with the `fixed` layout mode.
9
+ * @attribute {boolean} fixed - Pins the aside in a fixed desktop position instead of keeping it in normal flow.
10
+ * @attribute {string} variant - Selects an alternate layout variant such as the mobile `top-start` drawer style.
11
+ * @slot default - Slot for the aside content.
12
+ * @cssproperty [--wje-aside-width] - Controls the width of the aside column.
13
+ * @cssproperty [--wje-aside-top] - Controls the top offset of a fixed aside.
14
+ * @cssproperty [--wje-aside-border-color=var(--wje-border-color)] - Controls the border color of the aside.
15
+ * @cssproperty [--wje-aside-border-width] - Controls the border width of the aside.
16
+ * @cssproperty [--wje-aside-border-style] - Controls the border style of the aside.
13
17
  * @tag wje-aside
14
18
  */
15
19
  export default class Aside extends WJElement {
@@ -4,18 +4,26 @@ import { default as WJElement } from '../wje-element/element.js';
4
4
  * @documentation https://elements.webjet.sk/components/avatar
5
5
  * @status stable
6
6
  * @augments WJElement
7
- * @slot - The avatar main content.
7
+ * @attribute {boolean} initials - Renders generated initials from `label` instead of the default slotted content.
8
+ * @attribute {string} label - Provides the source text for generated initials and the accessible label of the avatar.
9
+ * @attribute {string} size - Selects a predefined avatar size such as `small`, `medium`, `normal`, `large`, or larger variants.
10
+ * @attribute {string} status-placement - Positions the `status` slot on one of the avatar corners.
11
+ * @slot default - Slot for the main avatar content, typically an image.
12
+ * @slot icon - Slot for an icon rendered inside the avatar.
13
+ * @slot status - Slot for a status badge or indicator positioned on the avatar edge.
14
+ * @slot secondary - Slot for additional secondary content rendered with the avatar.
8
15
  * @csspart native - The component's native wrapper.
9
- * @cssproperty --wje-avatar-width;
10
- * @cssproperty --wje-avatar-height;
11
- * @cssproperty --wje-avatar-font-size;
12
- * @cssproperty --wje-avatar-font-weight;
13
- * @cssproperty --wje-avatar-color;
14
- * @cssproperty --wje-avatar-background-color;
15
- * @cssproperty --wje-avatar-border-radius;
16
- * @cssproperty --wje-avatar-border-color;
17
- * @cssproperty --wje-avatar-border-width;
18
- * @cssproperty --wje-avatar-border-style;
16
+ * @csspart status - The positioned slot container for status content.
17
+ * @csspart secondary - The slot container for secondary avatar content.
18
+ * @cssproperty [--wje-avatar-size] - Controls the overall rendered size of the avatar shell.
19
+ * @cssproperty [--wje-avatar-font-size] - Controls the font size used for initials and text content.
20
+ * @cssproperty [--wje-avatar-font-weight] - Controls the font weight used for initials and text content.
21
+ * @cssproperty [--wje-avatar-color] - Controls the text color inside the avatar.
22
+ * @cssproperty [--wje-avatar-background-color] - Controls the background color of the avatar surface.
23
+ * @cssproperty [--wje-avatar-border-radius] - Controls the avatar border radius.
24
+ * @cssproperty [--wje-avatar-border-color] - Controls the avatar border color when a border is applied.
25
+ * @cssproperty [--wje-avatar-border-width] - Controls the avatar border width when a border is applied.
26
+ * @cssproperty [--wje-avatar-border-style] - Controls the avatar border style when a border is applied.
19
27
  * @tag wje-avatar
20
28
  */
21
29
  export default class Avatar extends WJElement {
@@ -5,7 +5,8 @@ import { default as WJElement } from '../wje-element/element.js';
5
5
  * @status stable
6
6
  * @augments WJElement
7
7
  * @slot - The carousel main content.
8
- * @cssproperty [--wje-carousel-size=100%] - Size of the carousel component;
8
+ * @cssproperty [--wje-carousel-size=100%] - Effective size of one carousel item.
9
+ * @cssproperty [--wje-carousel-gap=0.5rem] - Gap between carousel items.
9
10
  */
10
11
  export default class Carousel extends WJElement {
11
12
  /**
@@ -49,6 +50,11 @@ export default class Carousel extends WJElement {
49
50
  * @returns {boolean}
50
51
  */
51
52
  get loop(): boolean;
53
+ /**
54
+ * Continuous loop attribute.
55
+ * @returns {boolean}
56
+ */
57
+ get continuousLoop(): boolean;
52
58
  /**
53
59
  * Before draw method for the Carousel.
54
60
  */
@@ -66,9 +72,25 @@ export default class Carousel extends WJElement {
66
72
  */
67
73
  afterDraw(): void;
68
74
  /**
69
- * Sync `activeSlide` to the slide whose center is closest to the container center.
75
+ * Sync `activeSlide` to the slide whose leading edge is closest to the snap start.
76
+ */
77
+ syncActiveToSnapStart(): void;
78
+ /**
79
+ * Syncs computed CSS variables derived from `slide-per-page`.
80
+ */
81
+ syncSlideMetrics(): void;
82
+ /**
83
+ * Returns the inline scroll padding used by the snap area.
84
+ * @returns {number}
70
85
  */
71
- syncActiveToCenter(): void;
86
+ getScrollPaddingInlineStart(): number;
87
+ /**
88
+ * Returns the interaction scroll behavior for UI controls.
89
+ * Continuous multi-slide loops use instant snapping to avoid blank edge states
90
+ * while the browser is still animating a previous smooth scroll.
91
+ * @returns {ScrollBehavior|string}
92
+ */
93
+ getControlBehavior(): ScrollBehavior | string;
72
94
  /**
73
95
  * Sets up the IntersectionObserver for the Carousel.
74
96
  */
@@ -83,6 +105,11 @@ export default class Carousel extends WJElement {
83
105
  * @param next
84
106
  */
85
107
  goToSlide(index: any, behavior?: string, next?: boolean): void;
108
+ /**
109
+ * Sets the active class on the currently targeted visual slide and removes it elsewhere.
110
+ * @param {number} vIndex
111
+ */
112
+ setActiveVisualSlide(vIndex: number): void;
86
113
  /**
87
114
  * Syncs ARIA attributes on the carousel and slides.
88
115
  */
@@ -91,6 +118,30 @@ export default class Carousel extends WJElement {
91
118
  * Clones the first and last items.
92
119
  */
93
120
  cloneFirstAndLastItems(): void;
121
+ /**
122
+ * Creates a sanitized loop clone that does not inherit transient render state
123
+ * such as inline `visibility: hidden` from the source slide.
124
+ * @param {HTMLElement} item
125
+ * @returns {HTMLElement}
126
+ */
127
+ createLoopClone(item: HTMLElement): HTMLElement;
128
+ /**
129
+ * Removes loop clones so they can be rebuilt for the current configuration.
130
+ */
131
+ removeLoopClones(): void;
132
+ /**
133
+ * Returns how many slides should be cloned on each side when loop is enabled.
134
+ * @param {number} totalSlides
135
+ * @returns {number}
136
+ */
137
+ getLoopCloneCount(totalSlides?: number): number;
138
+ /**
139
+ * Scrolls the carousel to a visual slide index.
140
+ * @param {number} vIndex
141
+ * @param {ScrollBehavior|string} behavior
142
+ */
143
+ scrollToVisualIndex(vIndex: number, behavior?: ScrollBehavior | string): void;
144
+ snapRestoreFrame: any;
94
145
  /**
95
146
  * Goes to the next slide.
96
147
  */
@@ -145,6 +196,30 @@ export default class Carousel extends WJElement {
145
196
  getVisualIndexForLogical(index: any): any;
146
197
  /** Maps visual index -> logical index (handles clones at 0 and last when loop=true) */
147
198
  getLogicalIndexForVisual(vIndex: any): any;
199
+ /**
200
+ * Returns the maximum logical slide index that can still render a full viewport.
201
+ * @param {number} totalSlides
202
+ * @returns {number}
203
+ */
204
+ getMaxVisibleStartIndex(totalSlides?: number): number;
205
+ /**
206
+ * Normalizes a logical index for the active loop mode.
207
+ * @param {number} index
208
+ * @param {number} totalSlides
209
+ * @returns {number}
210
+ */
211
+ normalizeLoopIndex(index: number, totalSlides?: number): number;
212
+ /**
213
+ * Returns how many logical positions are reachable for the current loop mode.
214
+ * @param {number} totalSlides
215
+ * @returns {number}
216
+ */
217
+ getLoopLogicalCount(totalSlides?: number): number;
218
+ /**
219
+ * Returns the pagination indexes for the current carousel mode.
220
+ * @returns {number[]}
221
+ */
222
+ getPaginationIndexes(): number[];
148
223
  /**
149
224
  * Goes to the slide.
150
225
  * @returns {boolean}
@@ -31,8 +31,13 @@ export default class CarouselItem extends WJElement {
31
31
  * @returns {DocumentFragment}
32
32
  */
33
33
  draw(): DocumentFragment;
34
+ defaultSlot: HTMLSlotElement;
34
35
  /**
35
36
  * After draw event for the CarouselItem element.
36
37
  */
37
38
  afterDraw(): void;
39
+ /**
40
+ * Keeps a simple layout hint for single-wrapper content.
41
+ */
42
+ syncContentLayoutMode(): void;
38
43
  }