UNPKG

novo-elements

Version:

1 lines 916 kB
{"version":3,"file":"novo-elements-utils.mjs","sources":["../../../projects/novo-elements/src/utils/app-bridge/interfaces.ts","../../../projects/novo-elements/src/utils/app-bridge/AppBridge.ts","../../../projects/novo-elements/src/utils/base-renderer/BaseRenderer.ts","../../../projects/novo-elements/src/utils/date/convert-tokens.ts","../../../projects/novo-elements/src/utils/date/legacy-parse.ts","../../../projects/novo-elements/src/utils/date/Date.ts","../../../projects/novo-elements/src/utils/date/Date.types.ts","../../../projects/novo-elements/src/utils/date/timezone-support.ts","../../../projects/novo-elements/src/utils/calendar-utils/CalendarUtils.ts","../../../projects/novo-elements/src/utils/ckeditor-input-fix.ts","../../../projects/novo-elements/src/utils/color-utils/ColorUtils.ts","../../../projects/novo-elements/src/utils/countries/Countries.ts","../../../projects/novo-elements/src/utils/decorators/BooleanInput.ts","../../../projects/novo-elements/src/utils/deferred/Deferred.ts","../../../projects/novo-elements/src/utils/Helpers.ts","../../../projects/novo-elements/src/utils/key-codes/Key.ts","../../../projects/novo-elements/src/utils/key-codes/KeyCodes.ts","../../../projects/novo-elements/src/utils/notifier/notifier.util.ts","../../../projects/novo-elements/src/utils/outside-click/OutsideClick.ts","../../../projects/novo-elements/src/utils/novo-elements-utils.ts"],"sourcesContent":["export enum AppBridgeHandler {\n HTTP,\n OPEN,\n OPEN_LIST,\n CLOSE,\n REFRESH,\n PIN,\n REGISTER,\n UPDATE,\n REQUEST_DATA,\n CALLBACK,\n PING,\n}\n\n// record - an individual entity record\n// add/fast-add - the add page for a new record\n// custom - custom action that opens the url provided in data.url\n// preview - the preview slideout available only in Novo\nexport type NovoApps = 'record' | 'add' | 'fast-add' | 'slide-out-add' | 'custom' | 'preview';\n\nexport type AlleyLinkColors =\n | 'purple'\n | 'green'\n | 'blue'\n | 'lead'\n | 'candidate'\n | 'contact'\n | 'company'\n | 'opportunity'\n | 'job'\n | 'billable-charge'\n | 'earn-code'\n | 'invoice-statement'\n | 'job-code'\n | 'payable-charge'\n | 'sales-tax-rate'\n | 'tax-rules'\n | 'submission'\n | 'placement'\n | 'navigation'\n | 'canvas'\n | 'neutral'\n | 'neutral-italic'\n | 'initial'\n | 'distributionList'\n | 'contract';\n\nexport interface IAppBridgeOpenEvent {\n type: NovoApps;\n entityType: string;\n entityId?: string;\n tab?: string;\n data?: any;\n passthrough?: string;\n}\n\nexport type MosaicLists =\n | 'Candidate'\n | 'ClientContact'\n | 'ClientCorporation'\n | 'JobOrder'\n | 'JobSubmission'\n | 'JobPosting'\n | 'Placement'\n | 'Lead'\n | 'Opportunity';\n\nexport interface IAppBridgeOpenListEvent {\n type: MosaicLists;\n keywords: Array<string>;\n criteria: any;\n}\n\nexport type NovoDataType = 'entitlements' | 'settings' | 'user';\n\nexport interface IAppBridgeRequestDataEvent {\n type: NovoDataType;\n}\n\nexport type HttpVerb = 'get' | 'post' | 'put' | 'delete';\n\nexport const HTTP_VERBS = {\n GET: 'get',\n POST: 'post',\n PUT: 'put',\n DELETE: 'delete',\n};\n\nexport type MessageType = 'register' | 'open' | 'openList' | 'close' | 'refresh' | 'pin' | 'ping' | 'update' | 'httpGET' | 'httpPOST' | 'httpPUT' | 'httpDELETE' | 'customEvent' | 'requestData' | 'callback';\n\nexport const MESSAGE_TYPES = {\n REGISTER: 'register',\n OPEN: 'open',\n OPEN_LIST: 'openList',\n CLOSE: 'close',\n REFRESH: 'refresh',\n PIN: 'pin',\n PING: 'ping',\n UPDATE: 'update',\n HTTP_GET: 'httpGET',\n HTTP_POST: 'httpPOST',\n HTTP_PUT: 'httpPUT',\n HTTP_DELETE: 'httpDELETE',\n CUSTOM_EVENT: 'customEvent',\n REQUEST_DATA: 'requestData',\n CALLBACK: 'callback',\n};\n","// NG2\nimport { HttpClient } from '@angular/common/http';\nimport { AppBridgeHandler, AlleyLinkColors, IAppBridgeOpenEvent, IAppBridgeOpenListEvent, MESSAGE_TYPES, HTTP_VERBS } from './interfaces';\n\ntype ValueOf<T> = T[keyof T];\n\ntype MessageType = ValueOf<typeof MESSAGE_TYPES>;\ntype HttpVerb = ValueOf<typeof HTTP_VERBS>;\n\ndeclare const postRobot: any;\n\nexport interface PostRobotEvent<T> {\n data: T;\n // the URL of the origin window\n origin: string;\n // the Window object this event was sent from (be warned, you may not be able to access its properties)\n source: Window;\n}\n\nexport class AppBridgeService {\n create(name: string) {\n return new AppBridge(name);\n }\n}\n\nexport class DevAppBridgeService {\n constructor(private http: HttpClient) {}\n create(name: string, postRobotRef?: any) {\n return new DevAppBridge(name, this.http, postRobotRef);\n }\n}\n\n// remove attributes unsafe for postrobot.send()\nfunction cleanPacket(packet: any) {\n if (packet && typeof packet === 'object' && 'source' in packet) {\n delete packet.source;\n }\n}\n\nexport class AppBridge {\n public id: string = `${Date.now()}`;\n public traceName: string;\n public windowName: string;\n\n private _registeredFrames = [];\n private _handlers = {};\n private _tracing: boolean = false;\n private _eventListeners: any = {};\n\n private postRobot: any;\n\n // Type?\n constructor(traceName: string = 'AppBridge', postRobotRef?: any) {\n this.traceName = traceName;\n this.postRobot = postRobotRef || /* global */ postRobot;\n if (this.postRobot) {\n this.postRobot.CONFIG.LOG_LEVEL = 'error';\n try {\n this._setupHandlers();\n } catch (error) {\n // No op\n }\n }\n }\n\n set tracing(tracing: boolean) {\n this._tracing = tracing;\n }\n\n public handle(type: AppBridgeHandler, handler: Function) {\n this._handlers[type] = handler;\n }\n\n private _trace(eventType, event) {\n if (this._tracing) {\n console.info(`[${this.traceName || this.id}] \"${eventType}\"`, event);\n }\n }\n\n protected _setupHandlers(): void {\n\n // map an object for all handlers, so that we can run some other actions before each of them\n const defaultMsgHandlers: { [msgType in MessageType]?: (evt: PostRobotEvent<any>) => Promise<unknown> } = {\n // Register\n [MESSAGE_TYPES.REGISTER]: async (event) => {\n this._registeredFrames.push(event);\n const windowName = await this.register(event.data);\n return {windowName};\n },\n\n // Update\n [MESSAGE_TYPES.UPDATE]: (event: PostRobotEvent<any>) => {\n return this.update(event.data).then((success) => {\n return { success };\n });\n },\n // Open\n [MESSAGE_TYPES.OPEN]: (event: PostRobotEvent<any>) => {\n return this.open(event.data).then((success) => {\n return { success };\n });\n },\n [MESSAGE_TYPES.OPEN_LIST]: (event: PostRobotEvent<any>) => {\n return this.openList(event.data).then((success) => {\n return { success };\n });\n },\n // Close\n [MESSAGE_TYPES.CLOSE]: (event: PostRobotEvent<any>) => {\n const index = this._registeredFrames.findIndex((frame) => frame.data.id === event.data.id);\n if (index !== -1) {\n this._registeredFrames.splice(index, 1);\n }\n return this.close(event.data).then(success => ({ success }));\n },\n // Refresh\n [MESSAGE_TYPES.REFRESH]: (event: PostRobotEvent<any>) => {\n return this.refresh(event.data).then((success) => {\n return { success };\n });\n },\n // PIN\n [MESSAGE_TYPES.PIN]: (event: PostRobotEvent<any>) => {\n return this.pin(event.data).then((success) => {\n return { success };\n });\n },\n // PING\n [MESSAGE_TYPES.PING]: (event: PostRobotEvent<any>) => {\n return this.httpGET('ping', undefined, event.data.origin).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // REQUEST_DATA\n [MESSAGE_TYPES.REQUEST_DATA]: (event: PostRobotEvent<any>) => {\n return this.requestData(event.data).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // CALLBACKS\n [MESSAGE_TYPES.CALLBACK]: (event: PostRobotEvent<any>) => {\n return this.callback(event.data).then((success) => {\n return { success };\n });\n },\n // HTTP-GET\n [MESSAGE_TYPES.HTTP_GET]: (event: PostRobotEvent<any>) => {\n return this.httpGET(event.data.relativeURL, undefined, event.data.origin).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // HTTP-POST\n [MESSAGE_TYPES.HTTP_POST]: (event: PostRobotEvent<any>) => {\n return this.httpPOST(event.data.relativeURL, event.data.data, undefined, event.data.origin).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // HTTP-PUT\n [MESSAGE_TYPES.HTTP_PUT]: (event: PostRobotEvent<any>) => {\n return this.httpPUT(event.data.relativeURL, event.data.data, undefined, event.data.origin).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // HTTP-DELETE\n [MESSAGE_TYPES.HTTP_DELETE]: (event: PostRobotEvent<any>) => {\n return this.httpDELETE(event.data.relativeURL, undefined, event.data.origin).then((result) => {\n return { data: result.data, error: result.error };\n });\n },\n // Custom Events\n [MESSAGE_TYPES.CUSTOM_EVENT]: async (event: PostRobotEvent<any>) => {\n if (this._eventListeners[event.data.event]) {\n this._eventListeners[event.data.event].forEach((listener) => {\n listener(event.data.data);\n });\n }\n if (this._registeredFrames.length > 0) {\n cleanPacket(event.data);\n this._registeredFrames.forEach((frame) => {\n // TODO: Should this make sure it doesn't echo the custom event back to the author?\n this.postRobot.send(frame.source, MESSAGE_TYPES.CUSTOM_EVENT, event.data);\n });\n }\n },\n };\n\n Object.keys(defaultMsgHandlers).forEach(msgType => {\n this.postRobot.on(msgType, event => {\n this._trace(msgType, event);\n const origin: string[] = Array.isArray(event.data.origin) ? event.data.origin : [];\n if (event.origin !== this.windowOrigin()) {\n origin.unshift(event.origin);\n } else if (origin.indexOf(event.data.originTraceName) === -1) {\n origin.unshift(event.data.originTraceName);\n }\n if (event.data) {\n // known gap - simple commands will not forward origin/source from subchild frames to parent\n event.data.origin = origin;\n event.data.source = event.source;\n }\n return defaultMsgHandlers[msgType](event);\n })\n });\n }\n\n protected windowOrigin() {\n return window.location.origin;\n }\n\n handleMessage<T>({ msgType, handler, packet, echoPacket, resolveEventData }: {\n msgType: MessageType,\n handler: AppBridgeHandler,\n packet: T,\n echoPacket: any,\n resolveEventData: (any) => boolean,\n }): Promise<boolean> {\n let returnPromise: Promise<any>;\n if (this._handlers[handler]) {\n // Should be directly returning a promise. However, as a fallback, provide callback arguments\n let callbackSuccess;\n let callbackFail;\n returnPromise = new Promise((s, f) => {\n callbackSuccess = s;\n callbackFail = f;\n });\n const handlerResult = this._handlers[handler](packet, callbackArg => {\n if (callbackArg) {\n callbackSuccess(true);\n } else {\n callbackFail(false);\n }\n });\n if (handlerResult && 'then' in handlerResult) {\n returnPromise = handlerResult;\n }\n return returnPromise.then(result => true, () => false);\n } else {\n return this.postRobot.sendToParent(msgType, echoPacket || packet);\n }\n\n }\n\n /**\n * Fires or responds to an open event\n * @param packet any - packet of data to send with the open event\n */\n public open(packet: IAppBridgeOpenEvent): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.OPEN]) {\n this._handlers[AppBridgeHandler.OPEN](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n cleanPacket(packet);\n Object.assign(packet, { id: this.id, windowName: this.windowName });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.OPEN, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.OPEN} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an openList event\n * @param packet any - packet of data to send with the open event\n */\n public openList(packet: Partial<IAppBridgeOpenListEvent>): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.OPEN_LIST]) {\n this._handlers[AppBridgeHandler.OPEN_LIST](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n const openListPacket = {};\n Object.assign(openListPacket, { type: 'List', entityType: packet.type, keywords: packet.keywords, criteria: packet.criteria });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.OPEN_LIST, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.OPEN_LIST} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an close event\n * @param packet any - packet of data to send with the close event\n */\n public update(\n packet: Partial<{ entityType: string; entityId: string; title: string; titleKey: string; color: AlleyLinkColors }>,\n ): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.UPDATE]) {\n this._handlers[AppBridgeHandler.UPDATE](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n cleanPacket(packet);\n Object.assign(packet, { id: this.id, windowName: this.windowName });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.UPDATE, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.UPDATE} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an close event\n */\n public close(packet?: object): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.CLOSE]) {\n this._handlers[AppBridgeHandler.CLOSE](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n if (packet) {\n console.info('[AppBridge] - close(packet) is deprecated! Please just use close()!');\n }\n const realPacket = { id: this.id, windowName: this.windowName };\n this.postRobot\n .sendToParent(MESSAGE_TYPES.CLOSE, realPacket)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.CLOSE} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an close event\n */\n public refresh(packet?: object): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.REFRESH]) {\n this._handlers[AppBridgeHandler.REFRESH](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n if (packet) {\n console.info('[AppBridge] - refresh(packet) is deprecated! Please just use refresh()!');\n }\n const realPacket = { id: this.id, windowName: this.windowName };\n this.postRobot\n .sendToParent(MESSAGE_TYPES.REFRESH, realPacket)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.REFRESH} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n public ping(): Promise<boolean> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.PING]) {\n this._handlers[AppBridgeHandler.PING]({}, (data: any, error: any) => {\n resolve({ data, error });\n });\n } else {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.PING, {})\n .then((event: any) => {\n resolve({ data: event.data.data, error: event.data.error });\n })\n .catch((err) => {\n reject(null);\n });\n }\n });\n }\n\n /**\n * Fires or responds to a pin event\n */\n public pin(packet?: object): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.PIN]) {\n this._handlers[AppBridgeHandler.PIN](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n if (packet) {\n console.info('[AppBridge] - pin(packet) is deprecated! Please just use pin()!');\n }\n const realPacket = { id: this.id, windowName: this.windowName };\n this.postRobot\n .sendToParent(MESSAGE_TYPES.PIN, realPacket)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.PIN} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to a requestData event\n * @param packet any - packet of data to send with the requestData event\n */\n public requestData(packet: { type: string }): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.REQUEST_DATA]) {\n this._handlers[AppBridgeHandler.REQUEST_DATA](packet, (data: any) => {\n if (data) {\n resolve({ data });\n } else {\n reject(false);\n }\n });\n } else {\n cleanPacket(packet);\n Object.assign(packet, { id: this.id, windowName: this.windowName });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.REQUEST_DATA, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.REQUEST_DATA} (callback)`, event);\n if (event.data) {\n resolve({ data: event.data.data });\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires a generic callback command\n * @param packet string - key: string, generic: boolean\n */\n public callback(packet: { key: string; generic: boolean; options: object }): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.CALLBACK]) {\n this._handlers[AppBridgeHandler.CALLBACK](packet, (success: boolean) => {\n if (success) {\n resolve(true);\n } else {\n reject(false);\n }\n });\n } else {\n cleanPacket(packet);\n Object.assign(packet, { id: this.id, windowName: this.windowName });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.CALLBACK, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.CALLBACK} (callback)`, event);\n if (event.data) {\n resolve(true);\n } else {\n reject(false);\n }\n })\n .catch((err) => {\n reject(false);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an register event\n * @param packet any - packet of data to send with the event\n */\n public register(packet: Partial<{ title: string; url: string; color: AlleyLinkColors }> = {}): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.REGISTER]) {\n this._handlers[AppBridgeHandler.REGISTER](packet, (windowName: string) => {\n if (windowName) {\n resolve(windowName);\n } else {\n resolve(null);\n }\n });\n } else {\n cleanPacket(packet);\n Object.assign(packet, { id: this.id });\n this.postRobot\n .sendToParent(MESSAGE_TYPES.REGISTER, packet)\n .then((event) => {\n this._trace(`${MESSAGE_TYPES.REGISTER} (callback)`, event);\n if (event.data) {\n this.windowName = event.data.windowName;\n resolve(event.data.windowName);\n } else {\n resolve(null);\n }\n })\n .catch((err) => {\n this._trace(`${MESSAGE_TYPES.REGISTER} - FAILED - (no parent)`, err);\n reject(err);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an HTTP_GET event\n * @param relativeURL string - URL to fetch, relative to the mainframe URL\n * @param timeout - how long to attempt the request before reporting an error\n * @param originStack - the domain of the previous frame(s) the request originated from\n */\n public httpGET(relativeURL: string, timeout: number = 10000, originStack?: string[]): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.HTTP]) {\n this._handlers[AppBridgeHandler.HTTP]({ verb: HTTP_VERBS.GET, relativeURL, origin: originStack || [this.traceName] }, (data: any, error: any) => {\n resolve({ data, error });\n });\n } else {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.HTTP_GET, { relativeURL, origin: originStack, originTraceName: this.traceName }, { timeout })\n .then((event: any) => {\n resolve({ data: event.data.data, error: event.data.error });\n })\n .catch((err) => {\n reject(null);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an HTTP_POST event\n * @param relativeURL string - URL to fetch, relative to the mainframe URL\n * @param postData any - packet of data to send with the event\n * @param timeout - how long to attempt the request before reporting an error\n * @param originStack - the domain of the previous frame(s) the request originated from\n */\n public httpPOST(relativeURL: string, postData: any, timeout: number = 10000, originStack?: string[]): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.HTTP]) {\n this._handlers[AppBridgeHandler.HTTP]({ verb: HTTP_VERBS.POST, relativeURL, data: postData, origin: originStack || [this.traceName] }, (data: any, error: any) => {\n resolve({ data, error });\n });\n } else {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.HTTP_POST, { relativeURL, data: postData, origin: originStack, originTraceName: this.traceName }, { timeout })\n .then((event: any) => {\n resolve({ data: event.data.data, error: event.data.error });\n })\n .catch((err) => {\n reject(null);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an HTTP_PUT event\n * @param relativeURL string - URL to fetch, relative to the mainframe URL\n * @param packet any - packet of data to send with the event\n * @param timeout - how long to attempt the request before reporting an error\n * @param originStack - the domain of the previous frame(s) the request originated from\n */\n public httpPUT(relativeURL: string, putData: any, timeout: number = 10000, originStack?: string[]): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.HTTP]) {\n this._handlers[AppBridgeHandler.HTTP]({ verb: HTTP_VERBS.PUT, relativeURL, data: putData, origin: originStack || [this.traceName] }, (data: any, error: any) => {\n resolve({ data, error });\n });\n } else {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.HTTP_PUT, { relativeURL, data: putData, origin: originStack, originTraceName: this.traceName }, { timeout })\n .then((event: any) => {\n resolve({ data: event.data.data, error: event.data.error });\n })\n .catch((err) => {\n reject(null);\n });\n }\n });\n }\n\n /**\n * Fires or responds to an HTTP_DELETE event\n * @param relativeURL string - URL to fetch, relative to the mainframe URL\n * @param timeout - how long to attempt the request before reporting an error\n * @param originStack - the domain of the previous frame(s) the request originated from\n */\n public httpDELETE(relativeURL: string, timeout: number = 10000, originStack?: string[]): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n if (this._handlers[AppBridgeHandler.HTTP]) {\n this._handlers[AppBridgeHandler.HTTP]({ verb: HTTP_VERBS.DELETE, relativeURL, origin: originStack || [this.traceName] }, (data: any, error: any) => {\n resolve({ data, error });\n });\n } else {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.HTTP_DELETE, { relativeURL, origin: originStack, originTraceName: this.traceName }, { timeout })\n .then((event: any) => {\n resolve({ data: event.data.data, error: event.data.error });\n })\n .catch((err) => {\n reject(null);\n });\n }\n });\n }\n\n /**\n * Fires a custom event to anywhere in the application\n * @param event string - event name to fire\n * @param data any - data to be sent along with the event\n */\n public fireEvent(event: string, data: any): Promise<any> {\n return new Promise<any>((resolve, reject) => {\n this.postRobot\n .sendToParent(MESSAGE_TYPES.CUSTOM_EVENT, { event, data })\n .then((e: any) => {\n resolve(e);\n })\n .catch((err) => {\n reject(null);\n });\n });\n }\n\n /**\n * Fires a custom event to all registered frames\n * @param event string - event name to fire\n * @param data any - data to be sent along with the event\n */\n public fireEventToChildren(event: string, data: any): void {\n if (this._registeredFrames.length > 0) {\n this._registeredFrames.forEach((frame) => {\n this.postRobot.send(frame.source, MESSAGE_TYPES.CUSTOM_EVENT, {\n event,\n eventType: event,\n data,\n });\n });\n }\n }\n\n /**\n * Fires a custom event to specified frames\n * @param source Window - specific iframe contentWindow\n * @param event string - event name to fire\n * @param data any - data to be sent along with the event\n */\n public fireEventToChild(source: Window | HTMLIFrameElement, event: string, data: any): void {\n if (source instanceof HTMLIFrameElement) {\n source = source.contentWindow;\n }\n this.postRobot.send(source, MESSAGE_TYPES.CUSTOM_EVENT, { event, data });\n }\n\n /**\n * Adds an event listener to a custom event\n * @param event string - event name to listen to\n * @param callback function - callback to be fired when an event is caught\n */\n public addEventListener(event: string, callback: Function): void {\n if (!this._eventListeners[event]) {\n this._eventListeners[event] = [];\n }\n this._eventListeners[event].push(callback);\n }\n}\n\nexport class DevAppBridge extends AppBridge {\n private baseURL: string;\n\n constructor(traceName: string = 'DevAppBridge', private http: HttpClient, postRobotRef?: any) {\n super(traceName, postRobotRef);\n const cookie = this.getCookie('UlEncodedIdentity');\n if (cookie && cookie.length) {\n const identity = JSON.parse(decodeURIComponent(cookie));\n const endpoints = identity.sessions.reduce((obj, session) => {\n obj[session.name] = session.value.endpoint;\n return obj;\n }, {});\n this.baseURL = endpoints.rest;\n }\n }\n protected _setupHandlers(): void {}\n\n /**\n * Fires or responds to an HTTP_GET event\n */\n public httpGET(relativeURL: string): Promise<any> {\n return this.http.get(`${this.baseURL}/${relativeURL}`, { withCredentials: true }).toPromise();\n }\n\n /**\n * Fires or responds to an HTTP_POST event\n */\n public httpPOST(relativeURL: string, postData: any): Promise<any> {\n return this.http.post(`${this.baseURL}/${relativeURL}`, postData, { withCredentials: true }).toPromise();\n }\n\n /**\n * Fires or responds to an HTTP_PUT event\n */\n public httpPUT(relativeURL: string, putData: any): Promise<any> {\n return this.http.put(`${this.baseURL}/${relativeURL}`, putData, { withCredentials: true }).toPromise();\n }\n\n /**\n * Fires or responds to an HTTP_DELETE event\n */\n public httpDELETE(relativeURL: string): Promise<any> {\n return this.http.delete(`${this.baseURL}/${relativeURL}`, { withCredentials: true }).toPromise();\n }\n\n private getCookie(cname: string): any {\n if (document) {\n const name = `${cname}=`;\n const ca = document.cookie.split(';');\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n }\n }\n return false;\n }\n}\n","export class BaseRenderer {\n _data: any = {};\n _value: any = '';\n meta: any = {};\n\n get data() {\n return this._data;\n }\n\n set data(d: any) {\n this._data = d;\n }\n\n get value() {\n return this._value;\n }\n\n set value(v: any) {\n this._value = v;\n }\n}\n","/**\n * Copyright © 2022 Sasha Koss\n * https://www.npmjs.com/package/@date-fns/upgrade\n **/\n\ntype TokensMap = {\n [v1token: string]: string\n}\n\nconst tokensMap: TokensMap = {\n // 'D MMMM': '',\n // 'Do MMMM': '',\n // 'DD MMMM': '',\n M: 'L',\n Mo: 'Mo',\n MM: 'LL',\n MMM: 'LLL',\n MMMM: 'LLLL',\n Q: 'q',\n Qo: 'qo',\n D: 'd',\n Do: 'do',\n DD: 'dd',\n DDD: 'D',\n DDDo: 'Do',\n DDDD: 'DDD',\n d: 'i',\n do: 'io',\n dd: 'iiiiii',\n ddd: 'iii',\n dddd: 'iiii',\n A: 'a',\n a: 'a',\n aa: 'aaaa',\n E: 'i',\n W: 'I',\n Wo: 'Io',\n WW: 'II',\n YY: 'yy',\n YYYY: 'yyyy',\n GG: 'RR',\n GGGG: 'RRRR',\n H: 'H',\n HH: 'HH',\n h: 'h',\n hh: 'hh',\n m: 'm',\n mm: 'mm',\n s: 's',\n ss: 'ss',\n S: 'S',\n SS: 'SS',\n SSS: 'SSS',\n Z: 'xxx',\n ZZ: 'xx',\n X: 't',\n x: 'T',\n}\n\nconst v1tokens = Object.keys(tokensMap)\n .sort()\n .reverse()\n\nconst tokensRegExp = new RegExp(\n '(\\\\[[^\\\\[]*\\\\])|(\\\\\\\\)?' + '(' + v1tokens.join('|') + '|.)',\n 'g',\n)\n\ntype TokensBuffer = {\n formatBuffer: string[]\n textBuffer: string[]\n}\n\nexport function convertTokens(format: string): string {\n const tokensCaptures = format.match(tokensRegExp)\n if (tokensCaptures) {\n return tokensCaptures\n .reduce(\n (acc, tokenString, index) => {\n const v2token = tokensMap[tokenString]\n\n if (!v2token) {\n const escapedCaptures = tokenString.match(/^\\[(.+)\\]$/)\n if (escapedCaptures) {\n acc.textBuffer.push(escapedCaptures[1])\n } else {\n acc.textBuffer.push(tokenString)\n }\n }\n\n const endOfString = index === tokensCaptures.length - 1\n if (acc.textBuffer.length && (v2token || endOfString)) {\n acc.formatBuffer.push(`'${acc.textBuffer.join('')}'`)\n acc.textBuffer = []\n }\n\n if (v2token) acc.formatBuffer.push(v2token) // eslint-disable-line\n\n return acc\n },\n { formatBuffer: [], textBuffer: [] } as TokensBuffer,\n )\n .formatBuffer.join('')\n } else {\n return format\n }\n}\n","/**\n * Copyright © 2022 Sasha Koss\n * https://www.npmjs.com/package/@date-fns/upgrade\n **/\n\nimport { isDate } from 'date-fns'\n\nconst MILLISECONDS_IN_HOUR = 3600000\nconst MILLISECONDS_IN_MINUTE = 60000\nconst DEFAULT_ADDITIONAL_DIGITS = 2\n\nconst parseTokenDateTimeDelimeter = /[T ]/\nconst parseTokenPlainTime = /:/\n\n// year tokens\nconst parseTokenYY = /^(\\d{2})$/\nconst parseTokensYYY = [\n /^([+-]\\d{2})$/, // 0 additional digits\n /^([+-]\\d{3})$/, // 1 additional digit\n /^([+-]\\d{4})$/, // 2 additional digits\n]\n\nconst parseTokenYYYY = /^(\\d{4})/\nconst parseTokensYYYYY = [\n /^([+-]\\d{4})/, // 0 additional digits\n /^([+-]\\d{5})/, // 1 additional digit\n /^([+-]\\d{6})/, // 2 additional digits\n]\n\n// date tokens\nconst parseTokenMM = /^-(\\d{2})$/\nconst parseTokenDDD = /^-?(\\d{3})$/\nconst parseTokenMMDD = /^-?(\\d{2})-?(\\d{2})$/\nconst parseTokenWww = /^-?W(\\d{2})$/\nconst parseTokenWwwD = /^-?W(\\d{2})-?(\\d{1})$/\n\n// time tokens\nconst parseTokenHH = /^(\\d{2}([.,]\\d*)?)$/\nconst parseTokenHHMM = /^(\\d{2}):?(\\d{2}([.,]\\d*)?)$/\nconst parseTokenHHMMSS = /^(\\d{2}):?(\\d{2}):?(\\d{2}([.,]\\d*)?)$/\n\n// timezone tokens\nconst parseTokenTimezone = /([Z+-].*)$/\nconst parseTokenTimezoneZ = /^(Z)$/\nconst parseTokenTimezoneHH = /^([+-])(\\d{2})$/\nconst parseTokenTimezoneHHMM = /^([+-])(\\d{2}):?(\\d{2})$/\n\nexport type LegacyParseOptions = {\n additionalDigits?: 0 | 1 | 2\n}\n\nexport function legacyParse(\n argument: any,\n options: LegacyParseOptions = {},\n): Date {\n if (isDate(argument)) {\n // Prevent the date to lose the milliseconds when passed to new Date() in IE10\n return new Date(argument.getTime())\n } else if (typeof argument !== 'string') {\n return new Date(argument)\n }\n\n const additionalDigits =\n options.additionalDigits == null\n ? DEFAULT_ADDITIONAL_DIGITS\n : Number(options.additionalDigits)\n\n const dateStrings = splitDateString(argument)\n\n const parseYearResult = parseYear(dateStrings.date || '', additionalDigits)\n const year = parseYearResult.year\n const restDateString = parseYearResult.restDateString\n\n const date = parseDate(restDateString || '', year)\n\n if (date) {\n const timestamp = date.getTime()\n let time = 0\n let offset\n\n if (dateStrings.time) {\n time = parseTime(dateStrings.time) || 0\n }\n\n if (dateStrings.timezone) {\n offset = parseTimezone(dateStrings.timezone) * MILLISECONDS_IN_MINUTE\n } else {\n const fullTime = timestamp + time\n const fullTimeDate = new Date(fullTime)\n\n offset = getTimezoneOffsetInMilliseconds(fullTimeDate)\n\n // Adjust time when it's coming from DST\n const fullTimeDateNextDay = new Date(fullTime)\n fullTimeDateNextDay.setDate(fullTimeDate.getDate() + 1)\n const offsetDiff =\n getTimezoneOffsetInMilliseconds(fullTimeDateNextDay) -\n getTimezoneOffsetInMilliseconds(fullTimeDate)\n if (offsetDiff > 0) {\n offset += offsetDiff\n }\n }\n\n return new Date(timestamp + time + offset)\n } else {\n return new Date(argument)\n }\n}\n\ntype DateStrings = {\n date: string | undefined\n time: string | undefined\n timezone: string | undefined\n}\n\nexport function splitDateString(dateString: string): DateStrings {\n const array = dateString.split(parseTokenDateTimeDelimeter)\n let timeString;\n let date;\n let time;\n let timezone;\n\n if (parseTokenPlainTime.test(array[0])) {\n date = undefined\n timeString = array[0]\n } else {\n date = array[0]\n timeString = array[1]\n }\n\n if (timeString) {\n const token = parseTokenTimezone.exec(timeString)\n if (token) {\n time = timeString.replace(token[1], '')\n timezone = token[1]\n } else {\n time = timeString\n }\n }\n\n return {\n date,\n time,\n timezone,\n }\n}\n\nfunction parseYear(dateString: string, additionalDigits: number) {\n const parseTokenYYY = parseTokensYYY[additionalDigits]\n const parseTokenYYYYY = parseTokensYYYYY[additionalDigits]\n\n let token\n\n // YYYY or ±YYYYY\n token = parseTokenYYYY.exec(dateString) || parseTokenYYYYY.exec(dateString)\n if (token) {\n const yearString = token[1]\n return {\n year: parseInt(yearString, 10),\n restDateString: dateString.slice(yearString.length),\n }\n }\n\n // YY or ±YYY\n token = parseTokenYY.exec(dateString) || parseTokenYYY.exec(dateString)\n if (token) {\n const centuryString = token[1]\n return {\n year: parseInt(centuryString, 10) * 100,\n restDateString: dateString.slice(centuryString.length),\n }\n }\n\n // Invalid ISO-formatted year\n return {\n year: null,\n }\n}\n\nfunction parseDate(dateString: string, year: number | null) {\n // Invalid ISO-formatted year\n if (year === null) {\n return null\n }\n\n let token\n let date\n let month\n let week\n\n // YYYY\n if (dateString.length === 0) {\n date = new Date(0)\n date.setUTCFullYear(year)\n return date\n }\n\n // YYYY-MM\n token = parseTokenMM.exec(dateString)\n if (token) {\n date = new Date(0)\n month = parseInt(token[1], 10) - 1\n date.setUTCFullYear(year, month)\n return date\n }\n\n // YYYY-DDD or YYYYDDD\n token = parseTokenDDD.exec(dateString)\n if (token) {\n date = new Date(0)\n const dayOfYear = parseInt(token[1], 10)\n date.setUTCFullYear(year, 0, dayOfYear)\n return date\n }\n\n // YYYY-MM-DD or YYYYMMDD\n token = parseTokenMMDD.exec(dateString)\n if (token) {\n date = new Date(0)\n month = parseInt(token[1], 10) - 1\n const day = parseInt(token[2], 10)\n date.setUTCFullYear(year, month, day)\n return date\n }\n\n // YYYY-Www or YYYYWww\n token = parseTokenWww.exec(dateString)\n if (token) {\n week = parseInt(token[1], 10) - 1\n return dayOfISOYear(year, week)\n }\n\n // YYYY-Www-D or YYYYWwwD\n token = parseTokenWwwD.exec(dateString)\n if (token) {\n week = parseInt(token[1], 10) - 1\n const dayOfWeek = parseInt(token[2], 10) - 1\n return dayOfISOYear(year, week, dayOfWeek)\n }\n\n // Invalid ISO-formatted date\n return null\n}\n\nfunction parseTime(timeString: string) {\n let token\n let hours\n let minutes\n\n // hh\n token = parseTokenHH.exec(timeString)\n if (token) {\n hours = parseFloat(token[1].replace(',', '.'))\n return (hours % 24) * MILLISECONDS_IN_HOUR\n }\n\n // hh:mm or hhmm\n token = parseTokenHHMM.exec(timeString)\n if (token) {\n hours = parseInt(token[1], 10)\n minutes = parseFloat(token[2].replace(',', '.'))\n return (\n (hours % 24) * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE\n )\n }\n\n // hh:mm:ss or hhmmss\n token = parseTokenHHMMSS.exec(timeString)\n if (token) {\n hours = parseInt(token[1], 10)\n minutes = parseInt(token[2], 10)\n const seconds = parseFloat(token[3].replace(',', '.'))\n return (\n (hours % 24) * MILLISECONDS_IN_HOUR +\n minutes * MILLISECONDS_IN_MINUTE +\n seconds * 1000\n )\n }\n\n // Invalid ISO-formatted time\n return null\n}\n\nfunction parseTimezone(timezoneString: string) {\n let token\n let absoluteOffset\n\n // Z\n token = parseTokenTimezoneZ.exec(timezoneString)\n if (token) {\n return 0\n }\n\n // ±hh\n token = parseTokenTimezoneHH.exec(timezoneString)\n if (token) {\n absoluteOffset = parseInt(token[2], 10) * 60\n return token[1] === '+' ? -absoluteOffset : absoluteOffset\n }\n\n // ±hh:mm or ±hhmm\n token = parseTokenTimezoneHHMM.exec(timezoneString)\n if (token) {\n absoluteOffset = parseInt(token[2], 10) * 60 + parseInt(token[3], 10)\n return token[1] === '+' ? -absoluteOffset : absoluteOffset\n }\n\n return 0\n}\n\nfunction dayOfISOYear(isoYear: number, week = 0, day = 0) {\n const date = new Date(0)\n date.setUTCFullYear(isoYear, 0, 4)\n const fourthOfJanuaryDay = date.getUTCDay() || 7\n const diff = week * 7 + day + 1 - fourthOfJanuaryDay\n date.setUTCDate(date.getUTCDate() + diff)\n return date\n}\n\nfunction getTimezoneOffsetInMilliseconds(dirtyDate: Date) {\n const date = new Date(dirtyDate.getTime())\n const baseTimezoneOffset = date.getTimezoneOffset()\n date.setSeconds(0, 0)\n const millisecondsPartOfTimezoneOffset =\n date.getTime() % MILLISECONDS_IN_MINUTE\n\n return (\n baseTimezoneOffset * MILLISECONDS_IN_MINUTE +\n millisecondsPartOfTimezoneOffset\n )\n}\n","import {\n Day,\n addDays, addMonths, addWeeks,\n differenceInCalendarDays, differenceInDays,\n differenceInSeconds, endOfDay, endOfMonth, endOfWeek, format, getMonth, getYear,\n isAfter, isBefore, isSameDay, isSameMonth, isSameSecond, isWithinInterval,\n setHours, setMinutes, startOfDay, startOfMinute, startOfMonth, startOfWeek,\n} from 'date-fns';\nimport { convertTokens } from './convert-tokens';\nimport { LegacyParseOptions, legacyParse } from './legacy-parse';\n\ntype DateLike = Date | string | number;\n\nexport interface DateParseOptions extends LegacyParseOptions {\n userDateFormat?: string;\n}\n\n/**\n * This DateUtil is a wrapper for calling new date-fns v2 functions with existing legacy\n * v1 function calls without having to refactor too much code and potentially introduce\n * breaking changes.\n *\n * The old calls generally called date-fns functions with loosely-typed date values, often\n * of type DateLike (Date | string | number). This was a problem when upgrading to date-fns\n * v2 since functions are now typed more strongly and no longer accept strings.\n *\n * If you are adding a new component/feature and looking here to add a new date-fns wrapper\n * function, strongly consider not doing that and instead refactoring your code to not use\n * DateLike, and calling the date-fns function(s) directly.\n **/\nexport class DateUtil {\n static getDateFromAnyType(date: DateLike): Date | number {\n return legacyParse(date);\n }\n\n static getWeekDayFromNumber(weekDay: number | Day): Day {\n if (0 <= weekDay && weekDay <= 6) {\n return weekDay as Day;\n } else {\n console.warn('Invalid weekDay value:', weekDay);\n return 0;\n }\n }\n\n static parse(date: any, options?: DateParseOptions): Date {\n if (options?.userDateFormat && typeof date === 'string' && date.trim()) {\n date = this.rewireDatePositionsToMDY(date, options.userDateFormat);\n delete options.userDateFormat;\n }\n return legacyParse(date, options);\n }\n\n static format(date, formatString: string): string {\n if (!date) {\n return '';\n }\n date = this.getDateFromAnyType(date);\n formatString = convertTokens(formatString);\n return format(date, formatString);\n }\n\n static addDays(date, days: number): Date {\n date = this.getDateFromAnyType(date);\n return addDays(date, days);\n }\n\n static addWeeks(date, weeks: number): Date {\n date = this.getDateFromAnyType(date);\n return addWeeks(date, weeks);\n }\n\n static addMonths(date, months: number): Date {\n date = this.getDateFromAnyType(date);\n return addMonths(date, months);\n }\n\n static startOfMinute(date: DateLike): Date {\n date = this.getDateFromAnyType(date);\n return startOfMinute(date);\n }\n\n static startOfDay(date: DateLike): Date {\n date = this.getDateFromAnyType(date);\n return startOfDay(date);\n }\n\n static startOfWeek(date: DateLike, options?): Date {\n date = this.getDateFromAnyType(date);\n if (options?.weekStartsOn) {\n options.weekStartsOn = this.getWeekDayFromNumber(options.weekStartsOn);\n }\n return startOfWeek(date, options);\n }\n\n static startOfMonth(date: DateLike): Date {\n date = this.getDateFromAnyType(date);\n return startOfMonth(date);\n }\n\n static endOfDay(date: DateLike): Date {\n date = this.getDateFromAnyType(date);\n return endOfDay(date);\n }\n\n static endOfWeek(date: DateLike, options?): Date {\n date = this.getDateFromAnyType(date);\n if (options?.weekStartsOn) {\n options.weekStartsOn = this.getWeekDayFromNumber(options.weekStartsOn);\n }\n return endOfWeek(date, options);\n }\n\n static endOfMonth(date: DateLike): Date {\n date = this.getDateFromAnyType(date);\n return endOfMonth(date);\n }\n\n static isSameDay(dateLeft: DateLike, dateRight: DateLike): boolean {\n dateLeft = this.getDateFromAnyType(dateLeft);\n dateRight = this.getDateFromAnyType(dateRight);\n return isSameDay(dateLeft, dateRight);\n }\n\n static isSameMonth(dateLeft: DateLike, dateRight: DateLike): boolean {\n dateLeft = this.getDateFromAnyType(dateLeft);\n dateRight = this.getDateFromAnyType(dateRight);\n return isSameMonth(dateLeft, dateRight);\n }\n\n static isSameSecond(dateLeft: DateLike, dateRight: DateLike): boolean {\n dateLeft = this.getDateFromAnyType(dateLeft);\n dateRight = this.getDateFromAnyType(dateRight);\n return isSameSecond(dateLeft, dateRight);\n }\n\n static differenceInSeconds(date: DateLike, start: DateLike): number {\n date = this.getDateFromAnyType(date);\n start = this.getDateFromAnyType(start);\n return differenceInSeconds(date, start);\n }\n\n static differenceInCalendarDays(date: DateLike, start: DateLike): number {\n date = this.getDateFromAnyType(date);\n start = this.getDateFromAnyType(start);\n return differenceInCalendarDays(date, start);\n }\n\n static differenceInDays(date: DateLike, start: DateLike): number {\n date = this.getDateFromAnyType(date);\n start = this.getDateFromAnyType(start);\n return differenceInDays(date, start);\n }\n\n static isWithinRange(date: DateLike | null, start: DateLike, end: DateLike): boolean {\n date = this.getDateFromAnyType(date);\n const interval = {\n start: this.getDateFromAnyType(start),\n end: this.getDateFromAnyType(end),\n };\n\n /**\n * Need extra error handling here to retain backwards compatibility because the new\n * isWithinInterval replacement function throws an error for Invalid Dates and Invalid\n * Intervals instead of returning true or false.\n **/\n try {\n return isWithinInterval(date, interval);\n } catch (e) {\n console.warn(e.toString());\n return false;\n }\n }\n\n static getMonth(date: DateLike): number {\n date = this.getDateFromAnyType(date);\n return getMonth(date);\n }\n\n static getYear(date: DateLike): number {\n date = this.getDateFromAnyType(date);\n return getYear(date);\n }\n\n static setMinutes(date: DateLike, minutes: number) {\n date = this.getDateFromAnyType(date);\n return setMinutes(date, minutes);\n }\n\n static setHours(date: DateLike, hours: number) {\n date = this.getDateFromAnyType(date);\n return setHours(date, hours);\n }\n\n static isBefore(date: DateLike, minDate: Date | number): boolean {\n date = this.getDateFromAnyType(date);\n return isBefore(date, minDate);\n }\n\n static isAfter(date: DateLike, maxDate: Date | number): boolean {\n date = this.getDateFromAnyType(date);\n return isAfter(date, maxDate);\n }\n\n static rewireDatePositionsToMDY(dateStr: string, userDateFormat: string) {\n userDateFormat = userDateFormat.toUpperCase()\n if (userDateFormat === 'MM/DD/YYYY') {\n return dateStr;\n }\n const separatorPattern = /[.\\\\/-]/;\n // Creates an order, eg ['D', 'M', 'Y']\n const separatorChar = separatorPattern.exec(userDateFormat)[0];\n const tokenOrder = userDateFormat.split(separatorPattern).map(chars => chars[0]);\n if (tokenOrder.length < 3) {\n // Could not determine date token order from localized date format\n return dateStr;\n }\n const tokenSourceOrder = ['M', 'D', 'Y'].map(token => token