{ "version": 3, "sources": ["external-global:Serenity", "external-global:Slick", "../Modules/index.ts", "../Modules/GridEditing/GridEditController.ts", "../Modules/GridEditing/GridEditWrapper.ts", "../Modules/GridMixins/AutoColumnWidthMixin.ts", "../Modules/GridMixins/CardViewMixin.tsx", "../../../node_modules/.pnpm/jsx-dom@8.0.7/node_modules/jsx-dom/min/index.js", "../Modules/GridMixins/CustomSummaryMixin.ts", "../Modules/GridMixins/DraggableGroupingMixin.ts", "../Modules/GridMixins/DraggableGroupingPlugin.ts", "../Modules/GridMixins/EntityGridDialog.ts", "../Modules/GridMixins/FavoriteViewsMixin.ts", "../Modules/GridMixins/HeaderFiltersMixin.ts", "../Modules/GridMixins/HeaderFiltersPlugin.ts", "../Modules/Tools/IdleTimeout.ts", "../Modules/Tools/UIOverrides.ts", "../Modules/Translation/TranslationGrid.ts", "../Modules/Tools/CopyToClipboard.ts", "../Modules/Wizards/WizardDialog.ts", "../Modules/ServerTypes/Pro/Extensions.ElevateForm.ts", "../Modules/ServerTypes/Texts.ts", "../Modules/AccountElevation/ElevatePage.tsx", "../../../node_modules/.pnpm/jsx-dom@8.0.7/node_modules/jsx-dom/index.js"], "sourcesContent": ["module.exports = Serenity;", "module.exports = Slick;", "export * from \"./GridEditing/GridEditController\";\nexport * from \"./GridEditing/GridEditWrapper\";\nexport * from \"./GridMixins/AutoColumnWidthMixin\";\nexport * from \"./GridMixins/CardViewMixin\";\nexport * from \"./GridMixins/CustomSummaryMixin\";\nexport * from \"./GridMixins/DraggableGroupingMixin\";\nexport * from \"./GridMixins/DraggableGroupingPlugin\";\nexport * from \"./GridMixins/EntityGridDialog\";\nexport * from \"./GridMixins/FavoriteViewsMixin\";\nexport * from \"./GridMixins/HeaderFiltersMixin\";\nexport * from \"./GridMixins/HeaderFiltersPlugin\";\nexport * from \"./Tools/IdleTimeout\";\nexport * from \"./Tools/UIOverrides\";\nexport * from \"./Translation/TranslationGrid\";\nexport * from \"./Wizards/WizardDialog\";\nexport * from \"./AccountElevation/ElevatePage\"", "\uFEFFimport { DataGrid, EditorTypeRegistry, EntityGrid, ToolButton, Widget } from \"@serenity-is/corelib\";\nimport { deepClone, Dictionary, extend, getHighlightTarget, isBS3, notifyError, notifyWarning, PropertyItem, PropertyItemsData, SaveRequest, serviceRequest, tryFirst, tryGetText } from \"@serenity-is/corelib\";\nimport { CellStylesHash, Column, EditorClass, EditorFactory, EditorOptions, RowCell } from \"@serenity-is/sleekgrid\";\nimport { GridEditWrapper } from \"./GridEditWrapper\";\n\nexport interface GridEditOptions {\n grid: DataGrid;\n autoSave?: boolean;\n bulkSaveHandler?: (reqs: SaveRequest[]) => Promise;\n editable?: (args: { column: Column, item: TItem, row: number }) => boolean;\n editorParams?: object | ((args: { column: Column, item: TItem, slickArgs: EditorOptions }) => any);\n editorType?: (args: { column: Column, item: TItem, slickArgs: EditorOptions }) => {\n new (...args: any[]): Widget;\n },\n editorInit?: ((args: { editor: Widget, column: Column, item: TItem, slickArgs: EditorOptions }) => void);\n afterCommitEdit?: ((args: { column: Column, item: TItem, value: any, oldValue: any, row: number }) => void);\n refreshAfterSave?: boolean;\n resetOnLoad?: boolean;\n saveHandler?: (req: SaveRequest) => Promise;\n saveServiceMethod?: string;\n showValidationError?: boolean;\n undoRowDblEsc?: boolean;\n validator?: (value: any, args: EditorOptions) => string;\n}\n\nconst defaultGridEditOptions: Partial = {\n autoSave: false,\n refreshAfterSave: true,\n resetOnLoad: true,\n showValidationError: true,\n undoRowDblEsc: true\n} as const;\n\nexport class GridEditController implements EditorFactory {\n\n private _options: GridEditOptions;\n private dirtyStyles: CellStylesHash = {};\n\n constructor(opt: GridEditOptions) {\n this._options = opt = extend(extend({}, defaultGridEditOptions), opt) as GridEditOptions;\n\n opt.grid.slickGrid.setOptions({\n editable: true,\n editorFactory: this,\n enableCellNavigation: true,\n editorCellNavOnLRKeys: false,\n autoEdit: true,\n editCommandHandler: (item: any, column, command) => {\n var orig = item.__orig;\n if (orig == null)\n item.__orig = extend({}, item);\n var oldValue = item[column.field];\n command.execute();\n var value = item[column.field];\n this.options.afterCommitEdit?.({\n column: column,\n item,\n oldValue,\n value,\n row: command.row\n });\n this.updateModifiedClassesForRow(command.row);\n opt.grid[\"updateInterface\"]();\n\n if (opt.autoSave)\n this.saveChanges();\n }\n });\n\n var priorEscCell: RowCell;\n\n if (opt.undoRowDblEsc) {\n // cancel changes for current row on double escape<\n opt.grid.slickGrid.onKeyDown.subscribe(e => {\n if (e.key === \"Escape\" &&\n !opt.grid.slickGrid.getCellEditor()) {\n var activeCell = opt.grid.slickGrid.getActiveCell();\n if (activeCell != null &&\n activeCell.row >= 0 &&\n activeCell.cell >= 0 &&\n priorEscCell != null &&\n activeCell.row == priorEscCell.row &&\n activeCell.cell == priorEscCell.cell) {\n priorEscCell = null;\n this.undoRowChanges(activeCell.row);\n opt.grid.slickGrid.updateRow(activeCell.row);\n }\n else\n priorEscCell = activeCell;\n }\n else\n priorEscCell = null;\n });\n }\n\n if (opt.showValidationError) {\n opt.grid.slickGrid.onValidationError.subscribe((e, args) => {\n showValidationError(args.cellNode, args.validationResults.msg);\n });\n }\n\n if (opt.resetOnLoad) {\n opt.grid.view?.onDataLoaded.subscribe(() => {\n this.undoChanges();\n });\n }\n }\n\n updateModifiedClassesForRow(row: number) {\n var slick = this._options.grid.slickGrid;\n var item = slick.getDataItem(row);\n var orig = (item as any).__orig;\n if (orig == null)\n delete this.dirtyStyles[row];\n else {\n var styles = this.dirtyStyles[row];\n if (styles == null)\n this.dirtyStyles[row] = styles = {};\n var cols = slick.getColumns();\n for (var cell = 0; cell < cols.length; cell++) {\n var col = cols[cell];\n var field = col.editableProperty?.name ?? col.field;\n if (field == null ||\n !this.isFieldDirty(item, field))\n delete styles[col.id];\n else\n styles[col.id] = \"slick-cell-dirty\";\n }\n }\n slick.setCellCssStyles(\"dirtycells\", deepClone(this.dirtyStyles));\n }\n\n get options() {\n return this._options;\n }\n\n getEditor(column: Column, row: number): EditorClass {\n\n if (column.editableProperty == void 0 &&\n column.sourceItem &&\n column.sourceItem.filteringIdField != null) {\n var pid = this._options.grid[\"propertyItemsData\"] as PropertyItemsData;\n if (pid != null) {\n var idField = column.sourceItem.filteringIdField;\n column.editableProperty = tryFirst(pid.items || [], x => x.name == idField) ??\n tryFirst(pid.additionalItems || [], x => x.name == idField) ?? null;\n }\n }\n\n var propertyItem = column.editableProperty ?? column.sourceItem;\n\n if (propertyItem == null ||\n propertyItem.readOnly ||\n propertyItem.updatable === false ||\n EditorTypeRegistry.get(column.sourceItem.editorType ?? \"String\") == null)\n return null;\n \n if (this._options.editable != null) {\n var item = this._options.grid.slickGrid.getDataItem(row);\n var editable = this._options.editable({ column, item, row });\n if (editable !== void 0 && !editable)\n return null;\n }\n \n return GridEditWrapper;\n }\n\n isDirty() {\n var slick = this._options.grid?.slickGrid;\n if (!slick)\n return false;\n var dataLength = slick.getDataLength();\n for (var i = 0; i < dataLength; i++) {\n var item = slick.getDataItem(i);\n if (this.isItemDirty(item))\n return true;\n }\n return false;\n }\n\n isItemDirty(item: any) {\n return item && item.__orig &&\n Object.keys(item).some(key => key !== \"__orig\" && item.__orig[key] != item[key]);\n }\n\n isFieldDirty(item: any, field: string) {\n return item.__orig && (item.__orig[field] != item[field]);\n }\n\n undoRowChanges(row: number) {\n var item = this._options.grid.slickGrid.getDataItem(row);\n if (item && item.__orig) {\n var orig = item.__orig;\n for (var i in item)\n delete item[i];\n for (var i in orig)\n item[i] = orig[i];\n }\n this.updateModifiedClassesForRow(row);\n }\n\n undoChanges() {\n var slick = this._options.grid?.slickGrid;\n if (!slick)\n return;\n var dataLength = slick.getDataLength();\n for (var row = 0; row < dataLength; row++) {\n var item = slick.getDataItem(row);\n if (item.__orig)\n this.undoRowChanges(row);\n }\n for (var key in this.dirtyStyles)\n delete this.dirtyStyles[key];\n slick.setCellCssStyles(\"dirtycells\", deepClone(this.dirtyStyles));\n slick.invalidate();\n }\n\n saveChanges() {\n\n var slick = this._options.grid?.slickGrid;\n if (!slick)\n return;\n\n var dataLength = slick.getDataLength();\n var requests: Dictionary> = {};\n\n for (var row = 0; row < dataLength; row++) {\n var item = slick.getDataItem(row);\n if (this.isItemDirty(item)) {\n var request: SaveRequest = {\n EntityId: item.__orig[this._options.grid[\"getIdProperty\"]()],\n Entity: Object.create(null) as TItem\n };\n for (var field of Object.keys(item)) {\n if (field === \"__orig\")\n continue;\n if (this.isFieldDirty(item, field))\n request.Entity[field] = item[field];\n }\n if (Object.keys(request.Entity as any).length)\n requests[row] = request;\n }\n }\n\n var rows = Object.keys(requests);\n var current = -1;\n var self = this;\n\n (function saveNext() {\n if (++current >= rows.length) {\n self.undoChanges();\n if (self._options.refreshAfterSave)\n self._options.grid.refresh();\n self._options.grid[\"updateInterface\"]();\n return;\n }\n\n var row = parseInt(rows[current], 10);\n var request = requests[row];\n var item = self._options.grid.slickGrid.getDataItem(row);\n\n const then = () => {\n delete item.__orig;\n delete request[row];\n self.updateModifiedClassesForRow(row);\n saveNext();\n }\n\n const fail = () => {\n if (self._options.autoSave)\n self.undoRowChanges(row);\n self._options.grid[\"updateInterface\"]();\n }\n\n if (self._options.saveHandler) {\n self._options.saveHandler(request)\n .then(then)\n .catch(fail);\n }\n else {\n var serviceMethod = self._options.saveServiceMethod;\n\n if (serviceMethod == null) {\n var getService = (self._options.grid as EntityGrid)[\"getService\"];\n if (getService)\n serviceMethod = getService() + \"/Update\";\n }\n\n if (serviceMethod)\n serviceRequest(serviceMethod, request, then)\n .fail(fail);\n else\n notifyWarning(\"Save handler for edit controller is not defined!\");\n }\n })();\n }\n\n static saveChangesButton(controller: () => GridEditController): ToolButton {\n return {\n title: tryGetText('Controls.EntityGrid.SaveChangesButton') ?? \"Save Changes\",\n cssClass: 'apply-changes-button',\n disabled: () => !controller()?.isDirty(),\n onClick: () => controller()?.saveChanges(),\n separator: true\n }\n }\n\n static undoButton(controller: () => GridEditController): ToolButton {\n return {\n hint: tryGetText('Controls.EntityGrid.UndoChangesButton') ?? \"Undo Changes\",\n cssClass: 'undo-changes-button',\n icon: 'fa-undo',\n disabled: () => !controller()?.isDirty(),\n onClick: e => controller()?.undoChanges()\n }\n }\n}\n\nfunction showValidationError(el: HTMLElement, msg) {\n if (($.fn as any).tooltip) {\n var $el: any;\n var hl = getHighlightTarget(el);\n if (hl)\n $el = $(hl);\n else\n $el = $(el);\n\n ($.fn as any).tooltip && $el.tooltip({\n title: msg,\n trigger: 'manual'\n }).tooltip('show');\n\n window.setTimeout(function () {\n $el.tooltip(isBS3() ? 'destroy' : 'dispose');\n }, 1500);\n }\n else\n notifyError(msg);\n}\n\ndeclare module \"@serenity-is/sleekgrid\" {\n interface Column {\n editableProperty?: PropertyItem;\n }\n}", "import { Widget, EditorTypeRegistry, EditorUtils, Select2Editor, BooleanEditor, EnumEditor } from \"@serenity-is/corelib\";\nimport { extend, isInstanceOfType, localText, toId } from \"@serenity-is/corelib\";\nimport { Editor, EditorOptions, Grid, Position, ValidationResult } from \"@serenity-is/sleekgrid\";\nimport { GridEditController } from \"./GridEditController\";\n\nexport class GridEditWrapper implements Editor {\n private args: EditorOptions;\n private editor: Widget;\n private defaultValue: any;\n\n constructor(args: EditorOptions) {\n this.args = args;\n\n var controller = (args.grid as Grid).getOptions().editorFactory as GridEditController;\n var propertyItem = args.column.editableProperty ?? args.column.sourceItem;\n\n var editorParams = extend({}, propertyItem.editorParams);\n var ctrlEditorParams = controller?.options?.editorParams;\n if (ctrlEditorParams != null) {\n if (typeof ctrlEditorParams === \"function\")\n ctrlEditorParams = ctrlEditorParams({ column: args.column, item: args.item, slickArgs: args });\n editorParams = extend(editorParams, ctrlEditorParams);\n }\n\n var editorType = controller?.options?.editorType?.({\n column: args.column, item: args.item, slickArgs: args\n }) ?? EditorTypeRegistry.get(propertyItem.editorType ?? \"String\")\n ;\n\n var createOptions = {\n container: $(args.container),\n element: el => el.addClass('s-cell-editor'),\n type: editorType,\n options: editorParams\n }\n\n this.editor = Widget.create(createOptions);\n\n var maxLength = editorParams.maxLength ?? editorParams.maxlength ?? propertyItem?.maxLength;\n if (maxLength != null) {\n if (this.editor.element.is(':input')) {\n if (maxLength > 0) {\n this.editor.element?.attr('maxlength', maxLength);\n }\n else {\n this.editor.element?.removeAttr('maxlength');\n }\n } \n }\n\n this.editor.element.focus();\n this.editor.element[0][\"select\"]?.();\n\n controller?.options?.editorInit?.({\n column: args.column, editor: this.editor, item: args.item, slickArgs: args\n });\n }\n\n focus(): void {\n this.editor.element.focus();\n }\n\n isValueChanged(): boolean {\n return JSON.stringify(this.serializeValue()) !=\n JSON.stringify(this.defaultValue);\n }\n\n keyCaptureList?: number[];\n\n loadValue(source: any): void {\n const propertyItem = this.args.column.editableProperty ?? this.args.column.sourceItem;\n EditorUtils.loadValue(this.editor, propertyItem, source);\n this.defaultValue = this.serializeValue();\n }\n\n serializeValue() {\n const propertyItem = this.args.column.editableProperty ?? this.args.column.sourceItem;\n const target = Object.create(null);\n EditorUtils.saveValue(this.editor, propertyItem, target);\n\n if (isInstanceOfType(this.editor, EnumEditor)) {\n var value = target[propertyItem.name];\n if (typeof value === \"string\" && !isNaN(value as any)) {\n target[propertyItem.name] = toId(value);\n }\n }\n\n if (propertyItem.name !== this.args.column.field &&\n isInstanceOfType(this.editor, Select2Editor))\n target[this.args.column.field] = (this.editor as Select2Editor).text;\n\n return target;\n }\n\n applyValue(target: any, state: any): void {\n for (var k of Object.keys(state))\n target[k] = state[k];\n }\n\n position?(pos: Position): void {\n }\n\n preClick?(): void {\n if (this.args.column.sourceItem?.editorType == \"Boolean\")\n (this.editor as BooleanEditor).value = !(this.editor as BooleanEditor).value;\n }\n\n hide?(): void {\n }\n\n show?(): void {\n }\n\n validate?(): ValidationResult {\n const propertyItem = this.args.column.editableProperty ?? this.args.column.sourceItem;\n const value = EditorUtils.getValue(this.editor);\n if (propertyItem.required &&\n (value == null || (typeof value === \"string\" && !value.trim().length))) {\n return {\n valid: false,\n msg: localText(\"Validation.Required\")\n }\n }\n\n if (this.args.column.validator != null) {\n var result = this.args.column.validator(value, this.args);\n if (!result.valid)\n return result;\n }\n\n var controller = (this.args.grid as Grid).getOptions().editorFactory as GridEditController;\n if (controller &&\n controller.options?.validator) {\n var message = controller.options.validator(value, this.args);\n if (message != null)\n return { valid: false, msg: message };\n }\n\n return { valid: true, msg: null }\n }\n\n destroy() {\n this.editor?.destroy();\n }\n}", "\uFEFFimport { DataGrid, Decorators, GridPersistanceFlags, LazyLoadHelper, PersistedGridSettings, Widget } from \"@serenity-is/corelib\";\nimport { htmlEncode } from \"@serenity-is/corelib\";\nimport { Column, Grid } from \"@serenity-is/sleekgrid\";\n\nexport interface AutoColumnWidthMixinOptions {\n grid: DataGrid;\n /** Disable auto size on load behavior, default is false, user can stil auto size by double click */\n disabled?: boolean;\n /** True to just auto size once on load, not on every load, like after changing pages, sorting etc, default is false */\n autoSizeAllJustOnce?: boolean;\n /** Disable auto size on load behavior if user manually resizes a column, default is true */\n disableIfUserResize?: boolean;\n /** If column has an explicit width set in Form.cs, use that width on auto size, doesn't effect manually triggered auto size */\n useExplicitWidths?: () => boolean;\n /** Set to true if headers shouldn't affect auto width, default is false.\n * If passed a number, header are considered for auto width but only up to that \n * number, e.g. if you pass 200, and header width is 300, 200 will be used */\n ignoreHeaders?: boolean | number;\n /** Maximum rows to scan in data source, default is 40*/\n maxRows?: number;\n /** Maximum auto column width, default value is 400 */\n maxWidth?: number;\n /** Minimum auto column width, default value is 30 */\n minWidth?: number;\n /** Callback used before user auto size all columns */\n beforeUserAutoSizeAll?: () => void;\n /** Callback used after user auto size all columns */\n afterUserAutoSizeAll?: () => void;\n /** extra delta for input border and padding */\n inputDelta?: number;\n}\n\n/**\n * A mixin that can be applied to a DataGrid for auto size column width functionality\n */\n@Decorators.registerClass(\"Serenity.AutoColumnWidthMixin\")\nexport class AutoColumnWidthMixin extends Widget {\n\n private slickGrid: Grid;\n private $container: JQuery;\n private autoSizing: number = 0;\n private inputDelta: number;\n private markupReadyOnce: boolean;\n private oldMarkupReady: () => void;\n private oldPersistSettings: (flags?: GridPersistanceFlags) => void;\n private oldGetCurrentSettings: (flags?: GridPersistanceFlags) => PersistedGridSettings;\n private oldRestoreSettingsFrom: (settings?: PersistedGridSettings, flags?: GridPersistanceFlags) => void;\n public disabled: boolean;\n\n private columnResizeHandler = () => {\n if (!this.autoSizing && (this.options.disableIfUserResize ?? true))\n this.disabled = true;\n }\n\n constructor(options: AutoColumnWidthMixinOptions) {\n super(options.grid.element, options);\n\n if (options.disabled != null)\n this.disabled = !!options.disabled;\n\n this.slickGrid = options.grid.slickGrid;\n this.$container = $((this.slickGrid as any).getContainerNode());\n\n this.$container.on('dblclick.' + this.uniqueName, '.slick-resizable-handle', (e) => this.resizeHandleClick(e));\n this.slickGrid.onColumnsResized.subscribe(this.columnResizeHandler);\n var self = this;\n\n this.oldMarkupReady = options.grid['markupReady'];\n options.grid['markupReady'] = function () {\n self.oldMarkupReady && self.oldMarkupReady.call(this);\n if (!self.disabled && (!self.markupReadyOnce || !self.options.autoSizeAllJustOnce))\n self.autoSizeAll(self.disabled != null ? false : null);\n self.markupReadyOnce = true;\n };\n\n this.oldPersistSettings = options.grid['persistSettings'];\n options.grid['persistSettings'] = function (flags?: GridPersistanceFlags) {\n if (self.autoSizing)\n return;\n return self.oldPersistSettings.call(this, flags);\n };\n\n this.oldGetCurrentSettings = options.grid['getCurrentSettings'];\n options.grid['getCurrentSettings'] = function (flags?: GridPersistanceFlags): PersistedGridSettings {\n flags = flags || this.gridPersistanceFlags();\n flags.columnWidths = flags.columnWidths ?? !!self.disabled;\n return self.oldGetCurrentSettings.call(this, flags);\n }\n\n this.oldRestoreSettingsFrom = options.grid['restoreSettingsFrom'];\n options.grid['restoreSettingsFrom'] = function (settings: PersistedGridSettings, flags?: GridPersistanceFlags) {\n var myFlags = flags || this.gridPersistanceFlags();\n\n if (settings != null &&\n settings.columns &&\n (myFlags.columnWidths || settings.columns.some(x => x.width != null)))\n self.disabled = true;\n\n self.oldRestoreSettingsFrom.call(this, settings, flags);\n }\n\n this.inputDelta = options.inputDelta ?? 8;\n\n if (!this.disabled)\n this.autoSizeAll();\n }\n\n destroy() {\n if (this.options && this.options.grid) {\n this.options.grid.element.off('.' + this.uniqueName);\n this.options.grid['markupReady'] = this.oldMarkupReady;\n }\n\n this.slickGrid && this.slickGrid.onColumnsResized.unsubscribe(this.columnResizeHandler);\n\n this.options = null;\n this.slickGrid = null;\n this.$container = null;\n super.destroy();\n }\n\n\n private resizeHandleClick(e: JQueryEventObject) {\n if (e.ctrlKey) {\n e.preventDefault();\n e.stopPropagation();\n this.options.beforeUserAutoSizeAll && this.options.beforeUserAutoSizeAll();\n this.autoSizeAll(false);\n this.options.afterUserAutoSizeAll && this.options.afterUserAutoSizeAll();\n this.disabled = false;\n return;\n }\n\n var $header = $(e.currentTarget).closest('.slick-header-column');\n var columnDef = $header.data('column') as Column;\n\n if (!columnDef || !columnDef.resizable)\n return;\n\n e.preventDefault();\n e.stopPropagation();\n\n this.autoSizeColumn($header, columnDef);\n }\n\n private createCellNodes(sb: string[]): HTMLDivElement[] {\n const row = document.createElement('div');\n row.classList.add('slick-row', 's-offscreen');\n row.style.visibility = 'hidden';\n\n row.innerHTML = sb.join('');\n if (row.childNodes.length > 0)\n this.slickGrid.getCanvasNode().appendChild(row);\n\n if (Array[\"from\"])\n return Array[\"from\"](row.childNodes) as HTMLDivElement[];\n\n var childNodes = row.childNodes;\n var length = row.childNodes.length;\n var cellNodes: HTMLDivElement[] = [];\n for (var i = 0; i < length; i++)\n cellNodes.push(childNodes[i] as HTMLDivElement);\n\n return cellNodes;\n }\n\n private calcMaxWidthFromCellNodes(cellNodes: HTMLDivElement[], columnDef: Column, header: HTMLElement) {\n var maxAllowedWidth = columnDef.maxWidth > 0 ? columnDef.maxWidth : this.options.maxWidth;\n var maxWidth = 0;\n\n for (let index = 0; index < cellNodes.length; index++) {\n const cellNode = cellNodes[index];\n\n var width = cellNode.offsetWidth +\n (cellNode.dataset?.isInputNode === \"1\" ? (this.inputDelta ?? 0) : 0);\n\n if (width > maxWidth)\n maxWidth = width;\n\n if (maxAllowedWidth > 0 && width >= maxAllowedWidth)\n break;\n }\n\n var autoWidth = maxWidth || 0;\n\n if (typeof this.options.ignoreHeaders == \"number\") {\n autoWidth = Math.max(Math.min(this.options.ignoreHeaders, header.offsetWidth, autoWidth));\n }\n else if (!this.options.ignoreHeaders) {\n autoWidth = Math.max(header.offsetWidth, autoWidth);\n }\n\n autoWidth = (autoWidth || 0) + 1;\n\n if (columnDef.maxWidth > 0)\n autoWidth = Math.min(autoWidth, columnDef.maxWidth);\n else\n autoWidth = Math.min(autoWidth, this.options.maxWidth || 400);\n\n if (columnDef.minWidth > 0)\n autoWidth = Math.max(autoWidth, columnDef.minWidth);\n else\n autoWidth = Math.max(autoWidth, this.options.minWidth || 30);\n\n return autoWidth;\n }\n\n private getAutoColumnWidth($header: JQuery, columnDef: Column) {\n var colIndex = this.slickGrid.getColumnIndex(columnDef.id);\n var sb: string[] = [];\n this.renderColumnCells(sb, columnDef, colIndex, this.getMaxCalcLength());\n const cellNodes = this.createCellNodes(sb);\n try {\n let headerClone: HTMLElement;\n if (!this.options.ignoreHeaders)\n headerClone = createHeaderClone($header[0]);\n\n try {\n return this.calcMaxWidthFromCellNodes(cellNodes, columnDef, headerClone)\n } finally {\n headerClone?.parentElement?.removeChild(headerClone);\n }\n }\n finally {\n var rowNode = cellNodes[0]?.parentElement;\n rowNode && rowNode.parentElement.removeChild(rowNode);\n }\n }\n\n private autoSizeColumn($header: JQuery, columnDef: Column) {\n const autoWidth = this.getAutoColumnWidth($header, columnDef);\n\n if (autoWidth !== columnDef.width) {\n this.autoSizing++;\n try {\n columnDef.width = autoWidth;\n this.slickGrid.setColumns(this.slickGrid.getColumns());\n this.slickGrid.onColumnsResized.notify();\n }\n finally {\n this.autoSizing--;\n }\n }\n }\n\n private queueAutoSize: number = 0;\n\n public autoSizeAll(useExplicitWidths?: boolean) {\n if (!this.$container.is(':visible')) {\n\n if (this.queueAutoSize <= 0) {\n this.queueAutoSize++;\n LazyLoadHelper.executeOnceWhenShown(this.$container, () => this.autoSizeAll(useExplicitWidths));\n }\n\n return;\n }\n\n if (this.queueAutoSize > 0) {\n this.queueAutoSize--;\n }\n\n this.autoSizing++;\n try {\n\n var $headers = this.$container.find(\".slick-header-column\");\n useExplicitWidths = useExplicitWidths ?? (this.options.useExplicitWidths && this.options.useExplicitWidths());\n var maxRows = this.getMaxCalcLength();\n let sb: string[] = [];\n const headerClones: HTMLElement[] = [];\n\n try {\n $headers.each((index, el) => {\n var columnDef = $(el).data('column') as Column;\n if (columnDef && this.getPreSetWidth(columnDef) == null) {\n var colIndex = this.slickGrid.getColumnIndex(columnDef.id);\n this.renderColumnCells(sb, columnDef, colIndex, maxRows);\n }\n else {\n for (var i = 0; i < maxRows; i++)\n sb.push('
');\n }\n\n if (!this.options.ignoreHeaders)\n headerClones.push(createHeaderClone(el as HTMLElement));\n });\n\n let allCellNodes = this.createCellNodes(sb);\n try {\n\n $headers.each((index, el) => {\n var columnDef = $(el).data('column') as Column;\n if (!columnDef)\n return;\n\n var cellNodes = allCellNodes.slice(index * maxRows, (index + 1) * maxRows);\n\n var autoWidth = this.getPreSetWidth(columnDef);\n if (autoWidth == null) {\n autoWidth = this.calcMaxWidthFromCellNodes(cellNodes, columnDef, headerClones[index]);\n }\n columnDef.width = autoWidth;\n });\n }\n finally {\n var rowNode = allCellNodes[0]?.parentElement;\n rowNode && rowNode.parentElement?.removeChild(rowNode);\n }\n } finally {\n headerClones.forEach(el => el?.parentElement?.removeChild(el));\n }\n\n this.slickGrid.setColumns(this.slickGrid.getColumns());\n this.slickGrid.onColumnsResized.notify();\n }\n finally {\n this.autoSizing--;\n }\n }\n\n private getMaxCalcLength() {\n var length = this.slickGrid.getDataLength();\n if ((this.options.maxRows ?? 40) < length)\n length = this.options.maxRows ?? 40;\n return length;\n }\n\n private renderColumnCells(sb: string[], columnDef: Column, colIndex: number, maxRows: number) {\n\n for (var i = 0; i < maxRows; i++) {\n sb.push('
');\n continue;\n }\n\n var format = this.slickGrid.getFormatter(i, columnDef);\n var ctx = this.slickGrid.getFormatterContext(i, colIndex);\n let child: HTMLInputElement;\n let childHtml: string;\n\n if (format) {\n try {\n childHtml = format(ctx);\n }\n catch (ex) {\n childHtml = htmlEncode(item[columnDef.field] ?? '');\n }\n }\n else\n childHtml = htmlEncode(item[columnDef.field]);\n\n if (childHtml?.length > 5 && childHtml.substring(0, 6) == \"', htmlEncode(child.value), '');\n continue;\n }\n }\n\n sb.push('>', childHtml, '');\n }\n }\n\n getPreSetWidth(columnDef: Column): number {\n if (this.options.useExplicitWidths && columnDef.sourceItem && columnDef.sourceItem.width > 0 && columnDef.sourceItem.widthSet)\n return columnDef.sourceItem.width;\n }\n}\n\nfunction createHeaderClone(element: HTMLElement): HTMLElement {\n const clone = element.cloneNode(true) as HTMLElement;\n clone.style.cssText = 'position: absolute; visibility: hidden; right: auto; text-overflow: initial; white-space: nowrap;';\n element.parentNode.insertBefore(clone, element);\n\n return clone;\n}", "\uFEFF/** @jsxImportSource jsx-dom/min */\nimport { DataGrid, GridPersistanceFlags, PersistedGridSettings } from \"@serenity-is/corelib\";\nimport { getGlobalThis, localText, trimToNull } from \"@serenity-is/corelib\";\n\nexport type CardViewType = \"card\" | \"grid\";\n\nexport interface CardViewMixinOptions {\n grid: DataGrid;\n /* This can also return a React JSX VDOM but in that case ReactDOM \n should be available in the global namespace */\n renderItem: (item: TItem, index: number) => HTMLElement | any;\n viewType?: CardViewType;\n cardClass?: string;\n}\n\n/**\n * A mixin that can be applied to a DataGrid for card view functionality\n */\nexport class CardViewMixin {\n\n private dataGrid: DataGrid;\n private cardContainer: JQuery;\n\n constructor(private options: CardViewMixinOptions) {\n var dg = this.dataGrid = options.grid;\n\n var btnGroup = $(\n
\n \n \n \n \n \n \n
\n ).prependTo(dg.element.find('.grid-title'));\n\n this.cardContainer = $('
')\n .insertAfter(dg.element.children('.grid-container'));\n\n btnGroup.find('[data-view]').click((e) => {\n this.switchView($(e.target).closest('[data-view]').attr('data-view') as CardViewType);\n });\n\n if (options.viewType)\n this.switchView(this.options.viewType, false);\n\n this.resizeCardView();\n\n dg.element.bind('layout', () => this.resizeCardView());\n\n (dg.view as any).onDataChanged.subscribe(() => {\n this.updateCardItems();\n });\n\n var oldCurrentSettings = (dg as any).getCurrentSettings;\n (dg as any).getCurrentSettings = function (flag: GridPersistanceFlags) {\n var settings = oldCurrentSettings.apply(dg, [flag]);\n settings['viewType'] = btnGroup.find('[data-view].active').val();\n return settings;\n };\n\n var self = this;\n var oldRestoreSettingsFrom = (dg as any).restoreSettingsFrom;\n (dg as any).restoreSettingsFrom = function (settings: PersistedGridSettings, flags?: GridPersistanceFlags) {\n oldRestoreSettingsFrom.apply(dg, [settings, flags]);\n var viewType = (settings as any)?.viewType;\n if (viewType == \"card\" ||\n viewType == \"list\")\n self.switchView(viewType, false);\n };\n }\n\n public switchView(viewType: CardViewType, persist: boolean = true) {\n\n var button = this.dataGrid.element\n .find('.btn[data-view=\"' + viewType + '\"]');\n\n button.addClass('active').siblings('.active').not(button).removeClass('active');\n\n var card = viewType == 'card';\n this.dataGrid.element.children('.card-container').toggle(card);\n this.dataGrid.element.children('.grid-container').toggle(!card);\n\n if (card)\n this.updateCardItems();\n\n if (persist)\n (this.dataGrid as any).persistSettings();\n\n this.dataGrid.element.trigger('layout');\n }\n\n private updateCardItems() {\n const colClass = this.options.cardClass ?? \"col-12 col-md-6 col-lg-6 col-xxl-4\";\n\n $(this.cardContainer[0]).html('').append(\n
\n {this.dataGrid.getItems().map((item, index) =>\n
\n
{\n var node = this.options.renderItem(item, index);\n if (node instanceof HTMLElement) {\n el.appendChild(node);\n }\n else {\n getGlobalThis()?.ReactDOM.render(node as any, el);\n }\n }}>
\n
\n )}\n
\n );\n }\n\n private resizeCardView() {\n var gc = this.dataGrid.element.children('.grid-container');\n if (!gc.is(':visible'))\n return;\n var height = gc.height();\n if (height) {\n this.dataGrid.element.children('.card-container').css({\n height: height + 'px'\n });\n }\n }\n}", "/* eslint-disable */\nconst keys = Object.keys\nfunction identity(value) {\n return value\n}\nfunction isBoolean(val) {\n return typeof val === \"boolean\"\n}\nfunction isElement(val) {\n return val && typeof val.nodeType === \"number\"\n}\nfunction isString(val) {\n return typeof val === \"string\"\n}\nfunction isNumber(val) {\n return typeof val === \"number\"\n}\nfunction isObject(val) {\n return typeof val === \"object\" ? val !== null : isFunction(val)\n}\nfunction isFunction(val) {\n return typeof val === \"function\"\n}\nfunction isComponentClass(Component) {\n const { prototype } = Component\n return !!(prototype && prototype.isReactComponent)\n}\nfunction isArrayLike(obj) {\n return isObject(obj) && typeof obj.length === \"number\" && typeof obj.nodeType !== \"number\"\n}\nfunction forEach(value, fn) {\n if (!value) return\n for (const key of keys(value)) {\n fn(value[key], key)\n }\n}\n\nfunction createRef() {\n return Object.seal({\n current: null,\n })\n}\nfunction isRef(maybeRef) {\n return isObject(maybeRef) && \"current\" in maybeRef\n}\n\nconst jsxDomType = Symbol.for(\"jsx-dom:type\")\nvar JsxDomType = /*#__PURE__*/ (function (JsxDomType) {\n JsxDomType[\"ShadowRoot\"] = \"ShadowRoot\"\n return JsxDomType\n})(JsxDomType || {})\nfunction ShadowRoot(_ref) {\n let { children, ref, ...attr } = _ref\n return {\n [jsxDomType]: JsxDomType.ShadowRoot,\n ref,\n attr,\n children,\n }\n}\nfunction isShadowRoot(el) {\n return el != null && el[jsxDomType] === JsxDomType.ShadowRoot\n}\n\nconst SVGNamespace = \"http://www.w3.org/2000/svg\"\n\n// https://facebook.github.io/react/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored\n// Emulate JSX Expression logic to ignore certain type of children or className.\nfunction isVisibleChild(value) {\n return !isBoolean(value) && value != null\n}\nconst DomTokenList = typeof DOMTokenList !== \"undefined\" ? DOMTokenList : function () {}\n\n/**\n * Convert a `value` to a className string.\n * `value` can be a string, an array or a `Dictionary`.\n */\nfunction className(value) {\n if (Array.isArray(value)) {\n return value.map(className).filter(Boolean).join(\" \")\n } else if (value instanceof DomTokenList) {\n return \"\" + value\n } else if (isObject(value)) {\n return keys(value)\n .filter(k => value[k])\n .join(\" \")\n } else if (isVisibleChild(value)) {\n return \"\" + value\n } else {\n return \"\"\n }\n}\nfunction createFactory(tag) {\n return createElement.bind(null, tag)\n}\nfunction Fragment(attr) {\n const fragment = document.createDocumentFragment()\n appendChild(attr.children, fragment)\n return fragment\n}\nclass Component {\n constructor(props) {\n this.props = props\n }\n render() {\n return null\n }\n}\n\n/* @__PURE__ */\nObject.defineProperties(Component.prototype, {\n isReactComponent: {\n value: true,\n },\n})\nfunction initComponentClass(Class, attr, children) {\n attr = {\n ...attr,\n children,\n }\n const instance = new Class(attr)\n return instance.render()\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction jsx(tag, _ref) {\n let { children, ...attr } = _ref\n let node\n if (isString(tag)) {\n node = attr.namespaceURI\n ? document.createElementNS(attr.namespaceURI, tag)\n : document.createElement(tag)\n attributes(attr, node)\n appendChild(children, node)\n\n // Select `option` elements in `select`\n if (node instanceof window.HTMLSelectElement && attr.value != null) {\n if (attr.multiple === true && Array.isArray(attr.value)) {\n const values = attr.value.map(value => String(value))\n node\n .querySelectorAll(\"option\")\n .forEach(option => (option.selected = values.includes(option.value)))\n } else {\n node.value = attr.value\n }\n }\n attachRef(attr.ref, node)\n } else if (isFunction(tag)) {\n // Custom elements.\n if (isObject(tag.defaultProps)) {\n attr = {\n ...tag.defaultProps,\n ...attr,\n }\n }\n node = isComponentClass(tag)\n ? initComponentClass(tag, attr, children)\n : tag({\n ...attr,\n children,\n })\n } else {\n throw new TypeError(`Invalid JSX element type: ${tag}`)\n }\n return node\n}\nfunction createElement(tag, attr) {\n for (\n var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key2 = 2;\n _key2 < _len;\n _key2++\n ) {\n children[_key2 - 2] = arguments[_key2]\n }\n if (isString(attr) || Array.isArray(attr)) {\n children.unshift(attr)\n attr = {}\n }\n attr = attr || {}\n if (attr.children != null && !children.length) {\n ;({ children, ...attr } = attr)\n }\n return jsx(\n tag,\n {\n ...attr,\n children,\n },\n attr.key\n )\n}\nfunction attachRef(ref, node) {\n if (isRef(ref)) {\n ref.current = node\n } else if (isFunction(ref)) {\n ref(node)\n }\n}\nfunction appendChild(child, node) {\n if (isArrayLike(child)) {\n appendChildren(child, node)\n } else if (isString(child) || isNumber(child)) {\n appendChildToNode(document.createTextNode(child), node)\n } else if (child === null) {\n appendChildToNode(document.createComment(\"\"), node)\n } else if (isElement(child)) {\n appendChildToNode(child, node)\n } else if (isShadowRoot(child)) {\n const shadowRoot = node.attachShadow(child.attr)\n appendChild(child.children, shadowRoot)\n attachRef(child.ref, shadowRoot)\n }\n}\nfunction appendChildren(children, node) {\n for (const child of [...children]) {\n appendChild(child, node)\n }\n return node\n}\nfunction appendChildToNode(child, node) {\n if (node instanceof window.HTMLTemplateElement) {\n node.content.appendChild(child)\n } else {\n node.appendChild(child)\n }\n}\nfunction style(node, value) {\n if (value == null || value === false);\n else if (Array.isArray(value)) {\n value.forEach(v => style(node, v))\n } else if (isString(value)) {\n node.setAttribute(\"style\", value)\n } else if (isObject(value)) {\n forEach(value, (val, key) => {\n if (key.indexOf(\"-\") === 0) {\n // CSS custom properties (variables) start with `-` (e.g. `--my-variable`)\n // and must be assigned via `setProperty`.\n node.style.setProperty(key, val)\n } else {\n node.style[key] = val\n }\n })\n }\n}\nfunction attribute(key, value, node) {\n switch (key) {\n case \"htmlFor\":\n attr(node, \"for\", value)\n return\n case \"dataset\":\n forEach(value, (dataValue, dataKey) => {\n if (dataValue != null) {\n node.dataset[dataKey] = dataValue\n }\n })\n return\n case \"innerHTML\":\n case \"innerText\":\n case \"textContent\":\n if (isVisibleChild(value)) {\n node[key] = value\n }\n return\n case \"dangerouslySetInnerHTML\":\n if (isObject(value)) {\n node.innerHTML = value[\"__html\"]\n }\n return\n case \"value\":\n if (value == null || node instanceof window.HTMLSelectElement) {\n // skip nullish values\n // for `\n
\n \n \n\n`)\n .prependTo(dg.element.find(\".grid-title\"));\n\n dropdown.on('shown.bs.dropdown', e => {\n dropdown.find('input[type=text]').focus();\n });\n\n var viewName = dropdown.find('li.save input[type=text]');\n\n dropdown.find('button.save-button').click(async () => {\n var name = trimToNull(viewName.val());\n if (!name) {\n notifyWarning(localText(\"Site.FavoriteViewsMixin.EmptyNameError\"));\n return;\n }\n\n const favorites = await this.getFavorites();\n favorites[name] = (dg as any).getCurrentSettings();\n await this.saveFavorites(favorites);\n notifySuccess(format(localText(\"Site.FavoriteViewsMixin.SaveSuccessMessage\"), name));\n viewName.val('');\n this.populateFavorites();\n });\n\n this.ul = dropdown.children(\"ul\");\n this.ul.on('click', 'i.fa-trash-o', async e => {\n var name = $(e.target).closest('li').children('a').text();\n const favorites = await this.getFavorites();\n delete favorites[name];\n await this.saveFavorites(favorites);\n await this.populateFavorites();\n notifyWarning(format(localText(\"Site.FavoriteViewsMixin.DeleteSuccessMessage\"), name));\n });\n\n this.ul.on('click', 'a', async e => {\n var name = $(e.target).text();\n const favorites = await this.getFavorites();\n var settings = favorites[name];\n if (settings) {\n dg[\"restoreSettingsFrom\"](settings);\n dg.refresh();\n notifySuccess(format(localText(\"Site.FavoriteViewsMixin.LoadedViewMessage\"), name));\n }\n });\n\n this.populateFavorites();\n }\n\n private async populateFavorites(): Promise {\n var favorites = await this.getFavorites();\n\n var saveLI = this.ul.children('.save');\n this.ul.children().not(saveLI).remove();\n\n var keys = Object.keys(favorites).sort();\n if (keys.length) {\n for (var k of keys) {\n var li = $('
  • ')\n .insertBefore(saveLI)\n .children('a')\n .text(k)\n .end();\n\n $('')\n .attr('title', localText(\"Site.FavoriteViewsMixin.DeleteButtonHint\"))\n .appendTo(li);\n }\n\n $('
  • ').insertBefore(saveLI);\n }\n }\n\n private async saveFavorites(favorites: object): Promise {\n var storage = (this.dataGrid as any).getPersistanceStorage() as SettingStorage;\n var key = \"Views:\" + (this.dataGrid as any).getPersistanceKey();\n return Promise.resolve(storage.setItem(key, JSON.stringify(favorites)));\n }\n\n private async getFavorites(): Promise {\n var storage = (this.dataGrid as any).getPersistanceStorage() as SettingStorage;\n var key = \"Views:\" + (this.dataGrid as any).getPersistanceKey();\n var json = (await storage.getItem(key)) || \"{}\"\n return JSON.parse(json) || {};\n }\n}\n\nexport interface FavoriteViewsMixinOptions {\n // data grid object\n grid: DataGrid;\n}", "\uFEFFimport { DataGrid } from \"@serenity-is/corelib\";\nimport { Criteria, deepClone, ListRequest, ListResponse, serviceCall } from \"@serenity-is/corelib\";\nimport { Column } from \"@serenity-is/sleekgrid\";\nimport { HeaderFiltersPlugin, HeaderFilterType } from \"./HeaderFiltersPlugin\";\n\nexport interface HeadersFiltersMixinOptions {\n grid: DataGrid;\n filterByText?: boolean;\n}\n\n/**\n * A mixin that can be applied to a DataGrid for column filters functionality\n */\nexport class HeaderFiltersMixin {\n\n private filterByText: boolean;\n\n constructor(options: HeadersFiltersMixinOptions) {\n \n var skipColumnFilters: Column = null;\n var cache: any = {};\n\n if (options.filterByText == null) {\n this.filterByText = !options.grid.view.url || \n !options.grid.view['getPagingInfo']().rowsPerPage;\n }\n else\n this.filterByText = !!options.filterByText;\n\n var filterPlugin = new HeaderFiltersPlugin({\n getFilterType: (col: Column) => {\n if (this.filterByText)\n return HeaderFilterType.text;\n\n if (col.sortable != null && !col.sortable)\n return HeaderFilterType.disabled;\n\n if (col.sourceItem != null && \n col.sourceItem.notFilterable != null &&\n col.sourceItem.notFilterable)\n return HeaderFilterType.disabled;\n\n return HeaderFilterType.value;\n },\n getFilterValues: (col: Column, done: (vals: any[]) => void) => {\n if (col.headerFilterType == HeaderFilterType.text)\n return done(null);\n\n skipColumnFilters = col;\n try {\n if (!(options.grid as any).onViewSubmit()) {\n done([]);\n return;\n }\n }\n finally {\n skipColumnFilters = null;\n }\n\n var req = deepClone(options.grid.view.params) as ListRequest;\n req.DistinctFields = [col.field];\n req.Skip = 0;\n req.Take = 0;\n var cacheKey = $.toJSON(req);\n var cached = cache[cacheKey];\n if (cached && cached.expires > new Date().getTime())\n done(cached.value);\n else {\n serviceCall({\n request: req,\n url: options.grid.view.url,\n onSuccess: (response: ListResponse) => {\n cache[cacheKey] = {\n value: response.Values,\n expires: new Date().getTime() + 1000 * 30\n };\n done(response.Values);\n }\n });\n }\n }\n });\n\n filterPlugin.onFilterApplied.subscribe((e, data) => {\n var column = data.column as Column;\n if (column && column.headerFilterType == HeaderFilterType.text)\n options.grid.view.setItems(options.grid.view.getItems(), true);\n else\n options.grid.refresh();\n });\n\n options.grid.slickGrid.registerPlugin(filterPlugin);\n\n var me = this;\n\n var oldOnViewSubmit = (options.grid as any).onViewSubmit;\n (options.grid as any).onViewSubmit = function () {\n if (!oldOnViewSubmit.call(this))\n return false;\n\n var cols = this.slickGrid.getColumns() as Column[];\n var request = (this.view.params as ListRequest);\n for (var col of cols) {\n if (col === skipColumnFilters ||\n col.headerFilterType == HeaderFilterType.text)\n continue;\n\n var vals = col.headerFilterValues;\n if (vals && vals.length) {\n var nonNull = vals.filter((z: any) => z != null);\n var criteria = Criteria(col.field).in(nonNull);\n if (nonNull.length !== vals.length) {\n if (nonNull.length > 0)\n criteria = Criteria.or(Criteria(col.field).isNull(), criteria);\n else\n criteria = Criteria(col.field).isNull();\n }\n\n request.Criteria = Criteria.and(request.Criteria, criteria);\n }\n }\n\n return true;\n };\n\n var oldOnViewFilter = (options.grid as any).onViewFilter;\n (options.grid as any).onViewFilter = function (item: any) {\n if (!oldOnViewFilter.apply(this, arguments))\n return false;\n\n var cols = this.slickGrid.getColumns() as Column[];\n for (var col of cols) {\n if (col.headerFilterType != HeaderFilterType.text)\n continue;\n\n var vals = col.headerFilterValues;\n if (vals && vals.length) {\n var filterValue = filterPlugin.getFilterValue(item, col);\n if (vals.indexOf(filterValue) < 0)\n return false;\n }\n }\n\n return true;\n };\n }\n}", "\uFEFFimport { htmlEncode, tryGetText } from \"@serenity-is/corelib\";\nimport { RemoteView } from \"@serenity-is/corelib\";\nimport { Column, EventEmitter, EventSubscriber, Grid } from \"@serenity-is/sleekgrid\";\n\nexport enum HeaderFilterType {\n disabled = 0,\n value = 1,\n text = 2\n}\n\ndeclare module \"@serenity-is/sleekgrid\" {\n interface Column {\n headerFilterType?: HeaderFilterType;\n headerFilterValues?: object[];\n }\n}\n\n/*\n Based on SlickGrid Header Menu Plugin (https://github.com/mleibman/SlickGrid/blob/master/plugins/slick.headermenu.js)\n Based on SlickGrid Spreadsheet Plugins (https://github.com/danny-sg/slickgrid-spreadsheet-plugins/blob/master/ext.headerfilter.js)\n (Can't be used at the same time as the header menu plugin as it implements the dropdown in the same way)\n*/\n\nexport interface HeaderFiltersOptions {\n buttonImage?: string;\n buttonClass?: string;\n useColumnFormatter?: boolean;\n getFilterValues?: (column: Column, callback: (values: object[], texts?: string[]) => void) => void;\n getFilterType?: (column: Column) => HeaderFilterType;\n}\n\nexport class HeaderFiltersPlugin {\n\n private grid: Grid;\n private menu: JQuery;\n private searchInput: JQuery;\n private handler: EventSubscriber;\n private options: HeaderFiltersOptions;\n private checkedValues : any = new window['Set']();\n private filterValues: object[];\n private filterTexts: string[];\n public onFilterApplied = new EventEmitter();\n public onCommand = new EventEmitter();\n\n constructor(options: HeaderFiltersOptions) {\n this.handler = new EventSubscriber();\n\n var defaults: HeaderFiltersOptions = {\n buttonClass: \"headerfilterbutton\",\n useColumnFormatter: true,\n getFilterValues: null\n };\n\n this.options = $.extend(true, {}, defaults, options);\n this.handleMenuItemClick = this.handleMenuItemClick.bind(this);\n }\n \n init(g: Grid) {\n \n this.grid = g;\n this.handler.subscribe(g.onHeaderCellRendered, this.handleHeaderCellRendered.bind(this))\n .subscribe(g.onBeforeHeaderCellDestroy, this.handleBeforeHeaderCellDestroy.bind(this))\n .subscribe(g.onClick, this.handleBodyMouseDown.bind(this))\n .subscribe(g.onColumnsResized, this.columnsResized.bind(this));\n\n g.setColumns(g.getColumns());\n\n $(document.body).bind(\"mousedown\", this.handleBodyMouseDown = this.handleBodyMouseDown.bind(this));\n }\n\n destroy() {\n this.handler.unsubscribeAll();\n $(document.body).unbind(\"mousedown\", this.handleBodyMouseDown);\n }\n\n getFilterType(column: Column) {\n if (column.headerFilterType != null)\n return column.headerFilterType;\n\n if (this.options.getFilterType != null) {\n column.headerFilterType = this.options.getFilterType(column);\n if (column.headerFilterType != null)\n return column.headerFilterType;\n }\n\n if (column.headerFilterType == null)\n column.headerFilterType = HeaderFilterType.value;\n\n return column.headerFilterType;\n }\n\n private handleBodyMouseDown(e: any) {\n if (this.menu && this.menu[0] != e.target && !$.contains(this.menu[0], e.target)) {\n this.hideMenu();\n }\n }\n\n private hideMenu() {\n if (this.menu) {\n this.menu.remove();\n this.menu = null;\n }\n }\n\n private handleHeaderCellRendered(e: any, args: any) {\n var column = args.column as Column;\n\n var filterType = this.getFilterType(column);\n if (filterType === HeaderFilterType.disabled)\n return false;\n\n var $el = $(\"\")\n .addClass(\"slick-header-menubutton s-header-filter-button\")\n .data(\"column\", column);\n\n if (this.options.buttonImage) {\n $el.css(\"background-image\", \"url(\" + this.options.buttonImage + \")\");\n }\n\n this.setButtonIsFiltered($el, column.headerFilterValues != null && column.headerFilterValues.length > 0);\n\n $(args.node).addClass('has-header-menubutton');\n $el.on(\"click\", e => {\n e.stopPropagation();\n this.showFilter(e);\n }).appendTo(args.node);\n }\n\n private handleBeforeHeaderCellDestroy(e: any, args: any) {\n $(args.node)\n .find(\".s-header-filter-button\")\n .remove();\n }\n\n private addMenuItem(menu: JQuery, columnDef: Column, title: string, command: string, image: string) {\n var $item = $(\"
    \")\n .data(\"command\", command)\n .data(\"column\", columnDef)\n .bind(\"click\", this.handleMenuItemClick)\n .appendTo(menu);\n\n var $icon = $(\"
    \")\n .appendTo($item);\n\n if (image) {\n $icon.css(\"background-image\", \"url(\" + image + \")\");\n }\n\n $(\"\")\n .text(title)\n .appendTo($item);\n }\n\n private addSearchInput(menu: JQuery, columnDef: Column) {\n return $('')\n .data(\"column\", columnDef)\n .bind(\"keyup\", (e) => {\n this.updateFilterValues(columnDef, () => {});\n })\n .appendTo(menu);\n }\n\n private updateFilterItems(columnDef: Column) {\n var filterOptions = \"\";\n\n this.checkedValues = new window['Set'](columnDef.headerFilterValues || []);\n\n for (var i = 0; i < this.filterValues.length; i++) {\n var filtered = this.checkedValues.has(this.filterValues[i]);\n filterOptions += \"\";\n }\n\n var $filter = this.menu.find('.filter');\n $filter.empty().append($(filterOptions));\n\n $(':checkbox', $filter).bind('click', e => {\n this.onCheckboxClick($(e.target));\n });\n }\n\n private getFilterText(item: any, column: Column): string {\n var value = item[column.field];\n\n if (this.options.useColumnFormatter) {\n try {\n var format = this.grid.getFormatter(-1, column);\n if (format) {\n var ctx = this.grid.getFormatterContext(-1, -1);\n ctx.item = item;\n ctx.value = value;\n var html = format(ctx);\n\n if (value == null && html === '') {\n return (htmlEncode(tryGetText(\"Site.HeaderFiltersMixin.Null\") || \"(null)\"));\n }\n\n return html;\n }\n }\n catch (ex) {\n }\n }\n\n if (value == null)\n return (htmlEncode(tryGetText(\"Site.HeaderFiltersMixin.Null\") || \"(null)\"));\n\n return htmlEncode(value);\n }\n\n private showFilter(e: any) {\n var $menuButton = $(e.target);\n var columnDef = $menuButton.data(\"column\") as Column;\n\n this.checkedValues = new window['Set'](columnDef.headerFilterValues || []);\n\n if (!this.menu)\n this.menu = $(\"
    \").appendTo(document.body).hide();\n else\n this.menu.empty();\n\n this.searchInput = this.addSearchInput(this.menu, columnDef);\n\n var filterOptions = \"\";\n\n var $filter = $(\"
    \")\n .appendTo(this.menu);\n\n var buttons = $('
    ').appendTo(this.menu);\n\n $('')\n .appendTo(buttons)\n .bind('click', ev => {\n if (Array['from']) {\n columnDef.headerFilterValues = Array['from'](this.checkedValues);\n }\n else {\n columnDef.headerFilterValues = [];\n this.checkedValues && this.checkedValues.forEach((x: any) => columnDef.headerFilterValues.push(x));\n }\n this.setButtonIsFiltered($menuButton, columnDef.headerFilterValues.length > 0);\n this.handleApply(ev, columnDef);\n });\n\n $('')\n .appendTo(buttons)\n .bind('click', ev => {\n if (columnDef.headerFilterValues)\n columnDef.headerFilterValues.length = 0;\n this.setButtonIsFiltered($menuButton, false);\n this.handleApply(ev, columnDef);\n });\n\n $('')\n .appendTo(buttons)\n .bind('click', e => this.hideMenu());\n\n $(':checkbox', $filter).bind('click', (e) => {\n this.onCheckboxClick($(e.target));\n });\n\n this.updateFilterValues(columnDef, () => {\n this.menu.show();\n $filter.css('height', null);\n var menuHeight = this.menu.height();\n var buttonHeight = $(e.target).height();\n\n var offset = $(e.target).offset();\n var left = offset.left - this.menu.width() + $(e.target).width() - 8;\n\n var menuTop = offset.top + buttonHeight;\n\n var windowScrollTop = $(window).scrollTop();\n var bottomBoundary = $(window).height() + windowScrollTop;\n var contentWrapperTop = (parseInt($('div.content-wrapper').css('padding-top'), 10) || 0);\n\n if (menuTop + menuHeight > bottomBoundary &&\n bottomBoundary - menuTop + contentWrapperTop < menuTop - windowScrollTop) {\n menuTop -= (menuHeight + buttonHeight + 8);\n\n if (menuTop < windowScrollTop)\n menuTop = windowScrollTop;\n }\n\n var extraHeight = menuTop + menuHeight - bottomBoundary;\n\n if (extraHeight > 0) {\n $filter.css('height', ($filter.height() - extraHeight));\n }\n\n this.menu.css(\"top\", menuTop).css(\"left\", (left > 0 ? left : 0));\n });\n }\n\n private columnsResized() {\n this.hideMenu();\n }\n\n private onCheckboxClick($checkbox: JQuery) {\n var index = $checkbox.val();\n var $filter = $checkbox.parent().parent();\n\n if ($checkbox.val() < 0) {\n if ($checkbox.prop('checked')) {\n $(':checkbox', $filter).prop('checked', true);\n this.checkedValues = new window['Set'](this.filterValues || []);\n } else {\n $(':checkbox', $filter).prop('checked', false);\n this.checkedValues.clear();\n }\n } else {\n var value = this.filterValues[index];\n var has = this.checkedValues.has(value);\n\n if ($checkbox.prop('checked') && !has) {\n this.checkedValues.add(value);\n }\n else if (has) {\n this.checkedValues.delete(value);\n }\n }\n }\n\n private setButtonIsFiltered($el: JQuery, filtered: boolean) {\n $el.toggleClass('is-filtered', filtered);\n }\n\n private handleApply(e: any, columnDef: Column) {\n this.hideMenu();\n\n this.onFilterApplied.notify({ \n \"grid\": this.grid, \n \"column\": columnDef \n }, e, this);\n\n e.preventDefault();\n e.stopPropagation();\n }\n\n private containsFilter(filter: string): ((text: string) => boolean) {\n if (filter == null && filter.length == 0)\n return v => true;\n\n var lowercaseFilter = htmlEncode(filter).toLowerCase();\n\n return (text: string) => {\n text = (text ?? '').toString().replace(/<[^>]+>/g, '').toLowerCase();\n return text.indexOf(lowercaseFilter) >= 0;\n };\n }\n\n public getFilterValue(item: any, column: Column) {\n var value = item[column.field];\n if (this.options.useColumnFormatter &&\n column.formatter != null &&\n column.headerFilterType == HeaderFilterType.text) {\n return (this.getFilterText(item, column)\n .replace(/<[^>]+>/g, ''));\n }\n\n return value;\n }\n\n private sortFilterValues() {\n var idx: number[] = [];\n for (var i = 0; i < this.filterValues.length; i++) {\n idx[i] = i;\n }\n idx.sort((x, y) => {\n var A = this.filterValues[x];\n var B = this.filterValues[y];\n return (A < B ? -1 : (A > B ? 1 : 0));\n });\n var newFilterValues = [];\n var newFilterTexts = [];\n for (var i = 0; i < idx.length; i++) {\n newFilterValues.push(this.filterValues[i]);\n newFilterTexts.push(this.filterTexts[i]);\n }\n this.filterValues = newFilterValues;\n this.filterTexts = newFilterTexts;\n }\n\n private updateFilterValues(column: Column, done: () => void) {\n if (this.options.getFilterValues != null) {\n this.options.getFilterValues(column, (values: object[], texts: string[]) => {\n if (values == null) {\n this.updateFilterValuesFromData(column);\n this.updateFilterItems(column);\n done();\n }\n else {\n this.filterValues = [];\n this.filterTexts = [];\n\n texts = texts || values.map(x => {\n var item: any = {};\n item[column.field] = x;\n return this.getFilterText(item, column);\n });\n\n var filter = this.containsFilter(this.searchInput.val());\n this.filterValues = values.filter((x, i) => {\n if (filter(texts[i])) {\n this.filterTexts.push(texts[i]);\n return true;\n }\n\n return false;\n });\n\n this.sortFilterValues();\n this.updateFilterItems(column);\n done();\n }\n });\n }\n else {\n this.updateFilterValuesFromData(column);\n this.updateFilterItems(column);\n done();\n }\n }\n\n private updateFilterValuesFromData(column: Column) {\n\n this.filterValues = [];\n this.filterTexts = [];\n var dataView = ((this.grid.getData() as any) as RemoteView);\n \n var items: any[];\n if (this.checkedValues && this.checkedValues.size) {\n items = dataView.getItems();\n }\n else {\n items = [];\n for (var i = 0; i < dataView.getLength(); i++) {\n items.push(dataView.getItem(i));\n }\n }\n\n var seen = new window['Set']();\n var searchText = this.searchInput.val();\n var searchFilter = this.containsFilter(searchText);\n for (var item of items) {\n var value = this.getFilterValue(item, column);\n if (!seen.has(value)) {\n var text = this.getFilterText(item, column);\n if (searchFilter(text)) {\n seen.add(value);\n this.filterValues.push(value);\n this.filterTexts.push(text);\n }\n }\n }\n \n this.sortFilterValues();\n }\n\n private handleMenuItemClick(e: any) {\n var command = $(this).data(\"command\");\n var columnDef = $(this).data(\"column\");\n\n this.hideMenu();\n\n this.onCommand.notify({\n \"grid\": this,\n \"column\": columnDef,\n \"command\": command\n }, e, this);\n\n e.preventDefault();\n e.stopPropagation();\n }\n}\n\ntypeof globalThis != \"undefined\" && globalThis[\"Slick\"] && globalThis[\"Slick\"][\"Plugins\"] && (globalThis.Slick[\"Plugins\"][\"HeaderFilters\"] = HeaderFiltersPlugin);\n", "\uFEFFimport { htmlEncode, resolveUrl, localText, format } from \"@serenity-is/corelib\";\n\nexport interface IdleTimeoutOptions {\n /** which events to consider as an activity. */\n activityEvents?: string;\n /** signout user if no activity within this duration (seconds). default is 900 (15 mins). */\n activityTimeout?: number;\n /** optional callback that is called just before signing out */\n beforeSignout?: () => void;\n /** interval for checking timer, default is 5 seconds */\n checkInterval?: number;\n /** interval for calling keep alive url in seconds, default is 300 (5 mins) */\n keepAliveTimer?: number;\n /** keep alive url */\n keepAliveUrl?: string;\n /** url used to signout user */\n signoutUrl?: string;\n /** show warning for this number of seconds */\n warningDuration?: number;\n}\n\nexport class IdleTimeout {\n\n private options: IdleTimeoutOptions;\n private idleTimer: number;\n private keepAliveTimer: number;\n private warningTimer: number;\n private remainingTimer: number;\n\n constructor(options: IdleTimeoutOptions) {\n this.options = $.extend({}, IdleTimeout.defaults, options);\n\n localStorage.setItem('IdleTimeout:LastActivity', $.now().toString());\n localStorage.removeItem('IdleTimeout:Signout');\n\n var mouseX: number, mouseY: number;\n $('body').on(this.options.activityEvents, e => {\n\n if (e.type == 'mousemove') {\n\n if (e.clientX == mouseX && e.clientY == mouseY)\n return;\n\n mouseX = e.clientX;\n mouseY = e.clientY;\n }\n\n if (!this.isWarningActive()) {\n this.resetIdleTimer();\n }\n });\n\n if (this.options.keepAliveTimer)\n this.startKeepAliveTimer();\n\n this.resetIdleTimer();\n }\n\n protected startKeepAliveTimer() {\n\n clearTimeout(this.keepAliveTimer);\n\n var keepSessionAlive = () => {\n $.get(resolveUrl(this.options.keepAliveUrl) + '?' + new Date().getTime());\n this.startKeepAliveTimer();\n };\n\n this.keepAliveTimer = setTimeout(keepSessionAlive, this.options.keepAliveTimer * 1000);\n }\n\n protected isWarningActive() {\n return $('#idle-timeout-warning').is(':visible');\n }\n\n protected startWarningTimer() {\n this.warningTimer = setInterval(() => this.warningTimeout(), this.options.checkInterval * 1000);\n }\n\n protected stopWarningTimer() {\n clearInterval(this.warningTimer);\n clearInterval(this.remainingTimer);\n };\n\n protected warningTimeout() {\n if (this.getRemainingSeconds() < 0)\n this.signout();\n }\n\n protected resetIdleTimer() {\n clearTimeout(this.idleTimer);\n localStorage.setItem('IdleTimeout:LastActivity', $.now().toString());\n this.idleTimeout();\n };\n\n protected idleTimeout() {\n this.checkActivityTimeout();\n this.idleTimer = setTimeout(() => this.idleTimeout(), this.options.checkInterval * 1000);\n };\n\n protected checkActivityTimeout() {\n\n var timeLimit = parseInt(localStorage.getItem('IdleTimeout:LastActivity') || $.now().toString()) +\n (this.options.activityTimeout - (this.options.warningDuration || 0)) * 1000;\n\n if ($.now() > timeLimit) {\n if (!this.options.warningDuration) {\n this.signout();\n } else {\n this.showWarning();\n this.startWarningTimer();\n }\n } else if (localStorage.getItem('IdleTimeout:Signout')) {\n this.signout();\n } else if (this.isWarningActive()) {\n this.closeWarning();\n this.stopWarningTimer();\n }\n }\n\n protected signout() {\n localStorage.setItem('IdleTimeout:Signout', \"1\");\n clearTimeout(this.keepAliveTimer);\n this.stopWarningTimer();\n this.closeWarning();\n this.options.beforeSignout && this.options.beforeSignout();\n if (this.options.signoutUrl)\n window.location.href = resolveUrl(this.options.signoutUrl);\n }\n\n protected showWarning() {\n var warningDialog = $('#idle-timeout-warning');\n if (!warningDialog.length) {\n warningDialog = $(`
    \n
    \n
    \n
    \n

    ${htmlEncode(localText(\"Controls.IdleTimeout.WarningTitle\"))}

    \n \n
    \n
    \n

    ${htmlEncode(localText(\"Controls.IdleTimeout.WarningMessage\"))}

    \n

    ${format(htmlEncode(localText(\"Controls.IdleTimeout.CountdownMessage\")), ` `)}

    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n
    `).appendTo(document.body);\n\n $('#idle-timeout-warning-signout').on('click', () => this.signout());\n warningDialog.on('hide.bs.modal', () => {\n clearTimeout(this.warningTimer);\n clearTimeout(this.remainingTimer);\n this.resetIdleTimer();\n });\n }\n\n warningDialog['modal']('show');\n this.countdownDisplay();\n }\n\n protected closeWarning() {\n var warning = $('#idle-timeout-warning').off('hide.bs.modal');\n if (warning.length && warning.data() && warning.data()['bs.modal'] && warning.data()['bs.modal'].isShown) {\n warning.removeClass('fade');\n warning['modal']('hide');\n warning.remove();\n }\n }\n\n protected getRemainingSeconds() {\n var timeLimit = parseInt(localStorage.getItem('IdleTimeout:LastActivity') || $.now().toString()) +\n (this.options.activityTimeout * 1000);\n return Math.ceil(((timeLimit - $.now()) / 1000));\n }\n\n protected countdownDisplay() {\n clearTimeout(this.remainingTimer);\n var update = () => {\n var remainingSeconds = Math.max(this.getRemainingSeconds(), 1);\n var percentLeft = 100 * Math.max(1, remainingSeconds) / (this.options.warningDuration || 1);\n $('#idle-timeout-progress').css('width', percentLeft + '%');\n $('#idle-timeout-seconds').text(remainingSeconds);\n };\n this.remainingTimer = setInterval(update, 500);\n update();\n };\n\n static defaults: IdleTimeoutOptions = {\n activityEvents: 'click keyup mouseup mousemove scroll touchend touchmove wheel mousewheel',\n activityTimeout: 900,\n checkInterval: 5,\n keepAliveTimer: 300,\n keepAliveUrl: '~/Account/KeepAlive',\n signoutUrl: '~/Account/Signout',\n warningDuration: 60,\n }\n}\n", "\uFEFFexport function setupUIOverrides() {\n // no-op, all overrides are moved to corelib\n}", "import { Decorators, EntityGrid, GridUtils, LookupEditor, LookupEditorOptions, QuickFilterBar, SelectEditor, ToolButton, Widget } from \"@serenity-is/corelib\";\nimport { confirmDialog, Dictionary, format, isEmptyOrNull, isTrimmedEmpty, localText, notifyError, notifySuccess, outerHtml, serviceCall, ServiceResponse, trimToEmpty, trimToNull } from \"@serenity-is/corelib\";\nimport { TranslationItem, TranslationListResponse, TranslationUpdateRequest, TranslationUpdateResponse } from \"@serenity-is/extensions\";\nimport { Column } from \"@serenity-is/sleekgrid\";\nimport copyToClipboard from \"../Tools/CopyToClipboard\";\n\n@Decorators.registerClass('Serenity.Extensions.TranslationGrid')\nexport class TranslationGrid extends EntityGrid {\n protected getIdProperty() { return \"Key\"; }\n protected getLocalTextDbPrefix() { return \"Site.Translation.\"; }\n protected getService() { return \"Administration/Translation\" }\n\n private hasChanges: boolean;\n private searchText: string;\n private sourceLanguage: LookupEditor;\n private targetLanguage: LookupEditor;\n private targetLanguageKey: string;\n\n constructor(container: JQuery) {\n super(container);\n\n this.element.on('keyup.' + this.uniqueName + ' change.' + this.uniqueName,\n 'input.custom-text', e => {\n var value = trimToNull($(e.target).val());\n if (value === '') {\n value = null;\n }\n this.view.getItemById($(e.target).data('key')).CustomText = value;\n this.hasChanges = true;\n });\n }\n\n protected onClick(e: JQueryEventObject, row: number, cell: number): any {\n super.onClick(e, row, cell);\n\n if (e.isDefaultPrevented()) {\n return;\n }\n\n let item = this.itemAt(row);\n let done: () => void;\n\n if ($(e.target).hasClass('source-text')) {\n e.preventDefault();\n\n done = () => {\n item.CustomText = item.SourceText;\n this.view.updateItem(item.Key, item);\n this.hasChanges = true;\n };\n\n if (isTrimmedEmpty(item.CustomText) ||\n (trimToEmpty(item.CustomText) === trimToEmpty(item.SourceText))) {\n done();\n return;\n }\n\n confirmDialog(localText('Site.Translation.OverrideConfirmation'), done);\n return;\n }\n\n if ($(e.target).hasClass('target-text')) {\n e.preventDefault();\n\n done = () => {\n item.CustomText = item.TargetText;\n this.view.updateItem(item.Key, item);\n this.hasChanges = true;\n };\n\n if (isTrimmedEmpty(item.CustomText) ||\n (trimToEmpty(item.CustomText) === trimToEmpty(item.TargetText))) {\n done();\n return;\n }\n\n confirmDialog(localText('Site.Translation.OverrideConfirmation'), done);\n return;\n }\n }\n\n protected getColumns(): Column[] {\n\n var columns: Column[] = [];\n columns.push({ field: 'Key', width: 300, sortable: false });\n\n columns.push({\n field: 'SourceText',\n width: 300,\n sortable: false,\n format: ctx => {\n return outerHtml($('')\n .addClass('source-text')\n .text(ctx.value || ''));\n }\n });\n\n columns.push({\n field: 'CustomText',\n width: 300,\n sortable: false,\n format: ctx => outerHtml($('')\n .addClass('custom-text')\n .attr('value', ctx.value)\n .attr('type', 'text')\n .attr('data-key', ctx.item.Key))\n });\n\n columns.push({\n field: 'TargetText',\n width: 300,\n sortable: false,\n format: ctx => outerHtml($('')\n .addClass('target-text')\n .text(ctx.value || ''))\n });\n\n return columns;\n }\n\n protected createToolbarExtensions(): void {\n super.createToolbarExtensions();\n\n let opt: LookupEditorOptions = {\n lookupKey: 'Administration.Language'\n };\n\n this.sourceLanguage = Widget.create({\n type: LookupEditor,\n element: el => el.appendTo(this.toolbar.element).attr('placeholder', '--- ' +\n localText('Site.Translation.SourceLanguage') + ' ---'),\n options: opt\n });\n\n this.sourceLanguage.changeSelect2(e => {\n if (this.hasChanges) {\n this.saveChanges(this.targetLanguageKey).then(() => this.refresh());\n }\n else {\n this.refresh();\n }\n });\n\n this.targetLanguage = Widget.create({\n type: LookupEditor,\n element: el => el.appendTo(this.toolbar.element).attr('placeholder', '--- ' +\n localText('Site.Translation.TargetLanguage') + ' ---'),\n options: opt\n });\n\n this.targetLanguage.changeSelect2(e => {\n if (this.hasChanges) {\n this.saveChanges(this.targetLanguageKey).then(() => this.refresh());\n }\n else {\n this.refresh();\n }\n });\n }\n\n protected getQuickFilters() {\n var filters = super.getQuickFilters();\n\n var userTranslated = QuickFilterBar.boolean('UserTranslated',\n localText('Site.Translation.UserTranslated'));\n userTranslated.init = w => w.changeSelect2(() => this.hasChanges && this.saveChanges(this.targetLanguageKey));\n\n filters.push(userTranslated);\n\n var hasTranslation = QuickFilterBar.boolean('HasTranslation',\n localText('Site.Translation.HasTranslation'));\n hasTranslation.init = w => w.changeSelect2(() => this.hasChanges && this.saveChanges(this.targetLanguageKey));\n\n filters.push(hasTranslation);\n\n filters.push({\n field: 'Assembly',\n cssClass: 'Assembly',\n title: localText('Site.Translation.Assembly'),\n type: SelectEditor\n });\n\n return filters;\n }\n\n private keysByAssembly: Dictionary>;\n\n protected onViewProcessData(response: TranslationListResponse) {\n response = super.onViewProcessData(response);\n this.keysByAssembly = {};\n var assembly = this.tryFindQuickFilter(SelectEditor, \"Assembly\");\n if (assembly) {\n var value = assembly.value;\n assembly.clearItems();\n var asmNames = Object.keys(response.KeysByAssembly);\n asmNames.sort();\n for (var asmName of asmNames) {\n var asmKeys = response.KeysByAssembly[asmName];\n if (!asmKeys?.length)\n continue;\n assembly.addOption(asmName, asmName);\n var keys = this.keysByAssembly[asmName] = {};\n for (var key of asmKeys)\n keys[key] = true;\n }\n assembly.element.select2('val', value);\n }\n return response;\n }\n\n protected saveChanges(language: string): PromiseLike {\n var translations: { [key: string]: string } = {};\n for (let item of this.getItems()) {\n translations[item.Key] = item.CustomText;\n }\n\n return serviceCall({\n service: this.getService() + \"/Update\",\n request: {\n TargetLanguageID: language,\n Translations: translations\n }\n }).then((response: TranslationUpdateResponse) => {\n this.hasChanges = false;\n notifySuccess(format(localText('Site.Translation.SaveSuccessMessage'), response.SavedPath));\n });\n }\n\n protected onViewSubmit(): boolean {\n var request = this.view.params;\n request.SourceLanguageID = this.sourceLanguage.value;\n this.targetLanguageKey = this.targetLanguage.value || '';\n request.TargetLanguageID = this.targetLanguageKey;\n this.hasChanges = false;\n return super.onViewSubmit();\n }\n\n protected getButtons(): ToolButton[] {\n return [\n {\n title: localText('Site.Translation.SaveChangesButton'),\n onClick: _ => this.saveChanges(this.targetLanguageKey).then(() => this.refresh()),\n cssClass: 'apply-changes-button'\n },\n {\n hint: localText(\"Site.Translation.CopySourceTranslations\"),\n cssClass: 'copy-source-to-clipboard',\n icon: 'fa fa-clone',\n onClick: () => {\n var length = this.slickGrid.getDataLength();\n var d = {};\n for (var i = 0; i < length; i++) {\n var item = this.slickGrid.getDataItem(i) as TranslationItem;\n d[item.Key] = item.SourceText;\n }\n\n copyToClipboard(JSON.stringify(d, null, ' '))\n .then(() => notifySuccess(localText(\"Site.Translation.CopySuccessMessage\")))\n .catch(() => notifyError(localText(\"Site.Translation.CopyFailMessage\")))\n }\n },\n {\n hint: localText(\"Site.Translation.CopyTargetTranslations\"),\n cssClass: 'copy-target-to-clipboard',\n icon: 'fa fa-copy',\n onClick: () => {\n var length = this.slickGrid.getDataLength();\n var d = {};\n for (var i = 0; i < length; i++)\n {\n var item = this.slickGrid.getDataItem(i) as TranslationItem;\n d[item.Key] = item.CustomText?.length ? item.CustomText :\n item.HasTranslation ? item.TargetText : null;\n }\n\n copyToClipboard(JSON.stringify(d, null, ' '))\n .then(() => notifySuccess(localText(\"Site.Translation.CopySuccessMessage\")))\n .catch(() => notifyError(localText(\"Site.Translation.CopyFailMessage\")))\n }\n }\n ];\n }\n\n protected createQuickSearchInput() {\n GridUtils.addQuickSearchInputCustom(this.toolbar.element,\n (_, searchText, done) => {\n this.searchText = searchText;\n this.view.setItems(this.view.getItems(), true);\n done(this.slickGrid.getDataLength() > 0);\n });\n }\n\n protected onViewFilter(item: TranslationItem) {\n if (!super.onViewFilter(item))\n return false;\n\n var userTranslated = this.tryFindQuickFilter(SelectEditor, \"UserTranslated\");\n if (userTranslated?.value?.length) {\n if (userTranslated.value == \"1\" && !item.UserTranslated)\n return false;\n\n if (userTranslated.value == \"0\" && item.UserTranslated)\n return false;\n }\n\n var hasTranslation = this.tryFindQuickFilter(SelectEditor, \"HasTranslation\");\n if (hasTranslation?.value?.length) {\n if (hasTranslation.value == \"1\" && !item.HasTranslation)\n return false;\n\n if (hasTranslation.value == \"0\" && item.HasTranslation)\n return false;\n }\n\n var assembly = this.tryFindQuickFilter(SelectEditor, \"Assembly\");\n if (assembly?.value?.length) {\n var kba = (this.keysByAssembly || {})[assembly.value];\n if (!kba || !kba[item.Key])\n return false;\n }\n\n if (!this.searchText)\n return true;\n\n var sd = Select2.util.stripDiacritics;\n var searching = sd(this.searchText).toLowerCase();\n\n function match(str: string) {\n if (!str)\n return false;\n\n return str.toLowerCase().indexOf(searching) >= 0;\n }\n\n return isEmptyOrNull(searching) || match(item.Key) || match(item.SourceText) ||\n match(item.TargetText) || match(item.CustomText);\n }\n\n protected usePager() {\n return false;\n }\n}", "\nexport default async function copyToClipboard(text: string) {\n try {\n await navigator.clipboard.writeText(text);\n } catch (err) {\n var el = document.createElement('textarea');\n el.setAttribute('style', `position: absolute, left: -9999px, top: ${(window.pageYOffset || document.documentElement.scrollTop)}px`);\n el.setAttribute('readonly', '');\n el.value = text;\n var lastDialog = $('.ui-dialog-content:visible').last();\n if (lastDialog.length)\n lastDialog.append(el);\n else\n document.body.append(el);\n el.select();\n (document as any)[\"execCommand\"](\"copy\");\n el.remove();\n }\n}", "import { Decorators, PropertyGrid, PropertyGridMode, PropertyGridOptions, TemplatedDialog, WX } from \"@serenity-is/corelib\";\nimport { confirmDialog, getForm, htmlEncode, localText, PropertyItem } from \"@serenity-is/corelib\";\n\n/**\n * A dialog/panel base class that easily generates a wizard UI from tabs in a form definition (e.g. Form.cs)\n */\n@Decorators.registerClass(\"Serenity.WizardDialog\")\nexport abstract class WizardDialog extends TemplatedDialog {\n\n private wizardGrid: PropertyGrid;\n\n /**\n * Creates a new wizard dialog\n * @param opt options, might be used by derived classes\n */\n constructor(opt?: TOptions) {\n super(opt);\n\n this.element.children().addClass(\"wizard-horz\");\n\n this.wizardGrid = new PropertyGrid(this.byId(\"WizardGrid\"),\n this.getPropertyGridOptions());\n\n this.wizardGrid.element.children(\".property-tabs\").children('li').each((i, li) => {\n var $li = $(li);\n var h = $li.children('a').html();\n $li.html('').attr('data-step', i + 1);\n $('').text(i + 1).appendTo($li);\n $('').html(h).appendTo($li);\n $('').appendTo($li);\n });\n\n this.byId(\"CancelButton\").click((e) => this.confirmCancel(e));\n\n this.byId(\"BackButton\").click(() => {\n this.moveToStep(this.step - 1);\n });\n\n this.byId(\"NextButton\").click(() => {\n if (!this.validateForm())\n return false;\n\n this.moveToStep(this.step + 1);\n });\n\n this.wizardGrid.element.children(\".property-tabs\")\n .on(\"click\", \"li\", e => {\n var step = $(e.currentTarget).data('step');\n\n if (step > this.step)\n return;\n\n this.moveToStep(step);\n });\n\n this.wizardGrid.element\n .children(\".property-panes\")\n .children(\".tab-pane\")\n .addClass('hidden');\n\n this.wizardGrid.load(this.getInitialEntity());\n\n this.getStepLink(this._step).addClass(\"in show active\");\n this.getStepPanel(this._step).addClass(\"in show active\").removeClass(\"hidden\");\n\n this.element.on('dialogbeforeclose panelbeforeclose', e => {\n if (!WX.hasOriginalEvent(e))\n return;\n\n this.confirmCancel(e);\n });\n }\n\n /**\n * gets property grid options\n */\n protected getPropertyGridOptions(): PropertyGridOptions {\n return {\n idPrefix: this.idPrefix,\n mode: PropertyGridMode.insert,\n items: this.getPropertyItems(),\n localTextPrefix: 'Forms.' + this.getFormKey() + '.',\n useCategories: true\n };\n }\n\n /**\n * gets form key to use to load property items / tabs\n */\n protected getFormKey(): string {\n return null;\n }\n\n /**\n * gets list of property items to shown on form, uses form key to load items by default\n */\n protected getPropertyItems(): PropertyItem[] {\n var formKey = this.getFormKey();\n if (formKey)\n return getForm(formKey);\n\n return [];\n }\n\n /**\n * gets initial entity to load onto form, override these to customize initial form values\n */\n protected getInitialEntity(): TEntity {\n return {} as TEntity;\n }\n\n // gets maximum number of steps from\n protected get maxSteps() {\n return this.wizardGrid.element\n .children(\".property-tabs\")\n .children(\"li\")\n .length;\n }\n\n /**\n * moves to a step, by calling one of next, back or finish methods based on target step\n * @param toStep the target step to move to\n */\n protected moveToStep(toStep: number) {\n if (toStep == this.step || toStep < 1 || toStep > this.maxSteps + 1)\n return;\n\n if (toStep >= this.maxSteps + 1) {\n this.finish();\n return;\n }\n\n (toStep < this.step ? this.back : this.next).call(this, toStep);\n }\n\n private _step: number = 1;\n\n // gets current step\n protected get step(): number {\n return this._step;\n }\n\n // sets current step directly, skipping any validation\n protected set step(value: number) {\n this.getStepLink(this._step).removeClass(\"in active\");\n this.getStepPanel(this._step).removeClass(\"in show active\").addClass('hidden');\n this.getStepLink(value).addClass(\"in active\");\n this.getStepPanel(value).addClass(\"in show active\").removeClass('hidden')\n .find(\".require-layout\").triggerHandler(\"layout\");\n var s: number;\n for (s = value; s <= this._step; s++)\n this.getStepLink(s).removeClass(\"complete\").find(\"span.badge\").removeClass(\"badge-success\");\n for (s = this._step; s < value; s++)\n this.getStepLink(s).addClass(\"complete\").find(\"span.badge\").addClass(\"badge-success\");\n\n this._step = value;\n\n this.byId(\"BackButton\").toggleClass('disabled', this._step <= 1);\n this.byId(\"NextButton\").children('.txt').text(localText(\"Site.WizardDialog.\" +\n (this._step == this.maxSteps ? \"Finish\" : \"Next\") + \"Button\"));\n }\n\n /**\n * called to reset the form, and go back to first step\n */\n protected reset() {\n this.step = 1;\n this.wizardGrid.load(this.getInitialEntity());\n }\n\n /**\n * is called when user clicks the Finish button (next button on last step)\n */\n protected finish() {\n this.dialogClose();\n }\n\n /**\n * next method is called when user tries to go forward\n * @param toStep the step user is trying to move to, usually one step ahead\n */\n protected next(toStep: number) {\n this.step = toStep;\n }\n\n /**\n * back method is called when user tries to go backward\n * @param toStep the step user is trying to move to, usually one step back but can also be multiple\n */\n protected back(toStep: number) {\n this.step = toStep;\n }\n\n private getStepLink(step: number) {\n return this.wizardGrid.element\n .children(\".property-tabs\")\n .children(\"li\").eq(step - 1);\n }\n\n private getStepPanel(step: number) {\n return this.wizardGrid.element\n .children(\".property-panes\")\n .children().eq(step - 1)\n }\n\n /**\n * make sure derived classes use WizardDialog template,\n * if they don't define one of their own\n */\n protected getFallbackTemplate() {\n return `\n
    \n
    \n
    \n
    \n\n
    \n \n \n \n
    \n
    \n
    `;\n }\n\n /**\n * gets cancel confirmation message, return null to disable confirmation\n */\n protected getCancelMessage() {\n return localText(\"Site.WizardDialog.CancelMessage\");\n }\n\n /**\n * confirms when user tries to cancel or close the wizard\n * @param e\n */\n protected confirmCancel(e: JQueryEventObject) {\n var cancelMessage = this.getCancelMessage();\n if (!cancelMessage) {\n e.preventDefault();\n this.dialogClose();\n return;\n }\n\n e.preventDefault();\n confirmDialog(cancelMessage,\n () => {\n this.dialogClose();\n });\n }\n\n /** gets save entity from form, optionally from a limited list of steps (tabs)\n * @param steps the list of steps to read data from, pass null to get all\n */\n protected getSaveEntity(steps?: number[]): TEntity {\n var entity = {} as TEntity;\n this.wizardGrid.save(entity);\n\n if (steps != null) {\n var maxSteps = this.maxSteps;\n for (var i = 1; i <= maxSteps; i++) {\n if (steps.indexOf(i) >= 0)\n continue;\n\n var panel = this.getStepPanel(i);\n panel.find('.field').each((z, el) => {\n var field = $(el).attr('class').split(' ')[1];\n if (field)\n delete entity[field];\n });\n }\n }\n\n return entity;\n }\n\n // gets value of compact steps option\n protected get compactSteps() {\n return this.element.children().hasClass(\"compact-steps\");\n }\n\n // sets value of compact steps option, when it is on, inactive step titles only show\n // numbers and gets visible on hover. this is better there are many steps to fit\n protected set compactSteps(value: boolean) {\n this.element.children().toggleClass(\"compact-steps\", value);\n }\n}\n", "\uFEFFimport { PasswordEditor, PrefixedContext, initFormType } from \"@serenity-is/corelib\";\n\nexport interface ElevateForm {\n Password: PasswordEditor;\n}\n\nexport class ElevateForm extends PrefixedContext {\n static readonly formKey = 'Membership.Elevate';\n private static init: boolean;\n\n constructor(prefix: string) {\n super(prefix);\n\n if (!ElevateForm.init) {\n ElevateForm.init = true;\n\n var w0 = PasswordEditor;\n\n initFormType(ElevateForm, [\n 'Password', w0\n ]);\n }\n }\n}", "\uFEFFimport { proxyTexts } from \"@serenity-is/corelib\";\n\nnamespace Serenity.Pro.Extensions.Texts {\n\n export declare namespace Controls {\n\n namespace IdleTimeout {\n export const CountdownMessage: string;\n export const KeepAliveButton: string;\n export const SignoutButton: string;\n export const WarningMessage: string;\n export const WarningTitle: string;\n }\n }\n\n export declare namespace Db {\n\n namespace Pro {\n\n namespace Extensions {\n\n namespace FileSystem {\n export const Contents: string;\n export const CreationTime: string;\n export const Extension: string;\n export const Filename: string;\n export const FullPath: string;\n export const Id: string;\n export const IsDirectory: string;\n export const LastWriteTime: string;\n export const Metadata: string;\n export const ParentPath: string;\n export const Size: string;\n }\n }\n }\n }\n\n export declare namespace Forms {\n\n namespace Membership {\n\n namespace Elevation {\n export const ActionRequiresElevation: string;\n export const ConfirmAccess: string;\n export const ElevateButton: string;\n export const FormTitle: string;\n export const InvalidPassword: string;\n }\n }\n }\n\n export declare namespace Site {\n\n namespace CardViewMixin {\n export const CardView: string;\n export const ListView: string;\n }\n\n namespace DraggableGroupingMixin {\n export const CollapseAllButton: string;\n export const DropPlaceholder: string;\n export const ExpandAllButton: string;\n }\n\n namespace FavoriteViewsMixin {\n export const DeleteButtonHint: string;\n export const DeleteSuccessMessage: string;\n export const EmptyNameError: string;\n export const FavoriteViews: string;\n export const LoadedViewMessage: string;\n export const SaveButton: string;\n export const SaveSuccessMessage: string;\n export const SaveView: string;\n }\n\n namespace HeaderFiltersMixin {\n export const CancelButton: string;\n export const ClearButton: string;\n export const OkButton: string;\n export const Search: string;\n export const SelectAll: string;\n }\n\n namespace WizardDialog {\n export const BackButton: string;\n export const CancelButton: string;\n export const CancelMessage: string;\n export const FinishButton: string;\n export const NextButton: string;\n }\n\n }\n\n Serenity.Pro.Extensions['Texts'] = proxyTexts(Texts, '', {\n Controls: {\n IdleTimeout: {}\n },\n Db: {\n Pro: {\n Extensions: {\n FileSystem: {}\n }\n }\n },\n Forms: {\n Membership: {\n Elevation: {}\n }\n },\n Site: {\n CardViewMixin: {},\n DraggableGroupingMixin: {},\n FavoriteViewsMixin: {},\n HeaderFiltersMixin: {},\n WizardDialog: {}\n }\n }) as any;\n}\n\nexport const Texts = Serenity.Pro.Extensions.Texts;", "/** @jsxImportSource jsx-dom */\nimport { ElevateRequest } from \"@/ServerTypes/Pro\";\nimport { ElevateForm } from \"@/ServerTypes/Pro/Extensions.ElevateForm\";\nimport { Texts } from \"@/ServerTypes/Texts\";\nimport { PropertyPanel } from \"@serenity-is/corelib\";\nimport { parseQueryString, resolveUrl, serviceCall } from \"@serenity-is/corelib\";\n\nconst myTexts = Texts.Forms.Membership.Elevation;\n\nexport default function pageInit() {\n new ElevationPanel($('#PanelDiv').addClass(\"d-flex flex-grow-1 align-items-center\"));\n}\n\nexport class ElevationPanel extends PropertyPanel {\n\n protected getFormKey() {\n return ElevateForm.formKey;\n }\n\n protected getReturnUrl() {\n var q = parseQueryString();\n return q['returnUrl'] || q['ReturnUrl'];\n }\n\n protected redirectToReturnUrl() {\n var returnUrl = this.getReturnUrl();\n if (returnUrl && /^\\//.test(returnUrl)) {\n var hash = window.location.hash;\n if (hash != null && hash != '#')\n returnUrl += hash;\n window.location.href = returnUrl;\n }\n else {\n window.location.href = resolveUrl('~/');\n }\n }\n\n submitClick() {\n if (!this.validateForm()) {\n return;\n }\n\n var request = this.propertyGrid.save();\n\n serviceCall({\n url: resolveUrl('~/Account/Elevate'),\n request,\n onSuccess: () => {\n this.redirectToReturnUrl()\n }\n });\n }\n\n renderContents() {\n const id = this.useIdPrefix();\n this.element.empty().append(\n
    \n
    \n
    {myTexts.ConfirmAccess}
    \n

    {myTexts.ActionRequiresElevation}

    \n
    \n
    \n \n
    \n
    \n
    \n )\n }\n}\n\n", "/* eslint-disable */\nconst keys = Object.keys\nfunction identity(value) {\n return value\n}\nfunction isBoolean(val) {\n return typeof val === \"boolean\"\n}\nfunction isElement(val) {\n return val && typeof val.nodeType === \"number\"\n}\nfunction isString(val) {\n return typeof val === \"string\"\n}\nfunction isNumber(val) {\n return typeof val === \"number\"\n}\nfunction isObject(val) {\n return typeof val === \"object\" ? val !== null : isFunction(val)\n}\nfunction isFunction(val) {\n return typeof val === \"function\"\n}\nfunction isComponentClass(Component) {\n const { prototype } = Component\n return !!(prototype && prototype.isReactComponent)\n}\nfunction isArrayLike(obj) {\n return isObject(obj) && typeof obj.length === \"number\" && typeof obj.nodeType !== \"number\"\n}\nfunction forEach(value, fn) {\n if (!value) return\n for (const key of keys(value)) {\n fn(value[key], key)\n }\n}\n\nfunction createRef() {\n return Object.seal({\n current: null,\n })\n}\nfunction isRef(maybeRef) {\n return isObject(maybeRef) && \"current\" in maybeRef\n}\n\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found on\n * https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/LICENSE\n */\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\nconst isUnitlessNumber = {\n animationIterationCount: 0,\n borderImageOutset: 0,\n borderImageSlice: 0,\n borderImageWidth: 0,\n boxFlex: 0,\n boxFlexGroup: 0,\n boxOrdinalGroup: 0,\n columnCount: 0,\n columns: 0,\n flex: 0,\n flexGrow: 0,\n flexPositive: 0,\n flexShrink: 0,\n flexNegative: 0,\n flexOrder: 0,\n gridArea: 0,\n gridRow: 0,\n gridRowEnd: 0,\n gridRowSpan: 0,\n gridRowStart: 0,\n gridColumn: 0,\n gridColumnEnd: 0,\n gridColumnSpan: 0,\n gridColumnStart: 0,\n fontWeight: 0,\n lineClamp: 0,\n lineHeight: 0,\n opacity: 0,\n order: 0,\n orphans: 0,\n tabSize: 0,\n widows: 0,\n zIndex: 0,\n zoom: 0,\n // SVG-related properties\n fillOpacity: 0,\n floodOpacity: 0,\n stopOpacity: 0,\n strokeDasharray: 0,\n strokeDashoffset: 0,\n strokeMiterlimit: 0,\n strokeOpacity: 0,\n strokeWidth: 0,\n}\n\n/**\n * @param prefix vendor-specific prefix, eg: Webkit\n * @param key style name, eg: transitionDuration\n * @return style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n return prefix + key.charAt(0).toUpperCase() + key.substring(1)\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nconst prefixes = [\"Webkit\", \"ms\", \"Moz\", \"O\"]\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nkeys(isUnitlessNumber).forEach(prop => {\n prefixes.forEach(prefix => {\n isUnitlessNumber[prefixKey(prefix, prop)] = 0 // isUnitlessNumber[prop]\n })\n})\n\nconst jsxDomType = Symbol.for(\"jsx-dom:type\")\nvar JsxDomType = /*#__PURE__*/ (function (JsxDomType) {\n JsxDomType[\"ShadowRoot\"] = \"ShadowRoot\"\n return JsxDomType\n})(JsxDomType || {})\nfunction ShadowRoot(_ref) {\n let { children, ref, ...attr } = _ref\n return {\n [jsxDomType]: JsxDomType.ShadowRoot,\n ref,\n attr,\n children,\n }\n}\nfunction isShadowRoot(el) {\n return el != null && el[jsxDomType] === JsxDomType.ShadowRoot\n}\n\nconst SVGNamespace = \"http://www.w3.org/2000/svg\"\nconst XLinkNamespace = \"http://www.w3.org/1999/xlink\"\nconst XMLNamespace = \"http://www.w3.org/XML/1998/namespace\"\n\n// https://facebook.github.io/react/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored\n// Emulate JSX Expression logic to ignore certain type of children or className.\nfunction isVisibleChild(value) {\n return !isBoolean(value) && value != null\n}\nconst DomTokenList = typeof DOMTokenList !== \"undefined\" ? DOMTokenList : function () {}\n\n/**\n * Convert a `value` to a className string.\n * `value` can be a string, an array or a `Dictionary`.\n */\nfunction className(value) {\n if (Array.isArray(value)) {\n return value.map(className).filter(Boolean).join(\" \")\n } else if (value instanceof DomTokenList) {\n return \"\" + value\n } else if (isObject(value)) {\n return keys(value)\n .filter(k => value[k])\n .join(\" \")\n } else if (isVisibleChild(value)) {\n return \"\" + value\n } else {\n return \"\"\n }\n}\nconst svg = {\n animate: 0,\n circle: 0,\n clipPath: 0,\n defs: 0,\n desc: 0,\n ellipse: 0,\n feBlend: 0,\n feColorMatrix: 0,\n feComponentTransfer: 0,\n feComposite: 0,\n feConvolveMatrix: 0,\n feDiffuseLighting: 0,\n feDisplacementMap: 0,\n feDistantLight: 0,\n feFlood: 0,\n feFuncA: 0,\n feFuncB: 0,\n feFuncG: 0,\n feFuncR: 0,\n feGaussianBlur: 0,\n feImage: 0,\n feMerge: 0,\n feMergeNode: 0,\n feMorphology: 0,\n feOffset: 0,\n fePointLight: 0,\n feSpecularLighting: 0,\n feSpotLight: 0,\n feTile: 0,\n feTurbulence: 0,\n filter: 0,\n foreignObject: 0,\n g: 0,\n image: 0,\n line: 0,\n linearGradient: 0,\n marker: 0,\n mask: 0,\n metadata: 0,\n path: 0,\n pattern: 0,\n polygon: 0,\n polyline: 0,\n radialGradient: 0,\n rect: 0,\n stop: 0,\n svg: 0,\n switch: 0,\n symbol: 0,\n text: 0,\n textPath: 0,\n tspan: 0,\n use: 0,\n view: 0,\n}\nconst nonPresentationSVGAttributes =\n /^(a(ll|t|u)|base[FP]|c(al|lipPathU|on)|di|ed|ex|filter[RU]|g(lyphR|r)|ke|l(en|im)|ma(rker[HUW]|s)|n|pat|pr|point[^e]|re[^n]|s[puy]|st[^or]|ta|textL|vi|xC|y|z)/\nfunction createFactory(tag) {\n return createElement.bind(null, tag)\n}\nfunction Fragment(attr) {\n const fragment = document.createDocumentFragment()\n appendChild(attr.children, fragment)\n return fragment\n}\nclass Component {\n constructor(props) {\n this.props = props\n }\n render() {\n return null\n }\n}\n\n/* @__PURE__ */\nObject.defineProperties(Component.prototype, {\n isReactComponent: {\n value: true,\n },\n})\nfunction initComponentClass(Class, attr, children) {\n attr = {\n ...attr,\n children,\n }\n const instance = new Class(attr)\n return instance.render()\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction jsx(tag, _ref) {\n let { children, ...attr } = _ref\n if (!attr.namespaceURI && svg[tag] === 0) {\n attr = {\n ...attr,\n namespaceURI: SVGNamespace,\n }\n }\n let node\n if (isString(tag)) {\n node = attr.namespaceURI\n ? document.createElementNS(attr.namespaceURI, tag)\n : document.createElement(tag)\n attributes(attr, node)\n appendChild(children, node)\n\n // Select `option` elements in `select`\n if (node instanceof window.HTMLSelectElement && attr.value != null) {\n if (attr.multiple === true && Array.isArray(attr.value)) {\n const values = attr.value.map(value => String(value))\n node\n .querySelectorAll(\"option\")\n .forEach(option => (option.selected = values.includes(option.value)))\n } else {\n node.value = attr.value\n }\n }\n attachRef(attr.ref, node)\n } else if (isFunction(tag)) {\n // Custom elements.\n if (isObject(tag.defaultProps)) {\n attr = {\n ...tag.defaultProps,\n ...attr,\n }\n }\n node = isComponentClass(tag)\n ? initComponentClass(tag, attr, children)\n : tag({\n ...attr,\n children,\n })\n } else {\n throw new TypeError(`Invalid JSX element type: ${tag}`)\n }\n return node\n}\nfunction createElement(tag, attr) {\n for (\n var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key2 = 2;\n _key2 < _len;\n _key2++\n ) {\n children[_key2 - 2] = arguments[_key2]\n }\n if (isString(attr) || Array.isArray(attr)) {\n children.unshift(attr)\n attr = {}\n }\n attr = attr || {}\n if (attr.children != null && !children.length) {\n ;({ children, ...attr } = attr)\n }\n return jsx(\n tag,\n {\n ...attr,\n children,\n },\n attr.key\n )\n}\nfunction attachRef(ref, node) {\n if (isRef(ref)) {\n ref.current = node\n } else if (isFunction(ref)) {\n ref(node)\n }\n}\nfunction appendChild(child, node) {\n if (isArrayLike(child)) {\n appendChildren(child, node)\n } else if (isString(child) || isNumber(child)) {\n appendChildToNode(document.createTextNode(child), node)\n } else if (child === null) {\n appendChildToNode(document.createComment(\"\"), node)\n } else if (isElement(child)) {\n appendChildToNode(child, node)\n } else if (isShadowRoot(child)) {\n const shadowRoot = node.attachShadow(child.attr)\n appendChild(child.children, shadowRoot)\n attachRef(child.ref, shadowRoot)\n }\n}\nfunction appendChildren(children, node) {\n for (const child of [...children]) {\n appendChild(child, node)\n }\n return node\n}\nfunction appendChildToNode(child, node) {\n if (node instanceof window.HTMLTemplateElement) {\n node.content.appendChild(child)\n } else {\n node.appendChild(child)\n }\n}\nfunction normalizeAttribute(s, separator) {\n return s.replace(/[A-Z]/g, match => separator + match.toLowerCase())\n}\nfunction style(node, value) {\n if (value == null || value === false);\n else if (Array.isArray(value)) {\n value.forEach(v => style(node, v))\n } else if (isString(value)) {\n node.setAttribute(\"style\", value)\n } else if (isObject(value)) {\n forEach(value, (val, key) => {\n if (key.indexOf(\"-\") === 0) {\n // CSS custom properties (variables) start with `-` (e.g. `--my-variable`)\n // and must be assigned via `setProperty`.\n node.style.setProperty(key, val)\n } else if (isNumber(val) && isUnitlessNumber[key] !== 0) {\n node.style[key] = val + \"px\"\n } else {\n node.style[key] = val\n }\n })\n }\n}\nfunction attribute(key, value, node) {\n switch (key) {\n case \"xlinkActuate\":\n case \"xlinkArcrole\":\n case \"xlinkHref\":\n case \"xlinkRole\":\n case \"xlinkShow\":\n case \"xlinkTitle\":\n case \"xlinkType\":\n attrNS(node, XLinkNamespace, normalizeAttribute(key, \":\"), value)\n return\n case \"xmlnsXlink\":\n attr(node, normalizeAttribute(key, \":\"), value)\n return\n case \"xmlBase\":\n case \"xmlLang\":\n case \"xmlSpace\":\n attrNS(node, XMLNamespace, normalizeAttribute(key, \":\"), value)\n return\n }\n switch (key) {\n case \"htmlFor\":\n attr(node, \"for\", value)\n return\n case \"dataset\":\n forEach(value, (dataValue, dataKey) => {\n if (dataValue != null) {\n node.dataset[dataKey] = dataValue\n }\n })\n return\n case \"innerHTML\":\n case \"innerText\":\n case \"textContent\":\n if (isVisibleChild(value)) {\n node[key] = value\n }\n return\n case \"dangerouslySetInnerHTML\":\n if (isObject(value)) {\n node.innerHTML = value[\"__html\"]\n }\n return\n case \"value\":\n if (value == null || node instanceof window.HTMLSelectElement) {\n // skip nullish values\n // for `