UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

1 lines 628 kB
{"version":3,"file":"igniteui-angular-core.mjs","sources":["../../../projects/igniteui-angular/core/src/core/navigation/nav.service.ts","../../../projects/igniteui-angular/core/src/core/navigation/directives.ts","../../../projects/igniteui-angular/core/src/core/dates/dateRange.ts","../../../projects/igniteui-angular/core/src/core/enums.ts","../../../projects/igniteui-angular/core/src/core/setImmediate.ts","../../../projects/igniteui-angular/core/src/core/utils.ts","../../../projects/igniteui-angular/core/src/core/selection.ts","../../../projects/igniteui-angular/core/src/core/edit-provider.ts","../../../projects/igniteui-angular/core/src/core/touch.ts","../../../projects/igniteui-angular/core/src/core/touch-annotations.ts","../../../projects/igniteui-angular/core/src/grid-column-actions/token.ts","../../../projects/igniteui-angular/core/src/date-common/picker-icons.common.ts","../../../projects/igniteui-angular/core/src/date-common/types.ts","../../../projects/igniteui-angular/core/src/date-common/date-parts.ts","../../../projects/igniteui-angular/core/src/data-operations/grid-types.ts","../../../projects/igniteui-angular/core/src/date-common/util/date-time.util.ts","../../../projects/igniteui-angular/core/src/date-common/util/model.ts","../../../projects/igniteui-angular/core/src/date-common/util/helpers.ts","../../../projects/igniteui-angular/core/src/data-operations/data-clone-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/filtering-expression.interface.ts","../../../projects/igniteui-angular/core/src/data-operations/filtering-condition.ts","../../../projects/igniteui-angular/core/src/data-operations/expressions-tree-util.ts","../../../projects/igniteui-angular/core/src/data-operations/filtering-expressions-tree.ts","../../../projects/igniteui-angular/core/src/data-operations/paging-state.interface.ts","../../../projects/igniteui-angular/core/src/services/transaction/transaction.ts","../../../projects/igniteui-angular/core/src/data-operations/sorting-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/operations.ts","../../../projects/igniteui-angular/core/src/data-operations/grid-sorting-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/merge-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/data-util.ts","../../../projects/igniteui-angular/core/src/data-operations/filtering-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/tree-grid-filtering-strategy.ts","../../../projects/igniteui-angular/core/src/data-operations/groupby-record.interface.ts","../../../projects/igniteui-angular/core/src/services/animation/angular-animation-player.ts","../../../projects/igniteui-angular/core/src/services/animation/angular-animation-service.ts","../../../projects/igniteui-angular/core/src/services/direction/directionality.ts","../../../projects/igniteui-angular/core/src/services/overlay/utilities.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/connected-positioning-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/base-fit-position-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/auto-position-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/global-position-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/container-position-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/elastic-position-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/scroll-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/NoOpScrollStrategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/overlay.ts","../../../projects/igniteui-angular/core/src/services/overlay/position/index.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/absolute-scroll-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/block-scroll-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/close-scroll-strategy.ts","../../../projects/igniteui-angular/core/src/services/overlay/scroll/index.ts","../../../projects/igniteui-angular/core/src/services/transaction/base-transaction.ts","../../../projects/igniteui-angular/core/src/services/transaction/igx-transaction.ts","../../../projects/igniteui-angular/core/src/services/transaction/igx-hierarchical-transaction.ts","../../../projects/igniteui-angular/core/src/services/transaction/transaction-factory.service.ts","../../../projects/igniteui-angular/core/src/services/theme/theme.token.ts","../../../projects/igniteui-angular/core/src/services/public_api.ts","../../../projects/igniteui-angular/core/src/performance.service.ts","../../../projects/igniteui-angular/core/src/core/i18n/action-strip-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/banner-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/calendar-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/carousel-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/chip-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/combo-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/date-picker-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/date-range-picker-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/grid-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/input-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/list-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/paginator-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/query-builder-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/time-picker-resources.ts","../../../projects/igniteui-angular/core/src/core/i18n/tree-resources.ts","../../../projects/igniteui-angular/core/src/core/global-types.ts","../../../projects/igniteui-angular/core/src/public_api.ts","../../../projects/igniteui-angular/core/src/igniteui-angular-core.ts"],"sourcesContent":["import { IToggleView } from './IToggleView';\nimport { Injectable } from '@angular/core';\n\n/**\n * Common service to be injected between components where those implementing common\n * ToggleView interface can register and toggle directives can call their methods.\n * TODO: Track currently active? Events?\n */\n@Injectable({ providedIn: 'root' })\nexport class IgxNavigationService {\n private navs: { [id: string]: IToggleView };\n\n constructor() {\n this.navs = {};\n }\n\n public add(id: string, navItem: IToggleView) {\n this.navs[id] = navItem;\n }\n\n public remove(id: string) {\n delete this.navs[id];\n }\n\n public get(id: string): IToggleView {\n if (id) {\n return this.navs[id];\n }\n }\n\n public toggle(id: string, ...args) {\n if (this.navs[id]) {\n return this.navs[id].toggle(...args);\n }\n }\n public open(id: string, ...args) {\n if (this.navs[id]) {\n return this.navs[id].open(...args);\n }\n }\n public close(id: string, ...args) {\n if (this.navs[id]) {\n return this.navs[id].close(...args);\n }\n }\n}\n","import { Directive, HostListener, Input, inject } from '@angular/core';\nimport { IgxNavigationService } from './nav.service';\n\n/**\n * Directive that can toggle targets through provided NavigationService.\n *\n * Usage:\n * ```\n * <button type=\"button\" igxNavToggle=\"ID\">Toggle</button>\n * ```\n * Where the `ID` matches the ID of compatible `IToggleView` component.\n */\n@Directive({\n selector: '[igxNavToggle]',\n standalone: true\n})\nexport class IgxNavigationToggleDirective {\n @Input('igxNavToggle') private target;\n\n public state: IgxNavigationService;\n\n constructor() {\n const nav = inject(IgxNavigationService);\n\n this.state = nav;\n }\n\n @HostListener('click')\n public toggleNavigationDrawer() {\n this.state.toggle(this.target, true);\n }\n}\n\n/**\n * Directive that can close targets through provided NavigationService.\n *\n * Usage:\n * ```\n * <button type=\"button\" igxNavClose=\"ID\">Close</button>\n * ```\n * Where the `ID` matches the ID of compatible `IToggleView` component.\n */\n@Directive({\n selector: '[igxNavClose]',\n standalone: true\n})\nexport class IgxNavigationCloseDirective {\n @Input('igxNavClose') private target;\n\n public state: IgxNavigationService;\n\n constructor() {\n const nav = inject(IgxNavigationService);\n\n this.state = nav;\n }\n\n @HostListener('click')\n public closeNavigationDrawer() {\n this.state.close(this.target, true);\n }\n}\n","export interface DateRangeDescriptor {\n type: DateRangeType;\n dateRange?: Date[];\n}\n\nexport enum DateRangeType {\n After,\n Before,\n Between,\n Specific,\n Weekdays,\n Weekends\n}\n","/**\n * @hidden @internal\n *\n * Enumeration representing the possible predefined size options of the grid.\n * - Small: This is the smallest size with 32px row height. Left and Right paddings are 12px. Minimal column width is 56px.\n * - Medium: This is the middle size with 40px row height. Left and Right paddings are 16px. Minimal column width is 64px.\n * - Large: this is the default Grid size with the lowest intense and row height equal to 50px. Left and Right paddings are 24px. Minimal column width is 80px.\n */\nexport const Size = {\n Small: '1',\n Medium: '2',\n Large: '3'\n} as const;\nexport type Size = (typeof Size)[keyof typeof Size];\n\n\n/**\n * Enumeration representing the days of the week.\n */\nexport enum WEEKDAYS {\n SUNDAY,\n MONDAY,\n TUESDAY,\n WEDNESDAY,\n THURSDAY,\n FRIDAY,\n SATURDAY\n}\n","/* Copyright (c) 2014-2020 Denis Pushkarev\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE\n */\n\n// Note: Originally copied from core-js-pure package and modified. (https://github.com/zloirock/core-js)\n\nconst queue = {};\nlet counter = 0;\nlet eventListenerAdded = false;\n\ndeclare global {\n interface Window {\n setImmediate: any;\n clearImmediate: any;\n }\n}\n\nconst run = (id) => {\n if (queue.hasOwnProperty(id)) {\n const fn = queue[id];\n delete queue[id];\n fn();\n }\n};\n\nconst listener = (event) => run(event.data);\n\n// Use function instead of arrow function to workaround an issue in codesandbox\nexport function setImmediate(cb: () => void, ...args) {\n if (window.setImmediate) {\n return window.setImmediate(cb);\n }\n\n if (!eventListenerAdded) {\n eventListenerAdded = true;\n window.addEventListener('message', listener, false);\n }\n\n queue[++counter] = () => {\n cb.apply(undefined, args);\n };\n\n const windowLocation = window.location;\n window.postMessage(counter + '', windowLocation.protocol + '//' + windowLocation.host);\n\n return counter;\n}\n\nexport function clearImmediate(id: any) {\n if (window.clearImmediate) {\n return window.clearImmediate(id);\n }\n\n delete queue[id];\n}\n","import { CurrencyPipe, formatDate as _formatDate, isPlatformBrowser } from '@angular/common';\nimport { Injectable, InjectionToken, PLATFORM_ID, inject } from '@angular/core';\nimport { mergeWith } from 'lodash-es';\nimport { NEVER, Observable } from 'rxjs';\nimport { setImmediate } from './setImmediate';\nimport { isDevMode } from '@angular/core';\nimport type { IgxTheme } from '../services/theme/theme.token';\n\n/** @hidden @internal */\nexport const ELEMENTS_TOKEN = /*@__PURE__*/new InjectionToken<boolean>('elements environment');\n\n/**\n * @hidden\n */\nexport const showMessage = (message: string, isMessageShown: boolean): boolean => {\n if (!isMessageShown && isDevMode()) {\n console.warn(message);\n }\n\n return true;\n};\n\n/**\n *\n * @hidden @internal\n */\nexport const getResizeObserver = () => globalThis.window?.ResizeObserver;\n\n/**\n * @hidden\n */\nexport function cloneArray<T>(array: T[], deep = false): T[] {\n return deep ? (array ?? []).map(cloneValue) : (array ?? []).slice();\n}\n\n/**\n * @hidden\n */\nexport function areEqualArrays<T>(arr1: T[], arr2: T[]): boolean {\n if (arr1.length !== arr2.length) return false;\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) return false;\n }\n return true;\n}\n\n/**\n * Doesn't clone leaf items\n *\n * @hidden\n */\nexport const cloneHierarchicalArray = (array: any[], childDataKey: any): any[] => {\n const result: any[] = [];\n if (!array) {\n return result;\n }\n\n for (const item of array) {\n const clonedItem = cloneValue(item);\n if (Array.isArray(item[childDataKey])) {\n clonedItem[childDataKey] = cloneHierarchicalArray(clonedItem[childDataKey], childDataKey);\n }\n result.push(clonedItem);\n }\n return result;\n};\n\n/**\n * Creates an object with prototype from provided source and copies\n * all properties descriptors from provided source\n * @param obj Source to copy prototype and descriptors from\n * @returns New object with cloned prototype and property descriptors\n */\nexport const copyDescriptors = (obj) => {\n if (obj) {\n return Object.create(\n Object.getPrototypeOf(obj),\n Object.getOwnPropertyDescriptors(obj)\n );\n }\n}\n\n\n/**\n * Deep clones all first level keys of Obj2 and merges them to Obj1\n *\n * @param obj1 Object to merge into\n * @param obj2 Object to merge from\n * @returns Obj1 with merged cloned keys from Obj2\n * @hidden\n */\nexport const mergeObjects = (obj1: any, obj2: any): any => mergeWith(obj1, obj2, (objValue, srcValue) => {\n if (Array.isArray(srcValue)) {\n return objValue = srcValue;\n }\n});\n\n/**\n * Creates deep clone of provided value.\n * Supports primitive values, dates and objects.\n * If passed value is array returns shallow copy of the array.\n *\n * @param value value to clone\n * @returns Deep copy of provided value\n * @hidden\n */\nexport const cloneValue = (value: any): any => {\n if (isDate(value)) {\n return new Date(value.getTime());\n }\n if (Array.isArray(value)) {\n return value.slice();\n }\n\n if (value instanceof Map || value instanceof Set) {\n return value;\n }\n\n if (isObject(value)) {\n const result = {};\n\n for (const key of Object.keys(value)) {\n if (key === \"externalObject\") {\n continue;\n }\n result[key] = cloneValue(value[key]);\n }\n return result;\n }\n return value;\n};\n\n/**\n * Creates deep clone of provided value.\n * Supports primitive values, dates and objects.\n * If passed value is array returns shallow copy of the array.\n * For Objects property values and references are cached and reused.\n * This allows for circular references to same objects.\n *\n * @param value value to clone\n * @param cache map of cached values already parsed\n * @returns Deep copy of provided value\n * @hidden\n */\nexport const cloneValueCached = (value: any, cache: Map<any, any>): any => {\n if (isDate(value)) {\n return new Date(value.getTime());\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n\n if (value instanceof Map || value instanceof Set) {\n return value;\n }\n\n if (isObject(value)) {\n if (cache.has(value)) {\n return cache.get(value);\n }\n\n const result = {};\n cache.set(value, result);\n\n for (const key of Object.keys(value)) {\n result[key] = cloneValueCached(value[key], cache);\n }\n return result;\n }\n return value;\n};\n\n/**\n * Parse provided input to Date.\n *\n * @param value input to parse\n * @returns Date if parse succeed or null\n * @hidden\n */\nexport const parseDate = (value: any): Date | null => {\n // if value is Invalid Date return null\n if (isDate(value)) {\n return !isNaN(value.getTime()) ? value : null;\n }\n return value ? new Date(value) : null;\n};\n\n/**\n * Returns an array with unique dates only.\n *\n * @param columnValues collection of date values (might be numbers or ISO 8601 strings)\n * @returns collection of unique dates.\n * @hidden\n */\nexport const uniqueDates = (columnValues: any[]) => columnValues.reduce((a, c) => {\n if (!a.cache[c.label]) {\n a.result.push(c);\n }\n a.cache[c.label] = true;\n return a;\n}, { result: [], cache: {} }).result;\n\n/**\n * Checks if provided variable is Object\n *\n * @param value Value to check\n * @returns true if provided variable is Object\n * @hidden\n */\nexport const isObject = (value: any): boolean => !!(value && value.toString() === '[object Object]');\n\n/**\n * Checks if provided variable is Date\n *\n * @param value Value to check\n * @returns true if provided variable is Date\n * @hidden\n */\nexport const isDate = (value: any): value is Date => {\n return Object.prototype.toString.call(value) === \"[object Date]\";\n}\n\n/**\n * Checks if the two passed arguments are equal\n * Currently supports date objects\n *\n * @param obj1\n * @param obj2\n * @returns: `boolean`\n * @hidden\n */\nexport const isEqual = (obj1, obj2): boolean => {\n if (isDate(obj1) && isDate(obj2)) {\n return obj1.getTime() === obj2.getTime();\n }\n return obj1 === obj2;\n};\n\n/**\n * Limits a number to a range between a minimum and a maximum value.\n *\n * @param number\n * @param min\n * @param max\n * @returns: `number`\n * @hidden\n */\nexport const clamp = (number: number, min: number, max: number) =>\n Math.max(min, Math.min(number, max));\n\n\n/**\n * Utility service taking care of various utility functions such as\n * detecting browser features, general cross browser DOM manipulation, etc.\n *\n * @hidden @internal\n */\n@Injectable({ providedIn: 'root' })\nexport class PlatformUtil {\n private platformId = inject(PLATFORM_ID);\n\n public isBrowser: boolean = isPlatformBrowser(this.platformId);\n public isIOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window);\n public isSafari = this.isBrowser && /Safari[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent);\n public isFirefox = this.isBrowser && /Firefox[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent);\n public isEdge = this.isBrowser && /Edge[\\/\\s](\\d+\\.\\d+)/.test(navigator.userAgent);\n public isChromium = this.isBrowser && (/Chrom|e?ium/g.test(navigator.userAgent) ||\n /Google Inc/g.test(navigator.vendor)) && !/Edge/g.test(navigator.userAgent);\n public browserVersion = this.isBrowser ? parseFloat(navigator.userAgent.match(/Version\\/([\\d.]+)/)?.at(1)) : 0;\n\n /** @hidden @internal */\n public isElements = inject(ELEMENTS_TOKEN, { optional: true });\n\n public KEYMAP = {\n ENTER: 'Enter',\n SPACE: ' ',\n ESCAPE: 'Escape',\n ARROW_DOWN: 'ArrowDown',\n ARROW_UP: 'ArrowUp',\n ARROW_LEFT: 'ArrowLeft',\n ARROW_RIGHT: 'ArrowRight',\n END: 'End',\n HOME: 'Home',\n PAGE_DOWN: 'PageDown',\n PAGE_UP: 'PageUp',\n F2: 'F2',\n TAB: 'Tab',\n SEMICOLON: ';',\n // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values#editing_keys\n DELETE: 'Delete',\n BACKSPACE: 'Backspace',\n CONTROL: 'Control',\n X: 'x',\n Y: 'y',\n Z: 'z'\n } as const;\n\n /**\n * @hidden @internal\n * Returns the actual size of the node content, using Range\n * ```typescript\n * let range = document.createRange();\n * let column = this.grid.columnList.filter(c => c.field === 'ID')[0];\n *\n * let size = getNodeSizeViaRange(range, column.cells[0].nativeElement);\n *\n * @remarks\n * The last parameter is useful when the size of the element to measure is modified by a\n * parent element that has explicit size. In such cases the calculated size is never lower\n * and the function may instead remove the parent size while measuring to get the correct value.\n * ```\n */\n public getNodeSizeViaRange(range: Range, node: HTMLElement, sizeHoldingNode?: HTMLElement) {\n let overflow = null;\n let nodeStyles: string[];\n\n if (!this.isFirefox) {\n overflow = node.style.overflow;\n // we need that hack - otherwise content won't be measured correctly in IE/Edge\n node.style.overflow = 'visible';\n }\n\n if (sizeHoldingNode) {\n const style = sizeHoldingNode.style;\n nodeStyles = [style.width, style.minWidth, style.flexBasis];\n style.width = '';\n style.minWidth = '';\n style.flexBasis = '';\n }\n\n range.selectNodeContents(node);\n const scale = node.getBoundingClientRect().width / node.offsetWidth;\n const width = range.getBoundingClientRect().width / scale;\n\n if (!this.isFirefox) {\n // we need that hack - otherwise content won't be measured correctly in IE/Edge\n node.style.overflow = overflow;\n }\n\n if (sizeHoldingNode) {\n sizeHoldingNode.style.width = nodeStyles[0];\n sizeHoldingNode.style.minWidth = nodeStyles[1];\n sizeHoldingNode.style.flexBasis = nodeStyles[2];\n }\n\n return width;\n }\n\n\n /**\n * Returns true if the current keyboard event is an activation key (Enter/Space bar)\n *\n * @hidden\n * @internal\n *\n * @memberof PlatformUtil\n */\n public isActivationKey(event: KeyboardEvent) {\n return event.key === this.KEYMAP.ENTER || event.key === this.KEYMAP.SPACE;\n }\n\n /**\n * Returns true if the current keyboard event is a combination that closes the filtering UI of the grid. (Escape/Ctrl+Shift+L)\n *\n * @hidden\n * @internal\n * @param event\n * @memberof PlatformUtil\n */\n public isFilteringKeyCombo(event: KeyboardEvent) {\n return event.key === this.KEYMAP.ESCAPE || (event.ctrlKey && event.shiftKey && event.key.toLowerCase() === 'l');\n }\n\n /**\n * @hidden @internal\n */\n public isLeftClick(event: PointerEvent | MouseEvent) {\n return event.button === 0;\n }\n\n /**\n * @hidden @internal\n */\n public isNavigationKey(key: string) {\n return [\n this.KEYMAP.HOME, this.KEYMAP.END, this.KEYMAP.SPACE,\n this.KEYMAP.ARROW_DOWN, this.KEYMAP.ARROW_LEFT, this.KEYMAP.ARROW_RIGHT, this.KEYMAP.ARROW_UP\n ].includes(key as any);\n }\n}\n\n/**\n * @hidden\n */\nexport const flatten = (arr: any[]) => {\n let result = [];\n\n arr.forEach(el => {\n result.push(el);\n if (el.children) {\n const children = Array.isArray(el.children) ? el.children : el.children.toArray();\n result = result.concat(flatten(children));\n }\n });\n return result;\n};\n\nexport interface CancelableEventArgs {\n /**\n * Provides the ability to cancel the event.\n */\n cancel: boolean;\n}\n\nexport interface IBaseEventArgs {\n /**\n * Provides reference to the owner component.\n */\n owner?: any;\n}\n\nexport interface CancelableBrowserEventArgs extends CancelableEventArgs {\n /* blazorSuppress */\n /** Browser event */\n event?: Event;\n}\n\nexport interface IBaseCancelableBrowserEventArgs extends CancelableBrowserEventArgs, IBaseEventArgs { }\n\nexport interface IBaseCancelableEventArgs extends CancelableEventArgs, IBaseEventArgs { }\n\nexport const HORIZONTAL_NAV_KEYS = new Set(['arrowleft', 'left', 'arrowright', 'right', 'home', 'end']);\n\nexport const NAVIGATION_KEYS = new Set([\n 'down',\n 'up',\n 'left',\n 'right',\n 'arrowdown',\n 'arrowup',\n 'arrowleft',\n 'arrowright',\n 'home',\n 'end',\n 'space',\n 'spacebar',\n ' '\n]);\nexport const ACCORDION_NAVIGATION_KEYS = new Set('up down arrowup arrowdown home end'.split(' '));\nexport const ROW_EXPAND_KEYS = new Set('right down arrowright arrowdown'.split(' '));\nexport const ROW_COLLAPSE_KEYS = new Set('left up arrowleft arrowup'.split(' '));\nexport const ROW_ADD_KEYS = new Set(['+', 'add', '≠', '±', '=']);\nexport const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS),\n...Array.from(ROW_ADD_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup']);\nexport const HEADER_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'escape', 'esc', 'l',\n /** This symbol corresponds to the Alt + L combination under MAC. */\n '¬']);\n\n/**\n * @hidden\n * @internal\n *\n * Creates a new ResizeObserver on `target` and returns it as an Observable.\n * Run the resizeObservable outside angular zone, because it patches the MutationObserver which causes an infinite loop.\n * Related issue: https://github.com/angular/angular/issues/31712\n */\nexport const resizeObservable = (target: HTMLElement): Observable<ResizeObserverEntry[]> => {\n const resizeObserver = getResizeObserver();\n // check whether we are on server env or client env\n if (resizeObserver) {\n return new Observable((observer) => {\n const instance = new resizeObserver((entries: ResizeObserverEntry[]) => {\n observer.next(entries);\n });\n instance.observe(target);\n const unsubscribe = () => instance.disconnect();\n return unsubscribe;\n });\n }\n // if on a server env return a empty observable that does not complete immediately\n return NEVER;\n\n}\n\n/**\n * @hidden\n * @internal\n *\n * Compares two maps.\n */\nexport const compareMaps = (map1: Map<any, any>, map2: Map<any, any>): boolean => {\n if (!map2) {\n return !map1;\n }\n if (map1.size !== map2.size) {\n return false;\n }\n let match = true;\n const keys = Array.from(map2.keys());\n for (const key of keys) {\n if (map1.has(key)) {\n match = map1.get(key) === map2.get(key);\n } else {\n match = false;\n }\n if (!match) {\n break;\n }\n }\n return match;\n};\n\nfunction _isObject(entity: unknown): entity is object {\n return entity != null && typeof entity === 'object';\n}\n\nexport function columnFieldPath(path?: string): string[] {\n return path?.split('.') ?? [];\n}\n\n/**\n * Given a property access path in the format `x.y.z` resolves and returns\n * the value of the `z` property in the passed object.\n *\n * @hidden\n * @internal\n */\nexport function resolveNestedPath<T extends object, U>(obj: unknown, pathParts: string[], defaultValue?: U): T | U | undefined {\n if (!_isObject(obj) || pathParts.length < 1) {\n return defaultValue;\n }\n\n let current = obj;\n\n for (const key of pathParts) {\n if (_isObject(current) && key in (current as T)) {\n current = current[key];\n } else {\n return defaultValue;\n }\n }\n\n return current as T;\n}\n\n/**\n *\n * Given a property access path in the format `x.y.z` and a value\n * this functions builds and returns an object following the access path.\n *\n * @example\n * ```typescript\n * console.log('x.y.z.', 42);\n * >> { x: { y: { z: 42 } } }\n * ```\n *\n * @hidden\n * @internal\n */\nexport const reverseMapper = (path: string, value: any) => {\n const obj = {};\n const parts = path?.split('.') ?? [];\n\n let _prop = parts.shift();\n let mapping: any;\n\n // Initial binding for first level bindings\n obj[_prop] = value;\n mapping = obj;\n\n parts.forEach(prop => {\n // Start building the hierarchy\n mapping[_prop] = {};\n // Go down a level\n mapping = mapping[_prop];\n // Bind the value and move the key\n mapping[prop] = value;\n _prop = prop;\n });\n\n return obj;\n};\n\nexport const yieldingLoop = (count: number, chunkSize: number, callback: (index: number) => void, done: () => void) => {\n let i = 0;\n const chunk = () => {\n const end = Math.min(i + chunkSize, count);\n for (; i < end; ++i) {\n callback(i);\n }\n if (i < count) {\n setImmediate(chunk);\n } else {\n done();\n }\n };\n chunk();\n};\n\nexport const isConstructor = (ref: any) => typeof ref === 'function' && Boolean(ref.prototype) && Boolean(ref.prototype.constructor);\n\n/**\n * Similar to Angular's formatDate. However it will not throw on `undefined | null | ''` instead\n * coalescing to an empty string.\n */\nexport const formatDate = (value: string | number | Date, format: string, locale: string, timezone?: string): string => {\n if (value === null || value === undefined || value === '') {\n return '';\n }\n return _formatDate(value, format, locale, timezone);\n};\n\nexport const formatCurrency = new CurrencyPipe(undefined).transform;\n\n/** Converts pixel values to their rem counterparts for a base value */\nexport const rem = (value: number | string) => {\n const base = parseFloat(globalThis.window?.getComputedStyle(globalThis.document?.documentElement).getPropertyValue('--ig-base-font-size'))\n return Number(value) / base;\n}\n\n/** Get the size of the component as derived from the CSS size variable */\nexport function getComponentSize(el: Element) {\n return globalThis.window?.getComputedStyle(el).getPropertyValue('--component-size');\n}\n\n/** Get the first item in an array */\nexport function first<T>(arr: T[]) {\n return arr.at(0) as T;\n}\n\n/** Get the last item in an array */\nexport function last<T>(arr: T[]) {\n return arr.at(-1) as T;\n}\n\n/** Calculates the modulo of two numbers, ensuring a non-negative result. */\nexport function modulo(n: number, d: number) {\n return ((n % d) + d) % d;\n}\n\n/**\n * Splits an array into chunks of length `size` and returns a generator\n * yielding each chunk.\n * The last chunk may contain less than `size` elements.\n *\n * @example\n * ```typescript\n * const arr = [0,1,2,3,4,5,6,7,8,9];\n *\n * Array.from(chunk(arr, 2)) // [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]\n * Array.from(chunk(arr, 3)) // [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]\n * Array.from(chunk([], 3)) // []\n * Array.from(chunk(arr, -3)) // Error\n * ```\n */\nexport function* intoChunks<T>(arr: T[], size: number) {\n if (size < 1) {\n throw new Error('size must be an integer >= 1');\n }\n for (let i = 0; i < arr.length; i += size) {\n yield arr.slice(i, i + size);\n }\n}\n\n/**\n * @param size\n * @returns string that represents the --component-size default value\n */\nexport function getComponentCssSizeVar(size: string) {\n switch (size) {\n case \"1\":\n return 'var(--ig-size, var(--ig-size-small))';\n case \"2\":\n return 'var(--ig-size, var(--ig-size-medium))';\n default:\n return 'var(--ig-size, var(--ig-size-large))';\n }\n}\n\n/**\n * @param path - The URI path to be normalized.\n * @returns string encoded using the encodeURI function.\n */\nexport function normalizeURI(path: string) {\n return path?.split('/').map(encodeURI).join('/');\n}\n\nexport function getComponentTheme(el: Element) {\n return globalThis.window\n ?.getComputedStyle(el)\n .getPropertyValue('--theme')\n .trim() as IgxTheme;\n}\n\n/**\n * Collection re-created w/ the built in track by identity will always log\n * warning even for valid cases of recalculating all collection items.\n * See https://github.com/angular/angular/blob/55581b4181639568fb496e91055142a1b489e988/packages/core/src/render3/instructions/control_flow.ts#L393-L409\n * Current solution explicit track function doing the same as suggested in:\n * https://github.com/angular/angular/issues/56471#issuecomment-2180315803\n * This should be used with moderation and when necessary.\n * @internal\n */\nexport function trackByIdentity<T>(item: T): T {\n return item;\n}\n","import { Injectable } from '@angular/core';\n\n/** @hidden */\n@Injectable({\n providedIn: 'root',\n})\nexport class IgxSelectionAPIService {\n /**\n * If primaryKey is defined, then multiple selection is based on the primaryKey, and it is array of numbers, strings, etc.\n * If the primaryKey is omitted, then selection is based on the item data\n */\n protected selection: Map<string, Set<any>> = new Map<string, Set<any>>();\n\n /**\n * Get current component selection.\n *\n * @param componentID ID of the component.\n */\n public get(componentID: string): Set<any> {\n return this.selection.get(componentID);\n }\n\n /**\n * Set new component selection.\n *\n * @param componentID ID of the component.\n * @param newSelection The new component selection to be set.\n */\n public set(componentID: string, newSelection: Set<any>) {\n if (!componentID) {\n throw Error('Invalid value for component id!');\n }\n this.selection.set(componentID, newSelection);\n }\n\n /**\n * Clears selection for component.\n *\n * @param componentID ID of the component.\n */\n public clear(componentID: string) {\n this.selection.set(componentID, this.get_empty());\n }\n\n /**\n * Removes selection for a component.\n * @param componentID\n */\n public delete(componentID: string) {\n this.selection.delete(componentID);\n }\n\n /**\n * Get current component selection length.\n *\n * @param componentID ID of the component.\n */\n public size(componentID: string): number {\n const sel = this.get(componentID);\n return sel ? sel.size : 0;\n }\n\n /**\n * Creates new selection that consist of the new item added to the current component selection.\n * The returned collection is new Set,\n * therefore if you want to update component selection you need to call in addition the set_selection() method\n * or instead use the select_item() one.\n *\n * @param componentID ID of the component, which we add new item to.\n * @param itemID ID of the item to add to component selection.\n * @param sel Used internally only by the selection (add_items method) to accumulate selection for multiple items.\n *\n * @returns Selection after the new item is added.\n */\n public add_item(componentID: string, itemID, sel?: Set<any>): Set<any> {\n if (!sel) {\n sel = new Set(this.get(componentID));\n }\n if (sel === undefined) {\n sel = this.get_empty();\n }\n sel.add(itemID);\n return sel;\n }\n\n /**\n * Creates new selection that consist of the new items added to the current component selection.\n * The returned collection is new Set,\n * therefore if you want to update component selection you need to call in addition the set_selection() method\n * or instead use the select_items() one.\n *\n * @param componentID ID of the component, which we add new items to.\n * @param itemIDs Array of IDs of the items to add to component selection.\n * @param clearSelection If true it will clear previous selection.\n *\n * @returns Selection after the new items are added.\n */\n public add_items(componentID: string, itemIDs: any[], clearSelection?: boolean): Set<any> {\n let selection: Set<any>;\n if (clearSelection) {\n selection = this.get_empty();\n } else if (itemIDs && itemIDs.length === 0) {\n selection = new Set(this.get(componentID));\n }\n itemIDs.forEach((item) => selection = this.add_item(componentID, item, selection));\n return selection;\n }\n\n /**\n * Add item to the current component selection.\n *\n * @param componentID ID of the component, which we add new item to.\n * @param itemID ID of the item to add to component selection.\n * @param sel Used internally only by the selection (select_items method) to accumulate selection for multiple items.\n */\n public select_item(componentID: string, itemID, sel?: Set<any>) {\n this.set(componentID, this.add_item(componentID, itemID, sel));\n }\n\n /**\n * Add items to the current component selection.\n *\n * @param componentID ID of the component, which we add new items to.\n * @param itemIDs Array of IDs of the items to add to component selection.\n * @param clearSelection If true it will clear previous selection.\n */\n public select_items(componentID: string, itemID: any[], clearSelection?: boolean) {\n this.set(componentID, this.add_items(componentID, itemID, clearSelection));\n }\n\n /**\n * Creates new selection that consist of the new items excluded from the current component selection.\n * The returned collection is new Set,\n * therefore if you want to update component selection you need to call in addition the set_selection() method\n * or instead use the deselect_item() one.\n *\n * @param componentID ID of the component, which we remove items from.\n * @param itemID ID of the item to remove from component selection.\n * @param sel Used internally only by the selection (delete_items method) to accumulate deselected items.\n *\n * @returns Selection after the item is removed.\n */\n public delete_item(componentID: string, itemID, sel?: Set<any>) {\n if (!sel) {\n sel = new Set(this.get(componentID));\n }\n if (sel === undefined) {\n return;\n }\n sel.delete(itemID);\n return sel;\n }\n\n /**\n * Creates new selection that consist of the new items removed to the current component selection.\n * The returned collection is new Set,\n * therefore if you want to update component selection you need to call in addition the set_selection() method\n * or instead use the deselect_items() one.\n *\n * @param componentID ID of the component, which we remove items from.\n * @param itemID ID of the items to remove from component selection.\n *\n * @returns Selection after the items are removed.\n */\n public delete_items(componentID: string, itemIDs: any[]): Set<any> {\n let selection: Set<any>;\n itemIDs.forEach((deselectedItem) => selection = this.delete_item(componentID, deselectedItem, selection));\n return selection;\n }\n\n /**\n * Remove item from the current component selection.\n *\n * @param componentID ID of the component, which we remove item from.\n * @param itemID ID of the item to remove from component selection.\n * @param sel Used internally only by the selection (deselect_items method) to accumulate selection for multiple items.\n */\n public deselect_item(componentID: string, itemID, sel?: Set<any>) {\n this.set(componentID, this.delete_item(componentID, itemID, sel));\n }\n\n /**\n * Remove items to the current component selection.\n *\n * @param componentID ID of the component, which we add new items to.\n * @param itemIDs Array of IDs of the items to add to component selection.\n */\n public deselect_items(componentID: string, itemID: any[], _clearSelection?: boolean) {\n this.set(componentID, this.delete_items(componentID, itemID));\n }\n\n /**\n * Check if the item is selected in the component selection.\n *\n * @param componentID ID of the component.\n * @param itemID ID of the item to search.\n *\n * @returns If item is selected.\n */\n public is_item_selected(componentID: string, itemID): boolean {\n const sel = this.get(componentID);\n if (!sel) {\n return false;\n }\n return sel.has(itemID);\n }\n\n /**\n * Get first element in the selection.\n * This is correct when we have only one item in the collection (for single selection purposes)\n * and the method returns that item.\n *\n * @param componentID ID of the component.\n *\n * @returns First element in the set.\n */\n public first_item(componentID: string) {\n const sel = this.get(componentID);\n if (sel && sel.size > 0) {\n return sel.values().next().value;\n }\n }\n\n /**\n * Returns whether all items are selected.\n *\n * @param componentID ID of the component.\n * @param dataCount: number Number of items in the data.\n *\n * @returns If all items are selected.\n */\n public are_all_selected(componentID: string, dataCount: number): boolean {\n return dataCount > 0 && dataCount === this.size(componentID);\n }\n\n /**\n * Returns whether any of the items is selected.\n *\n * @param componentID ID of the component.\n * @param data Entire data array.\n *\n * @returns If there is any item selected.\n */\n public are_none_selected(componentID: string): boolean {\n return this.size(componentID) === 0;\n }\n\n /**\n * Get all primary key values from a data array. If there isn't a primary key defined that the entire data is returned instead.\n *\n * @param data Entire data array.\n * @param primaryKey Data primary key.\n *\n * @returns Array of identifiers, either primary key values or the entire data array.\n */\n public get_all_ids(data, primaryKey?) {\n // If primaryKey is 0, this should still map to the property\n return primaryKey !== undefined && primaryKey !== null ? data.map((x) => x[primaryKey]) : data;\n }\n\n /**\n * Returns empty selection collection.\n *\n * @returns empty set.\n */\n public get_empty() {\n return new Set();\n }\n}\n","import { InjectionToken } from \"@angular/core\";\n\n/**\n * Used for editor control components\n *\n * @hidden\n */\nexport interface EditorProvider {\n /** Return the focusable native element */\n getEditElement(): HTMLElement;\n}\n\n/**\n * Injection token is used to inject the EditorProvider token into components\n *\n * @hidden @internal\n */\nexport const EDITOR_PROVIDER = new InjectionToken<EditorProvider>('EditorProvider');\n","import { Injectable, NgZone, DOCUMENT, inject } from '@angular/core';\nimport { ɵgetDOM as getDOM } from '@angular/platform-browser';\nimport { PlatformUtil } from './utils';\nimport { HammerManager, HammerOptions, HammerStatic } from './touch-annotations';\n\nconst EVENT_SUFFIX = 'precise';\n\n/**\n * Touch gestures manager based on Hammer.js\n * Use with caution, this will track references for single manager per element. Very TBD. Much TODO.\n *\n * @hidden\n */\n@Injectable()\nexport class HammerGesturesManager {\n private _zone = inject(NgZone);\n private doc = inject(DOCUMENT);\n private platformUtil = inject(PlatformUtil);\n\n public static Hammer: HammerStatic = typeof window !== 'undefined' ? (window as any).Hammer : null;\n /**\n * Event option defaults for each recognizer, see http://hammerjs.github.io/api/ for API listing.\n */\n protected hammerOptions: HammerOptions = {};\n\n private platformBrowser: boolean;\n private _hammerManagers: Array<{ element: EventTarget; manager: HammerManager }> = [];\n\n constructor() {\n this.platformBrowser = this.platformUtil.isBrowser;\n if (this.platformBrowser && HammerGesturesManager.Hammer) {\n this.hammerOptions = {\n // D.P. #447 Force TouchInput due to PointerEventInput bug (https://github.com/hammerjs/hammer.js/issues/1065)\n // see https://github.com/IgniteUI/igniteui-angular/issues/447#issuecomment-324601803\n inputClass: HammerGesturesManager.Hammer.TouchInput,\n recognizers: [\n [HammerGesturesManager.Hammer.Pan, { threshold: 0 }],\n [HammerGesturesManager.Hammer.Swipe, { direction: HammerGesturesManager.Hammer.DIRECTION_HORIZONTAL }],\n [HammerGesturesManager.Hammer.Tap],\n [HammerGesturesManager.Hammer.Tap, { event: 'doubletap', taps: 2 }, ['tap']]\n ]\n };\n }\n }\n\n public supports(eventName: string): boolean {\n return eventName.toLowerCase().endsWith('.' + EVENT_SUFFIX);\n }\n\n /**\n * Add listener extended with options for Hammer.js. Will use defaults if none are provided.\n * Modeling after other event plugins for easy future modifications.\n */\n public addEventListener(\n element: HTMLElement,\n eventName: string,\n eventHandler: (eventObj) => void,\n options: HammerOptions = null): () => void {\n if (!this.platformBrowser) {\n return;\n }\n\n // Creating the manager bind events, must be done outside of angular\n return this._zone.runOutsideAngular(() => {\n if (!HammerGesturesManager.Hammer) {\n //no hammer\n return;\n }\n let mc: HammerManager = this.getManagerForElement(element);\n if (mc === null) {\n // new Hammer is a shortcut for Manager with defaults\n mc = new HammerGesturesManager.Hammer(element, Object.assign(this.hammerOptions, options));\n this.addManagerForElement(element, mc);\n }\n const handler = (eventObj) => this._zone.run(() => eventHandler(eventObj));\n mc.on(eventName, handler);\n return () => mc.off(eventName, handler);\n });\n }\n\n /**\n * Add listener extended with options for Hammer.js. Will use defaults if none are provided.\n * Modeling after other event plugins for easy future modifications.\n *\n * @param target Can be one of either window, body or document(fallback default).\n */\n public addGlobalEventListener(target: string, eventName: string, eventHandler: (eventObj) => void): () => void {\n if (!this.platformBrowser || !HammerGesturesManager.Hammer) {\n return;\n }\n\n const element = this.getGlobalEventTarget(target);\n\n // Creating the manager bind events, must be done outside of angular\n return this.addEventListener(element as HTMLElement, eventName, eventHandler);\n }\n\n /**\n * Exposes [Dom]Adapter.getGlobalEventTarget to get global event targets.\n * Supported: window, document, body. Defaults to document for invalid args.\n *\n * @param target Target name\n */\n public getGlobalEventTarget(target: string): EventTarget {\n return getDOM().getGlobalEventTarget(this.doc, target);\n }\n\n /**\n * Set HammerManager options.\n *\n * @param element The DOM element used to create the manager on.\n *\n * ### Example\n *\n * ```ts\n * manager.setManagerOption(myElem, \"pan\", { pointers: 1 });\n * ```\n */\n public setManagerOption(element: EventTarget, event: string, options: any) {\n const manager = this.getManagerForElement(element);\n manager.get(event).set(options);\n }\n\n /**\n * Add an element and manager map to the internal collection.\n *\n * @param element The DOM element used to create the manager on.\n */\n public addManagerForElement(element: EventTarget, manager: HammerManager) {\n this._hammerManagers.push({element, manager});\n }\n\n /**\n * Get HammerManager for the element or null\n *\n * @param element The DOM element used to create the manager on.\n */\n public getManagerForElement(element: EventTarget): HammerManager {\n const result = this._hammerManagers.filter(value => value.element === element);\n return result.length ? result[0].manager : null;\n }\n\n /**\n * Destroys the HammerManager for the element, removing event listeners in the process.\n *\n * @param element The DOM element used to create the manager on.\n */\n public removeManagerForElement(element: HTMLElement) {\n let index: number = null;\n for (let i = 0; i < this._hammerManagers.length; i++) {\n if (element === this._hammerManagers[i