) => {\n\t\t\t// Sometimes a change event will come through that was not related to\n\t\t\t// interacting directly with the input\n\t\t\t// I cannot seem to recreate this in the tests yet, but this is an\n\t\t\t// important chack\n\t\t\tif (!event) return;\n\n\t\t\tconst {value} = event.target;\n\t\t\tform && form.setValue(name, value);\n\t\t\tonChange && onChange(value);\n\t\t},\n\t\t[form?.setValue, name, onChange],\n\t);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t{!hideErrorMessage ? (\n\t\t\t\t\n\t\t\t) : null}\n\t\t\n\t);\n};\n\nexport const TextField = React.memo(TextFieldPrimitive);\nexport default TextField;\n","import React from 'react';\n\nimport TextField, {TextFieldProps} from './TextField';\nimport ReadOnlyTextField, {ReadOnlyTextFieldProps} from './ReadOnlyTextField';\n\nexport {default as ReadOnlyTextField} from './ReadOnlyTextField';\nexport * from './ReadOnlyTextField';\n\nexport {default as TextField} from './TextField';\nexport * from './TextField';\n\ntype ExternalProps = TextFieldProps | ReadOnlyTextFieldProps;\n\ntype InternalProps = {\n\treadOnly?: boolean;\n};\n\nexport default function ({readOnly, ...props}: InternalProps & ExternalProps) {\n\treturn !readOnly ? (\n\t\t\n\t) : (\n\t\t\n\t);\n}\n","import {AssetGalleryAsset} from '@netx/core-asset-gallery/types';\nexport const assetExpires = (asset: AssetGalleryAsset) =>\n\t!!asset.expirationDate;\nexport default assetExpires;\n","import moment from 'moment';\n\nexport const userInputToExpirationTime = (expirationDate: string) => {\n\tconst date = moment(expirationDate).endOf('day');\n\tdate.utc();\n\n\tconst tomorrow = moment().utc(false).add(1, 'day').valueOf();\n\n\t// Make sure date is valid and that it is greater than or equal to tomorrow\n\tif (!date.isValid() || date.valueOf() < tomorrow) {\n\t\tthrow new Error('Invalid expiration date');\n\t}\n\n\treturn date.valueOf();\n};\n\nexport default userInputToExpirationTime;\n","import { parseQueryArgs, QueryObserver } from '@tanstack/query-core';\nimport { useBaseQuery } from './useBaseQuery.esm.js';\n\nfunction useQuery(arg1, arg2, arg3) {\n const parsedOptions = parseQueryArgs(arg1, arg2, arg3);\n return useBaseQuery(parsedOptions, QueryObserver);\n}\n\nexport { useQuery };\n//# sourceMappingURL=useQuery.esm.js.map\n","import React, {FunctionComponent, useEffect, useState} from 'react';\n\nimport _ from 'underscore';\n\nimport {Tooltip as MuiTooltip, TooltipProps} from '@mui/material';\nimport {useUpdateEffect} from '../hooks/useUpdateEffect';\nexport type {TooltipProps} from '@mui/material';\n\n/**\n * Wrapper for MUI Tolltip\n *\n * Dismiss tooltip on scroll\n */\nexport const Tooltip: FunctionComponent<\n\tTooltipProps & {\n\t\tdisabled?: boolean;\n\t}\n> = ({disabled, children, title, open: _open, ...props}) => {\n\tconst [open, setOpen] = useState(_open || false);\n\n\tuseEffect(() => {\n\t\tif (!open) return;\n\n\t\tconst listener = _.throttle(() => {\n\t\t\tsetOpen(false);\n\t\t}, 50);\n\n\t\twindow.addEventListener('scroll', listener, true);\n\t\treturn () => {\n\t\t\twindow.removeEventListener('scroll', listener, true);\n\t\t};\n\t}, [open]);\n\n\tconst toggleOpen = (open: boolean) => () => setOpen(disabled ? false : open);\n\n\tuseUpdateEffect(() => {\n\t\t_open != null && setOpen(_open);\n\t}, [_open]);\n\n\tuseUpdateEffect(() => {\n\t\tdisabled && setOpen(false);\n\t}, [disabled]);\n\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport default Tooltip;\n","/**\n * Asset constituent model\n * @class\n */\nimport Base from '@netx/core/lib/netx-model';\n\nimport AssetSetModel from './assetSet';\n\nimport {types as assetSetTypes} from '../properties/assetSets';\n\nexport default class AssetConstituent extends Base {\n\t/**\n\t * @type {Netx.Rpc}\n\t * @private\n\t */\n\tget rpc() {\n\t\treturn true;\n\t}\n\t/**\n\t * @type {Netx.URL}\n\t * @private\n\t */\n\tget url() {\n\t\treturn Netx.URL.api;\n\t}\n\n\t/**\n\t * The unique ID for this model is \"id\"\n\t * @type {string}\n\t */\n\tget idAttribute() {\n\t\treturn 'constituentId';\n\t}\n\n\t/**\n\t * @property {object} defaults - The default attribute values\n\t * @property {number} defaults.constituentId - Constituent id (Never set the id in defaults)\n\t * @property {number} defaults.display - Display constituent (boolean as number)\n\t * @property {number} defaults.assetId - Asset id (the asset I am a constituent of)\n\t * @property {string} defaults.lowresUrl - Low resolution image (unused?)\n\t * @property {string} defaults.modDate - Modification date string\n\t * @property {string} defaults.previewUrl - Preview image\n\t * @property {number} defaults.rebuildCount - ??? Rebuild count\n\t * @property {number} defaults.rebuildType - ??? Rebuild type\n\t * @property {number} defaults.ref - ???\n\t * @property {string} defaults.thumbUrl - Thumbnail image\n\t * @property {string} defaults.title - Title\n\t * @property {number} defaults.type - 1 = time (keyframe), 2 = layer, 3 = page, 4 = clips\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\t// constituentId : 0,\n\t\t\tattributes: [],\n\t\t\tdisplay: 0,\n\t\t\tassetId: 0,\n\t\t\tlowresUrl: '',\n\t\t\tmodDate: '',\n\t\t\tpreviewUrl: '',\n\t\t\trebuildType: 0,\n\t\t\trebuildCount: 0,\n\t\t\tref: 1,\n\t\t\tthumbUrl: '',\n\t\t\ttitle: '',\n\t\t\ttype: 0,\n\t\t};\n\t}\n\n\t/**\n\t * @property {object} methods - Model RPC methods\n\t * @property {function|array} methods.read - Fetch constituent\n\t * @property {function|array} methods.setDisplay - Tell the dam to use this constituent as the image thumbnail/preview\n\t */\n\tget methods() {\n\t\treturn {\n\t\t\tread: ['getConstituentObject', 'constituentId'],\n\t\t\tsetDisplay: ['setConstituentDisplay', 'constituentId'],\n\t\t};\n\t}\n\n\t/**\n\t * @property {object} parsers - Model parsers\n\t * @property {function} parsers.setDisplay - Parse the return of our fetch, it is an array with a single record\n\t */\n\tget parsers() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {null} result Result (returns `null` - very helpful)\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tsetDisplay(result, opts) {\n\t\t\t\tthis.set({display: 1});\n\t\t\t\treturn result;\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {object} attrs Model attributes\n\t * @param {object} opts Model options\n\t */\n\tconstructor(attrs, opts = {}) {\n\t\tsuper(attrs, opts);\n\n\t\t/**\n\t\t * @memberof module:asset/models/assetConstituent\n\t\t * @alias clipAttributes\n\t\t * @type {module:asset/collections/attributes}\n\t\t */\n\t\tthis.clipAttributes =\n\t\t\topts.clipAttributes || Netx.getAttributesByObjectType('clip');\n\t}\n\n\t/**\n\t * Check our permissionMatrix for whether a particular named bit is set.\n\t * Pipes through the asset we belong to\n\t * @method\n\t * @param {string} perm One of the permissions in {module:permissions/properties/assetPermissions#matrixNames}\n\t * @returns {mixed} returns true or false, or undefined (which is falsy) if the argument is undefined.\n\t */\n\tallows(perm) {\n\t\t// TODO: better way to handle the contituents having access to the asset bean they belong to\n\t\t// Maybe, rather than passing an assetId to constituents we passa full on bean - that way when it updates\n\t\t// we update and have proper permission matrix rather than relying that the constituent's asset will always\n\t\t// be Netx.asset.current\n\t\tvar currentAsset = Netx.asset.current;\n\t\treturn currentAsset && currentAsset.allows.apply(currentAsset, arguments);\n\t}\n\n\t/**\n\t * Return an assetSet object defining the set that contains just this constituent.\n\t * @method\n\t * @return {module:asset/models/assetSet} AssetSet model\n\t */\n\ttoAssetSet() {\n\t\treturn new AssetSetModel({\n\t\t\ttype: assetSetTypes.asset,\n\t\t\tids: [this.get('assetId')],\n\t\t\tmodels: [this],\n\t\t\tlabel: this.get('title'),\n\t\t\tcanCreateLink: false,\n\t\t\tcanEmail: false,\n\t\t});\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'AssetConstituent';\n\t}\n}\n","import {i18n} from '@netx/core/i18n';\nimport {notMobile} from '@netx/core/lib/netx-enablers';\n\nexport let constituents = {\n\ttypes: {\n\t\t1: 'keyframe',\n\t\t2: 'layer',\n\t\t3: 'page',\n\t\t4: 'clip',\n\t},\n\ttypeNames: {\n\t\t1: 'asset:i18n.consituentsKeyframes',\n\t\t2: 'asset:i18n.consituentsLayers',\n\t\t3: 'asset:i18n.consituentsPages',\n\t\t4: 'asset:i18n.consituentsClips',\n\t},\n};\n\nexport let dragUserLevel = 8;\n\n// Tasks that run on assets at import\nexport let importTasks = {\n\tAudioTask: i18n.t('i18n.performingTaskAudio'),\n\tFFFViewTask: i18n.t('i18n.performingTaskFFFView'),\n\tINDDPageTask: i18n.t('i18n.performingTaskINDDPage'),\n\tIWorkPageTask: i18n.t('i18n.performingTaskIWorkPage'),\n\tKeyframesTask: i18n.t('i18n.performingTaskKeyframes'),\n\tMetadataTask: i18n.t('i18n.performingTaskMetadata'),\n\tOfficePageTask: i18n.t('i18n.performingTaskOfficePage'),\n\tPDFPageTask: i18n.t('i18n.performingTaskPDFPage'),\n\tPostImportTask: i18n.t('i18n.performingTaskPostImport'),\n\tPreviewTask: i18n.t('i18n.performingTaskPreview'),\n\tRelatedAssetTask: i18n.t('i18n.performingTaskRelatedAssets'),\n\tSWFTask: i18n.t('i18n.performingTaskSWF'),\n\tThumbnailTask: i18n.t('i18n.performingTaskThumbnail'),\n\tVideoPreviewTask: i18n.t('i18n.performingTaskVideoPeview'),\n\tWatermarkTask: i18n.t('i18n.performingTaskWatermark'),\n\tZoomTask: i18n.t('i18n.performingTaskZoom'),\n};\n\nexport let renderableChanges = [\n\t'attributeIds',\n\t'attributeNames',\n\t'attributeValues',\n\t'checkout',\n\t'creationdate',\n\t'expirationDate',\n\t'file',\n\t'fileSize2',\n\t'fileheight',\n\t'filesize',\n\t'filetype',\n\t'filetypelabel',\n\t'filewidth',\n\t'geoLocationLabel',\n\t'imageid',\n\t'importDate',\n\t'locationContext',\n\t'locationid',\n\t'moddate',\n\t'moduserid',\n\t'moduserlabel',\n\t'name',\n\t'path',\n\t'permissionMatrix',\n\t'previewHeight',\n\t'previewUrl',\n\t'previewWidth',\n\t'readOnly',\n\t'repurposeAvailability',\n\t'status',\n\t'thumb',\n\t'thumbUrl',\n\t'versionIds',\n\t'viewIds',\n\t'viewNames',\n\t'zoomAvailable',\n];\n\nexport let status = {\n\tUNKNOWN: 0,\n\tONLINE: 1,\n\tNEARLINE: 2,\n\tOFFLINE: 3,\n\tTEMP: 4,\n\tCHECKOUT: 5,\n\tIMPORT_IN_PROGRESS: 6,\n};\n\nexport let things = {\n\tattributeHistory: {\n\t\tlabel: i18n.t('i18n.attributeHistory'),\n\t\tuserLevel: 4,\n\t\tenableTest: notMobile,\n\t},\n\tattributes: {\n\t\tlabel: i18n.t('i18n.attributes'),\n\t\tuserLevel: 1,\n\t},\n\tcategories: {\n\t\tlabel: i18n.t('i18n.categories'),\n\t\tuserLevel: 2,\n\t},\n\tclips: {\n\t\tlabel: i18n.t('i18n.constituentsClips'),\n\t\tuserLevel: 2,\n\t},\n\tconstituents_keyframes: {\n\t\tlabel: i18n.t('i18n.constituentsKeyframes'),\n\t\tuserLevel: 7,\n\t},\n\tconstituents_layers: {\n\t\tlabel: i18n.t('i18n.constituentsLayers'),\n\t\tuserLevel: 7,\n\t},\n\tconstituents_pages: {\n\t\tlabel: i18n.t('i18n.constituentsPages'),\n\t\tuserLevel: 7,\n\t},\n\tdetail: {\n\t\tlabel: i18n.t('i18n.detail'),\n\t\tmatrix: 'read',\n\t\tuserLevel: 2,\n\t},\n\tfileinfo: {\n\t\tlabel: i18n.t('i18n.fileinfo'),\n\t\tuserLevel: 1,\n\t},\n\tindex: {\n\t\tlabel: i18n.t('i18n.index'),\n\t\tuserLevel: 9,\n\t},\n\tlinks: {\n\t\tlabel: i18n.t('i18n.links'),\n\t\tuserLevel: 2,\n\t},\n\tmetadata: {\n\t\tlabel: i18n.t('i18n.metadata'),\n\t\tuserLevel: 2,\n\t},\n\toverview: {\n\t\tlabel: i18n.t('i18n.overview'),\n\t\tuserLevel: 2,\n\t},\n\tpermissions: {\n\t\tlabel: i18n.t('i18n.permissions'),\n\t\tuserLevel: 8,\n\t},\n\tpreview: {\n\t\tlabel: i18n.t('i18n.preview'),\n\t\tuserLevel: 1,\n\t},\n\tprojects: {\n\t\tlabel: i18n.t('i18n.projects'),\n\t\tuserLevel: 1,\n\t\tenableTest: notMobile,\n\t},\n\tpublicLinks: {\n\t\tlabel: i18n.t('i18n.publicLinks'),\n\t\tuserLevel: 7,\n\t},\n\treviews: {\n\t\tlabel: i18n.t('i18n.reviews'),\n\t\tuserLevel: 1,\n\t\tenableTest: notMobile,\n\t},\n\tusage: {\n\t\tlabel: i18n.t('i18n.usage'),\n\t\tuserLevel: 7,\n\t},\n\tversions: {\n\t\tlabel: i18n.t('i18n.versions'),\n\t\tuserLevel: 4,\n\t},\n\tviews: {\n\t\tlabel: i18n.t('i18n.views'),\n\t\tuserLevel: 2,\n\t},\n};\n\nexport default {\n\tconstituents,\n\tdragUserLevel,\n\timportTasks,\n\trenderableChanges,\n\tstatus,\n\tthings,\n};\n","import { replaceData, noop, timeUntilStale, getAbortController } from './utils.esm.js';\nimport { defaultLogger } from './logger.esm.js';\nimport { notifyManager } from './notifyManager.esm.js';\nimport { createRetryer, isCancelledError, canFetch } from './retryer.esm.js';\nimport { Removable } from './removable.esm.js';\n\n// CLASS\nclass Query extends Removable {\n constructor(config) {\n super();\n this.abortSignalConsumed = false;\n this.defaultOptions = config.defaultOptions;\n this.setOptions(config.options);\n this.observers = [];\n this.cache = config.cache;\n this.logger = config.logger || defaultLogger;\n this.queryKey = config.queryKey;\n this.queryHash = config.queryHash;\n this.initialState = config.state || getDefaultState(this.options);\n this.state = this.initialState;\n }\n\n get meta() {\n return this.options.meta;\n }\n\n setOptions(options) {\n this.options = { ...this.defaultOptions,\n ...options\n };\n this.updateCacheTime(this.options.cacheTime);\n }\n\n optionalRemove() {\n if (!this.observers.length && this.state.fetchStatus === 'idle') {\n this.cache.remove(this);\n }\n }\n\n setData(newData, options) {\n const data = replaceData(this.state.data, newData, this.options); // Set data and mark it as cached\n\n this.dispatch({\n data,\n type: 'success',\n dataUpdatedAt: options == null ? void 0 : options.updatedAt,\n manual: options == null ? void 0 : options.manual\n });\n return data;\n }\n\n setState(state, setStateOptions) {\n this.dispatch({\n type: 'setState',\n state,\n setStateOptions\n });\n }\n\n cancel(options) {\n var _this$retryer;\n\n const promise = this.promise;\n (_this$retryer = this.retryer) == null ? void 0 : _this$retryer.cancel(options);\n return promise ? promise.then(noop).catch(noop) : Promise.resolve();\n }\n\n destroy() {\n super.destroy();\n this.cancel({\n silent: true\n });\n }\n\n reset() {\n this.destroy();\n this.setState(this.initialState);\n }\n\n isActive() {\n return this.observers.some(observer => observer.options.enabled !== false);\n }\n\n isDisabled() {\n return this.getObserversCount() > 0 && !this.isActive();\n }\n\n isStale() {\n return this.state.isInvalidated || !this.state.dataUpdatedAt || this.observers.some(observer => observer.getCurrentResult().isStale);\n }\n\n isStaleByTime(staleTime = 0) {\n return this.state.isInvalidated || !this.state.dataUpdatedAt || !timeUntilStale(this.state.dataUpdatedAt, staleTime);\n }\n\n onFocus() {\n var _this$retryer2;\n\n const observer = this.observers.find(x => x.shouldFetchOnWindowFocus());\n\n if (observer) {\n observer.refetch({\n cancelRefetch: false\n });\n } // Continue fetch if currently paused\n\n\n (_this$retryer2 = this.retryer) == null ? void 0 : _this$retryer2.continue();\n }\n\n onOnline() {\n var _this$retryer3;\n\n const observer = this.observers.find(x => x.shouldFetchOnReconnect());\n\n if (observer) {\n observer.refetch({\n cancelRefetch: false\n });\n } // Continue fetch if currently paused\n\n\n (_this$retryer3 = this.retryer) == null ? void 0 : _this$retryer3.continue();\n }\n\n addObserver(observer) {\n if (this.observers.indexOf(observer) === -1) {\n this.observers.push(observer); // Stop the query from being garbage collected\n\n this.clearGcTimeout();\n this.cache.notify({\n type: 'observerAdded',\n query: this,\n observer\n });\n }\n }\n\n removeObserver(observer) {\n if (this.observers.indexOf(observer) !== -1) {\n this.observers = this.observers.filter(x => x !== observer);\n\n if (!this.observers.length) {\n // If the transport layer does not support cancellation\n // we'll let the query continue so the result can be cached\n if (this.retryer) {\n if (this.abortSignalConsumed) {\n this.retryer.cancel({\n revert: true\n });\n } else {\n this.retryer.cancelRetry();\n }\n }\n\n this.scheduleGc();\n }\n\n this.cache.notify({\n type: 'observerRemoved',\n query: this,\n observer\n });\n }\n }\n\n getObserversCount() {\n return this.observers.length;\n }\n\n invalidate() {\n if (!this.state.isInvalidated) {\n this.dispatch({\n type: 'invalidate'\n });\n }\n }\n\n fetch(options, fetchOptions) {\n var _this$options$behavio, _context$fetchOptions;\n\n if (this.state.fetchStatus !== 'idle') {\n if (this.state.dataUpdatedAt && fetchOptions != null && fetchOptions.cancelRefetch) {\n // Silently cancel current fetch if the user wants to cancel refetches\n this.cancel({\n silent: true\n });\n } else if (this.promise) {\n var _this$retryer4;\n\n // make sure that retries that were potentially cancelled due to unmounts can continue\n (_this$retryer4 = this.retryer) == null ? void 0 : _this$retryer4.continueRetry(); // Return current promise if we are already fetching\n\n return this.promise;\n }\n } // Update config if passed, otherwise the config from the last execution is used\n\n\n if (options) {\n this.setOptions(options);\n } // Use the options from the first observer with a query function if no function is found.\n // This can happen when the query is hydrated or created with setQueryData.\n\n\n if (!this.options.queryFn) {\n const observer = this.observers.find(x => x.options.queryFn);\n\n if (observer) {\n this.setOptions(observer.options);\n }\n }\n\n if (!Array.isArray(this.options.queryKey)) {\n if (process.env.NODE_ENV !== 'production') {\n this.logger.error(\"As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']\");\n }\n }\n\n const abortController = getAbortController(); // Create query function context\n\n const queryFnContext = {\n queryKey: this.queryKey,\n pageParam: undefined,\n meta: this.meta\n }; // Adds an enumerable signal property to the object that\n // which sets abortSignalConsumed to true when the signal\n // is read.\n\n const addSignalProperty = object => {\n Object.defineProperty(object, 'signal', {\n enumerable: true,\n get: () => {\n if (abortController) {\n this.abortSignalConsumed = true;\n return abortController.signal;\n }\n\n return undefined;\n }\n });\n };\n\n addSignalProperty(queryFnContext); // Create fetch function\n\n const fetchFn = () => {\n if (!this.options.queryFn) {\n return Promise.reject('Missing queryFn');\n }\n\n this.abortSignalConsumed = false;\n return this.options.queryFn(queryFnContext);\n }; // Trigger behavior hook\n\n\n const context = {\n fetchOptions,\n options: this.options,\n queryKey: this.queryKey,\n state: this.state,\n fetchFn\n };\n addSignalProperty(context);\n (_this$options$behavio = this.options.behavior) == null ? void 0 : _this$options$behavio.onFetch(context); // Store state in case the current fetch needs to be reverted\n\n this.revertState = this.state; // Set to fetching state if not already in it\n\n if (this.state.fetchStatus === 'idle' || this.state.fetchMeta !== ((_context$fetchOptions = context.fetchOptions) == null ? void 0 : _context$fetchOptions.meta)) {\n var _context$fetchOptions2;\n\n this.dispatch({\n type: 'fetch',\n meta: (_context$fetchOptions2 = context.fetchOptions) == null ? void 0 : _context$fetchOptions2.meta\n });\n }\n\n const onError = error => {\n // Optimistically update state if needed\n if (!(isCancelledError(error) && error.silent)) {\n this.dispatch({\n type: 'error',\n error: error\n });\n }\n\n if (!isCancelledError(error)) {\n var _this$cache$config$on, _this$cache$config;\n\n // Notify cache callback\n (_this$cache$config$on = (_this$cache$config = this.cache.config).onError) == null ? void 0 : _this$cache$config$on.call(_this$cache$config, error, this);\n\n if (process.env.NODE_ENV !== 'production') {\n this.logger.error(error);\n }\n }\n\n if (!this.isFetchingOptimistic) {\n // Schedule query gc after fetching\n this.scheduleGc();\n }\n\n this.isFetchingOptimistic = false;\n }; // Try to fetch the data\n\n\n this.retryer = createRetryer({\n fn: context.fetchFn,\n abort: abortController == null ? void 0 : abortController.abort.bind(abortController),\n onSuccess: data => {\n var _this$cache$config$on2, _this$cache$config2;\n\n if (typeof data === 'undefined') {\n if (process.env.NODE_ENV !== 'production') {\n this.logger.error(\"Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: \" + this.queryHash);\n }\n\n onError(new Error('undefined'));\n return;\n }\n\n this.setData(data); // Notify cache callback\n\n (_this$cache$config$on2 = (_this$cache$config2 = this.cache.config).onSuccess) == null ? void 0 : _this$cache$config$on2.call(_this$cache$config2, data, this);\n\n if (!this.isFetchingOptimistic) {\n // Schedule query gc after fetching\n this.scheduleGc();\n }\n\n this.isFetchingOptimistic = false;\n },\n onError,\n onFail: (failureCount, error) => {\n this.dispatch({\n type: 'failed',\n failureCount,\n error\n });\n },\n onPause: () => {\n this.dispatch({\n type: 'pause'\n });\n },\n onContinue: () => {\n this.dispatch({\n type: 'continue'\n });\n },\n retry: context.options.retry,\n retryDelay: context.options.retryDelay,\n networkMode: context.options.networkMode\n });\n this.promise = this.retryer.promise;\n return this.promise;\n }\n\n dispatch(action) {\n const reducer = state => {\n var _action$meta, _action$dataUpdatedAt;\n\n switch (action.type) {\n case 'failed':\n return { ...state,\n fetchFailureCount: action.failureCount,\n fetchFailureReason: action.error\n };\n\n case 'pause':\n return { ...state,\n fetchStatus: 'paused'\n };\n\n case 'continue':\n return { ...state,\n fetchStatus: 'fetching'\n };\n\n case 'fetch':\n return { ...state,\n fetchFailureCount: 0,\n fetchFailureReason: null,\n fetchMeta: (_action$meta = action.meta) != null ? _action$meta : null,\n fetchStatus: canFetch(this.options.networkMode) ? 'fetching' : 'paused',\n ...(!state.dataUpdatedAt && {\n error: null,\n status: 'loading'\n })\n };\n\n case 'success':\n return { ...state,\n data: action.data,\n dataUpdateCount: state.dataUpdateCount + 1,\n dataUpdatedAt: (_action$dataUpdatedAt = action.dataUpdatedAt) != null ? _action$dataUpdatedAt : Date.now(),\n error: null,\n isInvalidated: false,\n status: 'success',\n ...(!action.manual && {\n fetchStatus: 'idle',\n fetchFailureCount: 0,\n fetchFailureReason: null\n })\n };\n\n case 'error':\n const error = action.error;\n\n if (isCancelledError(error) && error.revert && this.revertState) {\n return { ...this.revertState\n };\n }\n\n return { ...state,\n error: error,\n errorUpdateCount: state.errorUpdateCount + 1,\n errorUpdatedAt: Date.now(),\n fetchFailureCount: state.fetchFailureCount + 1,\n fetchFailureReason: error,\n fetchStatus: 'idle',\n status: 'error'\n };\n\n case 'invalidate':\n return { ...state,\n isInvalidated: true\n };\n\n case 'setState':\n return { ...state,\n ...action.state\n };\n }\n };\n\n this.state = reducer(this.state);\n notifyManager.batch(() => {\n this.observers.forEach(observer => {\n observer.onQueryUpdate(action);\n });\n this.cache.notify({\n query: this,\n type: 'updated',\n action\n });\n });\n }\n\n}\n\nfunction getDefaultState(options) {\n const data = typeof options.initialData === 'function' ? options.initialData() : options.initialData;\n const hasData = typeof data !== 'undefined';\n const initialDataUpdatedAt = hasData ? typeof options.initialDataUpdatedAt === 'function' ? options.initialDataUpdatedAt() : options.initialDataUpdatedAt : 0;\n return {\n data,\n dataUpdateCount: 0,\n dataUpdatedAt: hasData ? initialDataUpdatedAt != null ? initialDataUpdatedAt : Date.now() : 0,\n error: null,\n errorUpdateCount: 0,\n errorUpdatedAt: 0,\n fetchFailureCount: 0,\n fetchFailureReason: null,\n fetchMeta: null,\n isInvalidated: false,\n status: hasData ? 'success' : 'loading',\n fetchStatus: 'idle'\n };\n}\n\nexport { Query };\n//# sourceMappingURL=query.esm.js.map\n","import { hashQueryKeyByOptions, parseFilterArgs, matchQuery } from './utils.esm.js';\nimport { Query } from './query.esm.js';\nimport { notifyManager } from './notifyManager.esm.js';\nimport { Subscribable } from './subscribable.esm.js';\n\n// CLASS\nclass QueryCache extends Subscribable {\n constructor(config) {\n super();\n this.config = config || {};\n this.queries = [];\n this.queriesMap = {};\n }\n\n build(client, options, state) {\n var _options$queryHash;\n\n const queryKey = options.queryKey;\n const queryHash = (_options$queryHash = options.queryHash) != null ? _options$queryHash : hashQueryKeyByOptions(queryKey, options);\n let query = this.get(queryHash);\n\n if (!query) {\n query = new Query({\n cache: this,\n logger: client.getLogger(),\n queryKey,\n queryHash,\n options: client.defaultQueryOptions(options),\n state,\n defaultOptions: client.getQueryDefaults(queryKey)\n });\n this.add(query);\n }\n\n return query;\n }\n\n add(query) {\n if (!this.queriesMap[query.queryHash]) {\n this.queriesMap[query.queryHash] = query;\n this.queries.push(query);\n this.notify({\n type: 'added',\n query\n });\n }\n }\n\n remove(query) {\n const queryInMap = this.queriesMap[query.queryHash];\n\n if (queryInMap) {\n query.destroy();\n this.queries = this.queries.filter(x => x !== query);\n\n if (queryInMap === query) {\n delete this.queriesMap[query.queryHash];\n }\n\n this.notify({\n type: 'removed',\n query\n });\n }\n }\n\n clear() {\n notifyManager.batch(() => {\n this.queries.forEach(query => {\n this.remove(query);\n });\n });\n }\n\n get(queryHash) {\n return this.queriesMap[queryHash];\n }\n\n getAll() {\n return this.queries;\n }\n\n find(arg1, arg2) {\n const [filters] = parseFilterArgs(arg1, arg2);\n\n if (typeof filters.exact === 'undefined') {\n filters.exact = true;\n }\n\n return this.queries.find(query => matchQuery(filters, query));\n }\n\n findAll(arg1, arg2) {\n const [filters] = parseFilterArgs(arg1, arg2);\n return Object.keys(filters).length > 0 ? this.queries.filter(query => matchQuery(filters, query)) : this.queries;\n }\n\n notify(event) {\n notifyManager.batch(() => {\n this.listeners.forEach(listener => {\n listener(event);\n });\n });\n }\n\n onFocus() {\n notifyManager.batch(() => {\n this.queries.forEach(query => {\n query.onFocus();\n });\n });\n }\n\n onOnline() {\n notifyManager.batch(() => {\n this.queries.forEach(query => {\n query.onOnline();\n });\n });\n }\n\n}\n\nexport { QueryCache };\n//# sourceMappingURL=queryCache.esm.js.map\n","import { notifyManager } from './notifyManager.esm.js';\nimport { Mutation } from './mutation.esm.js';\nimport { matchMutation, noop } from './utils.esm.js';\nimport { Subscribable } from './subscribable.esm.js';\n\n// CLASS\nclass MutationCache extends Subscribable {\n constructor(config) {\n super();\n this.config = config || {};\n this.mutations = [];\n this.mutationId = 0;\n }\n\n build(client, options, state) {\n const mutation = new Mutation({\n mutationCache: this,\n logger: client.getLogger(),\n mutationId: ++this.mutationId,\n options: client.defaultMutationOptions(options),\n state,\n defaultOptions: options.mutationKey ? client.getMutationDefaults(options.mutationKey) : undefined\n });\n this.add(mutation);\n return mutation;\n }\n\n add(mutation) {\n this.mutations.push(mutation);\n this.notify({\n type: 'added',\n mutation\n });\n }\n\n remove(mutation) {\n this.mutations = this.mutations.filter(x => x !== mutation);\n this.notify({\n type: 'removed',\n mutation\n });\n }\n\n clear() {\n notifyManager.batch(() => {\n this.mutations.forEach(mutation => {\n this.remove(mutation);\n });\n });\n }\n\n getAll() {\n return this.mutations;\n }\n\n find(filters) {\n if (typeof filters.exact === 'undefined') {\n filters.exact = true;\n }\n\n return this.mutations.find(mutation => matchMutation(filters, mutation));\n }\n\n findAll(filters) {\n return this.mutations.filter(mutation => matchMutation(filters, mutation));\n }\n\n notify(event) {\n notifyManager.batch(() => {\n this.listeners.forEach(listener => {\n listener(event);\n });\n });\n }\n\n resumePausedMutations() {\n const pausedMutations = this.mutations.filter(x => x.state.isPaused);\n return notifyManager.batch(() => pausedMutations.reduce((promise, mutation) => promise.then(() => mutation.continue().catch(noop)), Promise.resolve()));\n }\n\n}\n\nexport { MutationCache };\n//# sourceMappingURL=mutationCache.esm.js.map\n","import { parseFilterArgs, parseQueryArgs, functionalUpdate, noop, hashQueryKey, partialMatchKey, hashQueryKeyByOptions } from './utils.esm.js';\nimport { QueryCache } from './queryCache.esm.js';\nimport { MutationCache } from './mutationCache.esm.js';\nimport { focusManager } from './focusManager.esm.js';\nimport { onlineManager } from './onlineManager.esm.js';\nimport { notifyManager } from './notifyManager.esm.js';\nimport { infiniteQueryBehavior } from './infiniteQueryBehavior.esm.js';\nimport { defaultLogger } from './logger.esm.js';\n\n// CLASS\nclass QueryClient {\n constructor(config = {}) {\n this.queryCache = config.queryCache || new QueryCache();\n this.mutationCache = config.mutationCache || new MutationCache();\n this.logger = config.logger || defaultLogger;\n this.defaultOptions = config.defaultOptions || {};\n this.queryDefaults = [];\n this.mutationDefaults = [];\n\n if (process.env.NODE_ENV !== 'production' && config.logger) {\n this.logger.error(\"Passing a custom logger has been deprecated and will be removed in the next major version.\");\n }\n }\n\n mount() {\n this.unsubscribeFocus = focusManager.subscribe(() => {\n if (focusManager.isFocused()) {\n this.resumePausedMutations();\n this.queryCache.onFocus();\n }\n });\n this.unsubscribeOnline = onlineManager.subscribe(() => {\n if (onlineManager.isOnline()) {\n this.resumePausedMutations();\n this.queryCache.onOnline();\n }\n });\n }\n\n unmount() {\n var _this$unsubscribeFocu, _this$unsubscribeOnli;\n\n (_this$unsubscribeFocu = this.unsubscribeFocus) == null ? void 0 : _this$unsubscribeFocu.call(this);\n (_this$unsubscribeOnli = this.unsubscribeOnline) == null ? void 0 : _this$unsubscribeOnli.call(this);\n }\n\n isFetching(arg1, arg2) {\n const [filters] = parseFilterArgs(arg1, arg2);\n filters.fetchStatus = 'fetching';\n return this.queryCache.findAll(filters).length;\n }\n\n isMutating(filters) {\n return this.mutationCache.findAll({ ...filters,\n fetching: true\n }).length;\n }\n\n getQueryData(queryKey, filters) {\n var _this$queryCache$find;\n\n return (_this$queryCache$find = this.queryCache.find(queryKey, filters)) == null ? void 0 : _this$queryCache$find.state.data;\n }\n\n ensureQueryData(arg1, arg2, arg3) {\n const parsedOptions = parseQueryArgs(arg1, arg2, arg3);\n const cachedData = this.getQueryData(parsedOptions.queryKey);\n return cachedData ? Promise.resolve(cachedData) : this.fetchQuery(parsedOptions);\n }\n\n getQueriesData(queryKeyOrFilters) {\n return this.getQueryCache().findAll(queryKeyOrFilters).map(({\n queryKey,\n state\n }) => {\n const data = state.data;\n return [queryKey, data];\n });\n }\n\n setQueryData(queryKey, updater, options) {\n const query = this.queryCache.find(queryKey);\n const prevData = query == null ? void 0 : query.state.data;\n const data = functionalUpdate(updater, prevData);\n\n if (typeof data === 'undefined') {\n return undefined;\n }\n\n const parsedOptions = parseQueryArgs(queryKey);\n const defaultedOptions = this.defaultQueryOptions(parsedOptions);\n return this.queryCache.build(this, defaultedOptions).setData(data, { ...options,\n manual: true\n });\n }\n\n setQueriesData(queryKeyOrFilters, updater, options) {\n return notifyManager.batch(() => this.getQueryCache().findAll(queryKeyOrFilters).map(({\n queryKey\n }) => [queryKey, this.setQueryData(queryKey, updater, options)]));\n }\n\n getQueryState(queryKey, filters) {\n var _this$queryCache$find2;\n\n return (_this$queryCache$find2 = this.queryCache.find(queryKey, filters)) == null ? void 0 : _this$queryCache$find2.state;\n }\n\n removeQueries(arg1, arg2) {\n const [filters] = parseFilterArgs(arg1, arg2);\n const queryCache = this.queryCache;\n notifyManager.batch(() => {\n queryCache.findAll(filters).forEach(query => {\n queryCache.remove(query);\n });\n });\n }\n\n resetQueries(arg1, arg2, arg3) {\n const [filters, options] = parseFilterArgs(arg1, arg2, arg3);\n const queryCache = this.queryCache;\n const refetchFilters = {\n type: 'active',\n ...filters\n };\n return notifyManager.batch(() => {\n queryCache.findAll(filters).forEach(query => {\n query.reset();\n });\n return this.refetchQueries(refetchFilters, options);\n });\n }\n\n cancelQueries(arg1, arg2, arg3) {\n const [filters, cancelOptions = {}] = parseFilterArgs(arg1, arg2, arg3);\n\n if (typeof cancelOptions.revert === 'undefined') {\n cancelOptions.revert = true;\n }\n\n const promises = notifyManager.batch(() => this.queryCache.findAll(filters).map(query => query.cancel(cancelOptions)));\n return Promise.all(promises).then(noop).catch(noop);\n }\n\n invalidateQueries(arg1, arg2, arg3) {\n const [filters, options] = parseFilterArgs(arg1, arg2, arg3);\n return notifyManager.batch(() => {\n var _ref, _filters$refetchType;\n\n this.queryCache.findAll(filters).forEach(query => {\n query.invalidate();\n });\n\n if (filters.refetchType === 'none') {\n return Promise.resolve();\n }\n\n const refetchFilters = { ...filters,\n type: (_ref = (_filters$refetchType = filters.refetchType) != null ? _filters$refetchType : filters.type) != null ? _ref : 'active'\n };\n return this.refetchQueries(refetchFilters, options);\n });\n }\n\n refetchQueries(arg1, arg2, arg3) {\n const [filters, options] = parseFilterArgs(arg1, arg2, arg3);\n const promises = notifyManager.batch(() => this.queryCache.findAll(filters).filter(query => !query.isDisabled()).map(query => {\n var _options$cancelRefetc;\n\n return query.fetch(undefined, { ...options,\n cancelRefetch: (_options$cancelRefetc = options == null ? void 0 : options.cancelRefetch) != null ? _options$cancelRefetc : true,\n meta: {\n refetchPage: filters.refetchPage\n }\n });\n }));\n let promise = Promise.all(promises).then(noop);\n\n if (!(options != null && options.throwOnError)) {\n promise = promise.catch(noop);\n }\n\n return promise;\n }\n\n fetchQuery(arg1, arg2, arg3) {\n const parsedOptions = parseQueryArgs(arg1, arg2, arg3);\n const defaultedOptions = this.defaultQueryOptions(parsedOptions); // https://github.com/tannerlinsley/react-query/issues/652\n\n if (typeof defaultedOptions.retry === 'undefined') {\n defaultedOptions.retry = false;\n }\n\n const query = this.queryCache.build(this, defaultedOptions);\n return query.isStaleByTime(defaultedOptions.staleTime) ? query.fetch(defaultedOptions) : Promise.resolve(query.state.data);\n }\n\n prefetchQuery(arg1, arg2, arg3) {\n return this.fetchQuery(arg1, arg2, arg3).then(noop).catch(noop);\n }\n\n fetchInfiniteQuery(arg1, arg2, arg3) {\n const parsedOptions = parseQueryArgs(arg1, arg2, arg3);\n parsedOptions.behavior = infiniteQueryBehavior();\n return this.fetchQuery(parsedOptions);\n }\n\n prefetchInfiniteQuery(arg1, arg2, arg3) {\n return this.fetchInfiniteQuery(arg1, arg2, arg3).then(noop).catch(noop);\n }\n\n resumePausedMutations() {\n return this.mutationCache.resumePausedMutations();\n }\n\n getQueryCache() {\n return this.queryCache;\n }\n\n getMutationCache() {\n return this.mutationCache;\n }\n\n getLogger() {\n return this.logger;\n }\n\n getDefaultOptions() {\n return this.defaultOptions;\n }\n\n setDefaultOptions(options) {\n this.defaultOptions = options;\n }\n\n setQueryDefaults(queryKey, options) {\n const result = this.queryDefaults.find(x => hashQueryKey(queryKey) === hashQueryKey(x.queryKey));\n\n if (result) {\n result.defaultOptions = options;\n } else {\n this.queryDefaults.push({\n queryKey,\n defaultOptions: options\n });\n }\n }\n\n getQueryDefaults(queryKey) {\n if (!queryKey) {\n return undefined;\n } // Get the first matching defaults\n\n\n const firstMatchingDefaults = this.queryDefaults.find(x => partialMatchKey(queryKey, x.queryKey)); // Additional checks and error in dev mode\n\n if (process.env.NODE_ENV !== 'production') {\n // Retrieve all matching defaults for the given key\n const matchingDefaults = this.queryDefaults.filter(x => partialMatchKey(queryKey, x.queryKey)); // It is ok not having defaults, but it is error prone to have more than 1 default for a given key\n\n if (matchingDefaults.length > 1) {\n this.logger.error(\"[QueryClient] Several query defaults match with key '\" + JSON.stringify(queryKey) + \"'. The first matching query defaults are used. Please check how query defaults are registered. Order does matter here. cf. https://react-query.tanstack.com/reference/QueryClient#queryclientsetquerydefaults.\");\n }\n }\n\n return firstMatchingDefaults == null ? void 0 : firstMatchingDefaults.defaultOptions;\n }\n\n setMutationDefaults(mutationKey, options) {\n const result = this.mutationDefaults.find(x => hashQueryKey(mutationKey) === hashQueryKey(x.mutationKey));\n\n if (result) {\n result.defaultOptions = options;\n } else {\n this.mutationDefaults.push({\n mutationKey,\n defaultOptions: options\n });\n }\n }\n\n getMutationDefaults(mutationKey) {\n if (!mutationKey) {\n return undefined;\n } // Get the first matching defaults\n\n\n const firstMatchingDefaults = this.mutationDefaults.find(x => partialMatchKey(mutationKey, x.mutationKey)); // Additional checks and error in dev mode\n\n if (process.env.NODE_ENV !== 'production') {\n // Retrieve all matching defaults for the given key\n const matchingDefaults = this.mutationDefaults.filter(x => partialMatchKey(mutationKey, x.mutationKey)); // It is ok not having defaults, but it is error prone to have more than 1 default for a given key\n\n if (matchingDefaults.length > 1) {\n this.logger.error(\"[QueryClient] Several mutation defaults match with key '\" + JSON.stringify(mutationKey) + \"'. The first matching mutation defaults are used. Please check how mutation defaults are registered. Order does matter here. cf. https://react-query.tanstack.com/reference/QueryClient#queryclientsetmutationdefaults.\");\n }\n }\n\n return firstMatchingDefaults == null ? void 0 : firstMatchingDefaults.defaultOptions;\n }\n\n defaultQueryOptions(options) {\n if (options != null && options._defaulted) {\n return options;\n }\n\n const defaultedOptions = { ...this.defaultOptions.queries,\n ...this.getQueryDefaults(options == null ? void 0 : options.queryKey),\n ...options,\n _defaulted: true\n };\n\n if (!defaultedOptions.queryHash && defaultedOptions.queryKey) {\n defaultedOptions.queryHash = hashQueryKeyByOptions(defaultedOptions.queryKey, defaultedOptions);\n } // dependent default values\n\n\n if (typeof defaultedOptions.refetchOnReconnect === 'undefined') {\n defaultedOptions.refetchOnReconnect = defaultedOptions.networkMode !== 'always';\n }\n\n if (typeof defaultedOptions.useErrorBoundary === 'undefined') {\n defaultedOptions.useErrorBoundary = !!defaultedOptions.suspense;\n }\n\n return defaultedOptions;\n }\n\n defaultMutationOptions(options) {\n if (options != null && options._defaulted) {\n return options;\n }\n\n return { ...this.defaultOptions.mutations,\n ...this.getMutationDefaults(options == null ? void 0 : options.mutationKey),\n ...options,\n _defaulted: true\n };\n }\n\n clear() {\n this.queryCache.clear();\n this.mutationCache.clear();\n }\n\n}\n\nexport { QueryClient };\n//# sourceMappingURL=queryClient.esm.js.map\n","/**\n * @class\n */\nimport Base from '@netx/core/lib/netx-model';\n\nclass Sorter extends Base {\n\t/**\n\t * @property {object} defaults - Model defaults\n\t * @property {string} defaults.field - Sort field\n\t * @property {string} defaults.sortOrder - Sort order (asc, desc)\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tfield: '',\n\t\t\torder: 'desc',\n\t\t};\n\t}\n\n\t/** @override */\n\tconstructor(attrs, opts = {}) {\n\t\tsuper(attrs, opts);\n\n\t\t/**\n\t\t * If not provided, the keys of the collection's models will be used\n\t\t * @memberof module:app/models/sorter\n\t\t * @alias sortableFields\n\t\t * @type {array}\n\t\t */\n\t\tthis.sortableFields =\n\t\t\topts.sortableFields || _.keys(this.collection.model.GetDefaults());\n\n\t\t/**\n\t\t * @memberof module:app/models/sorter\n\t\t * @alias sortableOrders\n\t\t * @type {array}\n\t\t */\n\t\tthis.sortableOrders = opts.sortableOrders || ['asc', 'desc'];\n\n\t\t// Hey, listen!\n\t\tthis.listenTo(\n\t\t\tthis,\n\t\t\t'change',\n\t\t\t_.debounce((sorter, opts) => {\n\t\t\t\tthis.collection[this.collection.preferredFetchMethod || 'fetch'](\n\t\t\t\t\t_.extend({duplicateQueryPolicy: 'abort'}, opts),\n\t\t\t\t);\n\t\t\t}, 15),\n\t\t);\n\t}\n\n\t/**\n\t * @method\n\t * @return {object}\n\t */\n\tgetSortDTO() {\n\t\treturn this.self();\n\t}\n\n\t/**\n\t * @method\n\t * @param {string} field Field\n\t * @param {string} order Order\n\t */\n\tsetSort(field, order) {\n\t\torder = order || 'desc';\n\t\t// Normalize\n\t\tif (order === 'descending') order = 'desc';\n\t\tif (order === 'ascending') order = 'asc';\n\n\t\tif (!_.contains(this.sortableFields, field)) {\n\t\t\tthrow new Error('Invalid sort `field` \"' + field + '\"');\n\t\t}\n\t\tif (!_.contains(this.sortableOrders, order)) {\n\t\t\tthrow new Error('Invalid sort `order` \"' + order + '\"');\n\t\t}\n\n\t\treturn this.set({\n\t\t\tfield: field,\n\t\t\torder: order,\n\t\t});\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Sorter';\n\t}\n}\n\nexport default Sorter;\n","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTableCellUtilityClass(slot) {\n return generateUtilityClass('MuiTableCell', slot);\n}\nconst tableCellClasses = generateUtilityClasses('MuiTableCell', ['root', 'head', 'body', 'footer', 'sizeSmall', 'sizeMedium', 'paddingCheckbox', 'paddingNone', 'alignLeft', 'alignCenter', 'alignRight', 'alignJustify', 'stickyHeader']);\nexport default tableCellClasses;","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"align\", \"className\", \"component\", \"padding\", \"scope\", \"size\", \"sortDirection\", \"variant\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport { darken, alpha, lighten } from '@mui/system';\nimport capitalize from '../utils/capitalize';\nimport TableContext from '../Table/TableContext';\nimport Tablelvl2Context from '../Table/Tablelvl2Context';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport tableCellClasses, { getTableCellUtilityClass } from './tableCellClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n variant,\n align,\n padding,\n size,\n stickyHeader\n } = ownerState;\n const slots = {\n root: ['root', variant, stickyHeader && 'stickyHeader', align !== 'inherit' && `align${capitalize(align)}`, padding !== 'normal' && `padding${capitalize(padding)}`, `size${capitalize(size)}`]\n };\n return composeClasses(slots, getTableCellUtilityClass, classes);\n};\n\nconst TableCellRoot = styled('td', {\n name: 'MuiTableCell',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, styles[ownerState.variant], styles[`size${capitalize(ownerState.size)}`], ownerState.padding !== 'normal' && styles[`padding${capitalize(ownerState.padding)}`], ownerState.align !== 'inherit' && styles[`align${capitalize(ownerState.align)}`], ownerState.stickyHeader && styles.stickyHeader];\n }\n})(({\n theme,\n ownerState\n}) => _extends({}, theme.typography.body2, {\n display: 'table-cell',\n verticalAlign: 'inherit',\n // Workaround for a rendering bug with spanned columns in Chrome 62.0.\n // Removes the alpha (sets it to 1), and lightens or darkens the theme color.\n borderBottom: theme.vars ? `1px solid ${theme.vars.palette.TableCell.border}` : `1px solid\n ${theme.palette.mode === 'light' ? lighten(alpha(theme.palette.divider, 1), 0.88) : darken(alpha(theme.palette.divider, 1), 0.68)}`,\n textAlign: 'left',\n padding: 16\n}, ownerState.variant === 'head' && {\n color: (theme.vars || theme).palette.text.primary,\n lineHeight: theme.typography.pxToRem(24),\n fontWeight: theme.typography.fontWeightMedium\n}, ownerState.variant === 'body' && {\n color: (theme.vars || theme).palette.text.primary\n}, ownerState.variant === 'footer' && {\n color: (theme.vars || theme).palette.text.secondary,\n lineHeight: theme.typography.pxToRem(21),\n fontSize: theme.typography.pxToRem(12)\n}, ownerState.size === 'small' && {\n padding: '6px 16px',\n [`&.${tableCellClasses.paddingCheckbox}`]: {\n width: 24,\n // prevent the checkbox column from growing\n padding: '0 12px 0 16px',\n '& > *': {\n padding: 0\n }\n }\n}, ownerState.padding === 'checkbox' && {\n width: 48,\n // prevent the checkbox column from growing\n padding: '0 0 0 4px'\n}, ownerState.padding === 'none' && {\n padding: 0\n}, ownerState.align === 'left' && {\n textAlign: 'left'\n}, ownerState.align === 'center' && {\n textAlign: 'center'\n}, ownerState.align === 'right' && {\n textAlign: 'right',\n flexDirection: 'row-reverse'\n}, ownerState.align === 'justify' && {\n textAlign: 'justify'\n}, ownerState.stickyHeader && {\n position: 'sticky',\n top: 0,\n zIndex: 2,\n backgroundColor: (theme.vars || theme).palette.background.default\n}));\n/**\n * The component renders a `` element when the parent context is a header\n * or otherwise a ` | ` element.\n */\n\nconst TableCell = /*#__PURE__*/React.forwardRef(function TableCell(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTableCell'\n });\n\n const {\n align = 'inherit',\n className,\n component: componentProp,\n padding: paddingProp,\n scope: scopeProp,\n size: sizeProp,\n sortDirection,\n variant: variantProp\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const table = React.useContext(TableContext);\n const tablelvl2 = React.useContext(Tablelvl2Context);\n const isHeadCell = tablelvl2 && tablelvl2.variant === 'head';\n let component;\n\n if (componentProp) {\n component = componentProp;\n } else {\n component = isHeadCell ? 'th' : 'td';\n }\n\n let scope = scopeProp;\n\n if (!scope && isHeadCell) {\n scope = 'col';\n }\n\n const variant = variantProp || tablelvl2 && tablelvl2.variant;\n\n const ownerState = _extends({}, props, {\n align,\n component,\n padding: paddingProp || (table && table.padding ? table.padding : 'normal'),\n size: sizeProp || (table && table.size ? table.size : 'medium'),\n sortDirection,\n stickyHeader: variant === 'head' && table && table.stickyHeader,\n variant\n });\n\n const classes = useUtilityClasses(ownerState);\n let ariaSort = null;\n\n if (sortDirection) {\n ariaSort = sortDirection === 'asc' ? 'ascending' : 'descending';\n }\n\n return /*#__PURE__*/_jsx(TableCellRoot, _extends({\n as: component,\n ref: ref,\n className: clsx(classes.root, className),\n \"aria-sort\": ariaSort,\n scope: scope,\n ownerState: ownerState\n }, other));\n});\nprocess.env.NODE_ENV !== \"production\" ? TableCell.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * Set the text-align on the table cell content.\n *\n * Monetary or generally number fields **should be right aligned** as that allows\n * you to add them up quickly in your head without having to worry about decimals.\n * @default 'inherit'\n */\n align: PropTypes.oneOf(['center', 'inherit', 'justify', 'left', 'right']),\n\n /**\n * The content of the component.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * Sets the padding applied to the cell.\n * The prop defaults to the value (`'default'`) inherited from the parent Table component.\n */\n padding: PropTypes.oneOf(['checkbox', 'none', 'normal']),\n\n /**\n * Set scope attribute.\n */\n scope: PropTypes.string,\n\n /**\n * Specify the size of the cell.\n * The prop defaults to the value (`'medium'`) inherited from the parent Table component.\n */\n size: PropTypes\n /* @typescript-to-proptypes-ignore */\n .oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),\n\n /**\n * Set aria-sort direction.\n */\n sortDirection: PropTypes.oneOf(['asc', 'desc', false]),\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),\n\n /**\n * Specify the cell type.\n * The prop defaults to the value inherited from the parent TableHead, TableBody, or TableFooter components.\n */\n variant: PropTypes\n /* @typescript-to-proptypes-ignore */\n .oneOfType([PropTypes.oneOf(['body', 'footer', 'head']), PropTypes.string])\n} : void 0;\nexport default TableCell;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTableHeadUtilityClass(slot) {\n return generateUtilityClass('MuiTableHead', slot);\n}\nconst tableHeadClasses = generateUtilityClasses('MuiTableHead', ['root']);\nexport default tableHeadClasses;","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"className\", \"component\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport Tablelvl2Context from '../Table/Tablelvl2Context';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport { getTableHeadUtilityClass } from './tableHeadClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes\n } = ownerState;\n const slots = {\n root: ['root']\n };\n return composeClasses(slots, getTableHeadUtilityClass, classes);\n};\n\nconst TableHeadRoot = styled('thead', {\n name: 'MuiTableHead',\n slot: 'Root',\n overridesResolver: (props, styles) => styles.root\n})({\n display: 'table-header-group'\n});\nconst tablelvl2 = {\n variant: 'head'\n};\nconst defaultComponent = 'thead';\nconst TableHead = /*#__PURE__*/React.forwardRef(function TableHead(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTableHead'\n });\n\n const {\n className,\n component = defaultComponent\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const ownerState = _extends({}, props, {\n component\n });\n\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(Tablelvl2Context.Provider, {\n value: tablelvl2,\n children: /*#__PURE__*/_jsx(TableHeadRoot, _extends({\n as: component,\n className: clsx(classes.root, className),\n ref: ref,\n role: component === defaultComponent ? null : 'rowgroup',\n ownerState: ownerState\n }, other))\n });\n});\nprocess.env.NODE_ENV !== \"production\" ? TableHead.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * The content of the component, normally `TableRow`.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default TableHead;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTableRowUtilityClass(slot) {\n return generateUtilityClass('MuiTableRow', slot);\n}\nconst tableRowClasses = generateUtilityClasses('MuiTableRow', ['root', 'selected', 'hover', 'head', 'footer']);\nexport default tableRowClasses;","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"className\", \"component\", \"hover\", \"selected\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport { alpha } from '@mui/system';\nimport Tablelvl2Context from '../Table/Tablelvl2Context';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport tableRowClasses, { getTableRowUtilityClass } from './tableRowClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n selected,\n hover,\n head,\n footer\n } = ownerState;\n const slots = {\n root: ['root', selected && 'selected', hover && 'hover', head && 'head', footer && 'footer']\n };\n return composeClasses(slots, getTableRowUtilityClass, classes);\n};\n\nconst TableRowRoot = styled('tr', {\n name: 'MuiTableRow',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.head && styles.head, ownerState.footer && styles.footer];\n }\n})(({\n theme\n}) => ({\n color: 'inherit',\n display: 'table-row',\n verticalAlign: 'middle',\n // We disable the focus ring for mouse, touch and keyboard users.\n outline: 0,\n [`&.${tableRowClasses.hover}:hover`]: {\n backgroundColor: (theme.vars || theme).palette.action.hover\n },\n [`&.${tableRowClasses.selected}`]: {\n backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),\n '&:hover': {\n backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.hoverOpacity}))` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity)\n }\n }\n}));\nconst defaultComponent = 'tr';\n/**\n * Will automatically set dynamic row height\n * based on the material table element parent (head, body, etc).\n */\n\nconst TableRow = /*#__PURE__*/React.forwardRef(function TableRow(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTableRow'\n });\n\n const {\n className,\n component = defaultComponent,\n hover = false,\n selected = false\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const tablelvl2 = React.useContext(Tablelvl2Context);\n\n const ownerState = _extends({}, props, {\n component,\n hover,\n selected,\n head: tablelvl2 && tablelvl2.variant === 'head',\n footer: tablelvl2 && tablelvl2.variant === 'footer'\n });\n\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(TableRowRoot, _extends({\n as: component,\n ref: ref,\n className: clsx(classes.root, className),\n role: component === defaultComponent ? null : 'row',\n ownerState: ownerState\n }, other));\n});\nprocess.env.NODE_ENV !== \"production\" ? TableRow.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * Should be valid | children such as `TableCell`.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * If `true`, the table row will shade on hover.\n * @default false\n */\n hover: PropTypes.bool,\n\n /**\n * If `true`, the table row will have the selected shading.\n * @default false\n */\n selected: PropTypes.bool,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default TableRow;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTableBodyUtilityClass(slot) {\n return generateUtilityClass('MuiTableBody', slot);\n}\nconst tableBodyClasses = generateUtilityClasses('MuiTableBody', ['root']);\nexport default tableBodyClasses;","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"className\", \"component\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport Tablelvl2Context from '../Table/Tablelvl2Context';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport { getTableBodyUtilityClass } from './tableBodyClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes\n } = ownerState;\n const slots = {\n root: ['root']\n };\n return composeClasses(slots, getTableBodyUtilityClass, classes);\n};\n\nconst TableBodyRoot = styled('tbody', {\n name: 'MuiTableBody',\n slot: 'Root',\n overridesResolver: (props, styles) => styles.root\n})({\n display: 'table-row-group'\n});\nconst tablelvl2 = {\n variant: 'body'\n};\nconst defaultComponent = 'tbody';\nconst TableBody = /*#__PURE__*/React.forwardRef(function TableBody(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTableBody'\n });\n\n const {\n className,\n component = defaultComponent\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const ownerState = _extends({}, props, {\n component\n });\n\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(Tablelvl2Context.Provider, {\n value: tablelvl2,\n children: /*#__PURE__*/_jsx(TableBodyRoot, _extends({\n className: clsx(classes.root, className),\n as: component,\n ref: ref,\n role: component === defaultComponent ? null : 'rowgroup',\n ownerState: ownerState\n }, other))\n });\n});\nprocess.env.NODE_ENV !== \"production\" ? TableBody.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * The content of the component, normally `TableRow`.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default TableBody;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTableUtilityClass(slot) {\n return generateUtilityClass('MuiTable', slot);\n}\nconst tableClasses = generateUtilityClasses('MuiTable', ['root', 'stickyHeader']);\nexport default tableClasses;","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"className\", \"component\", \"padding\", \"size\", \"stickyHeader\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport TableContext from './TableContext';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport { getTableUtilityClass } from './tableClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n stickyHeader\n } = ownerState;\n const slots = {\n root: ['root', stickyHeader && 'stickyHeader']\n };\n return composeClasses(slots, getTableUtilityClass, classes);\n};\n\nconst TableRoot = styled('table', {\n name: 'MuiTable',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.stickyHeader && styles.stickyHeader];\n }\n})(({\n theme,\n ownerState\n}) => _extends({\n display: 'table',\n width: '100%',\n borderCollapse: 'collapse',\n borderSpacing: 0,\n '& caption': _extends({}, theme.typography.body2, {\n padding: theme.spacing(2),\n color: (theme.vars || theme).palette.text.secondary,\n textAlign: 'left',\n captionSide: 'bottom'\n })\n}, ownerState.stickyHeader && {\n borderCollapse: 'separate'\n}));\nconst defaultComponent = 'table';\nconst Table = /*#__PURE__*/React.forwardRef(function Table(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTable'\n });\n\n const {\n className,\n component = defaultComponent,\n padding = 'normal',\n size = 'medium',\n stickyHeader = false\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const ownerState = _extends({}, props, {\n component,\n padding,\n size,\n stickyHeader\n });\n\n const classes = useUtilityClasses(ownerState);\n const table = React.useMemo(() => ({\n padding,\n size,\n stickyHeader\n }), [padding, size, stickyHeader]);\n return /*#__PURE__*/_jsx(TableContext.Provider, {\n value: table,\n children: /*#__PURE__*/_jsx(TableRoot, _extends({\n as: component,\n role: component === defaultComponent ? null : 'table',\n ref: ref,\n className: clsx(classes.root, className),\n ownerState: ownerState\n }, other))\n });\n});\nprocess.env.NODE_ENV !== \"production\" ? Table.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * The content of the table, normally `TableHead` and `TableBody`.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * Allows TableCells to inherit padding of the Table.\n * @default 'normal'\n */\n padding: PropTypes.oneOf(['checkbox', 'none', 'normal']),\n\n /**\n * Allows TableCells to inherit size of the Table.\n * @default 'medium'\n */\n size: PropTypes\n /* @typescript-to-proptypes-ignore */\n .oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),\n\n /**\n * Set the header sticky.\n *\n * ⚠️ It doesn't work with IE11.\n * @default false\n */\n stickyHeader: PropTypes.bool,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default Table;","/**\n * Displays a single asset clip constituent\n * @class\n */\nimport Base from './assetConstituentView';\nimport Template from '../templates/assetConstituentView_clip.html';\n\nexport default class AssetConstituentView_Clip extends Base {\n\t/** @override */\n\tconstructor(opts = {}) {\n\t\topts.template = opts.template || Template;\n\t\tsuper(opts);\n\n\t\t/**\n\t\t * @memberOf Netx.Views.AssetConstituentView_clip\n\t\t * @property {object} Plugins - Plugins for this view\n\t\t * @property {object} Plugins.tooltip - Tooltip\n\t\t */\n\t\tthis.Plugins.Register({\n\t\t\ttooltip: {\n\t\t\t\tname: 'tooltip',\n\t\t\t\tdataAlias: 'bs.tooltip',\n\t\t\t\tmultiple: false,\n\t\t\t\toptions: {\n\t\t\t\t\tcontainer: 'body',\n\t\t\t\t\ttemplate:\n\t\t\t\t\t\t'',\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\t/** @override */\n\tbindModelEvents() {\n\t\tsuper.bindModelEvents();\n\n\t\tthis.stopListening(this.model, 'change');\n\t\treturn (\n\t\t\tthis.listenTo(\n\t\t\t\tthis.model,\n\t\t\t\t'change:startTime change:endTime change:title change:keyframeReady change:display',\n\t\t\t\tthis.debouncedRender,\n\t\t\t)\n\t\t\t\t// Keyframe progress\n\t\t\t\t.listenTo(this.model.progress, 'change', progress => {\n\t\t\t\t\tprogress.get('active')\n\t\t\t\t\t\t? this.showProgress(progress)\n\t\t\t\t\t\t: this.hideProgress();\n\t\t\t\t})\n\t\t);\n\t}\n\n\t/** @override */\n\tpreRender() {\n\t\t// Cleanup\n\t\tthis.Plugins.Destroy('tooltip');\n\n\t\tsuper.preRender();\n\n\t\tconst model = this.model;\n\t\tconst cacheBuster = model.cacheBuster();\n\t\t// Set on template vars\n\t\t_.extend(this.templateVars, {\n\t\t\tduration: model.getDuration(),\n\t\t\tpreviewModUrl: model.get('previewUrl') + cacheBuster,\n\t\t\tprettyRange: model.getPrettyRange(),\n\t\t\tthumbModUrl: model.get('thumbUrl') + cacheBuster,\n\t\t\tpercent: this.model.progress.get('percent'),\n\t\t\tprogressMessage: this.model.progress.get('message'),\n\t\t});\n\t}\n\n\t/** @override */\n\tpostRender() {\n\t\tsuper.postRender();\n\n\t\t// Cache\n\t\tthis.$progress = this.$('.progress');\n\t\tthis.$progressBar = this.$progress.find('.progress-bar');\n\t\tthis.$progressBarSr = this.$progressBar.find('.sr-only');\n\t\tthis.$progressMessage = this.$progress.find('.nx-progress-message');\n\t\tthis.$tooltip = this.$('[data-toggle=\"tooltip\"]');\n\n\t\t// Initilaize tooltip\n\t\tthis.Plugins.Initialize('tooltip', this.$tooltip);\n\n\t\t// Active progress\n\t\tif (this.model.progress.get('active')) {\n\t\t\tthis.showProgress(this.model.progress);\n\t\t}\n\t}\n\n\t/**\n\t * @method\n\t */\n\thideProgress() {\n\t\tthis.$el.removeClass('has-progress');\n\n\t\tthis.$progress && this.$progress.hide();\n\t\tthis.$progressBar &&\n\t\t\tthis.$progressBar.css('width', '0%').attr('aria-valuenow', 0);\n\t\tthis.$progressBarSr &&\n\t\t\tthis.$progressBarSr.html(i18n.t('i18n.percentLoaded', {percent: 0}));\n\t}\n\n\t/**\n\t * Show clip keyframe progress\n\t * @method\n\t * @param {module:asset/models/assetConstituent_clip} model Clip model\n\t * @param {number} progress Keyframe progress\n\t */\n\tkeyframeProgress(model, progress) {\n\t\tthis.$progress && this.$progress.css('width', progress + '%');\n\t}\n\n\t/**\n\t * @method\n\t * @param {Netx.Models.Progress} progress Progress model\n\t */\n\tshowProgress(progress) {\n\t\tthis.$progressMessage &&\n\t\t\tthis.$progressMessage.html(progress.get('message'));\n\t\tconst percent = progress.get('percent');\n\n\t\tif (_.isNumber(percent)) {\n\t\t\tthis.$el.addClass('has-progress');\n\t\t\tthis.$progress && this.$progress.show();\n\n\t\t\tthis.$progressBar &&\n\t\t\t\tthis.$progressBar\n\t\t\t\t\t.css('width', percent + '%')\n\t\t\t\t\t.attr('aria-valuenow', percent);\n\t\t\tthis.$progressBarSr &&\n\t\t\t\tthis.$progressBarSr.html(\n\t\t\t\t\ti18n.t('i18n.percentLoaded', {percent: percent}),\n\t\t\t\t);\n\t\t}\n\t}\n\n\t/** @override */\n\tunbindModelEvents() {\n\t\tsuper.unbindModelEvents();\n\n\t\treturn this.stopListening(this.model.progress);\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'AssetConstituentView_Clip';\n\t}\n}\n","import Base from '@netx/core-asset/views/assetConstituentView_clip';\n\nimport {\n\tfaArrowDown,\n\tfaPencilAlt,\n\tfaTrashAlt,\n} from '@fortawesome/pro-solid-svg-icons';\nconst icons = Base.initializeIcons({\n\tfaArrowDown,\n\tfaPencilAlt,\n\tfaTrashAlt,\n});\n\nexport default class AssetConstituentView_Clip extends Base {\n\t/** @override */\n\tconstructor(opts = {}) {\n\t\topts.icons = {...icons, ...opts.icons};\n\t\tsuper(opts);\n\t}\n}\n","import {\n\tATTRIBUTE_SYSTEM_ID,\n\tATTRIBUTE_SYSTEM,\n} from '@netx/core-attribute/constants';\n\nexport const UPGRADED_FEATURES = ['attributes'];\n\nexport const GOO_SETTING_KEYS = [\n\t'contactMessage',\n\t'detailAttributes',\n\t'googleAnalyticsEnabled',\n\t'googleAnalyticsId',\n\t'homeRoute',\n\t'logoutUrl',\n\t'requireLogin',\n\t'searchCategory',\n\t'searchCategoryName',\n\t'searchCategoryPath',\n\t'sortAttributes',\n\t'ssoLabel',\n\t'ssoLoginEnabled',\n\t'ssoUrl',\n\t'upgradedFeatures',\n];\nexport const SETTING_KEYS = [\n\t'attributeIds',\n\t'category',\n\t'categoryName',\n\t'categoryPath',\n\t'displayCatDescriptions',\n\t'label',\n\t'path',\n\t'searchPlaceholder',\n\t'userLevel',\n];\n\nexport const ATTRIBUTE_CONTEXT = {\n\tDETAIL: 'detailAttributes',\n\tSORT: 'sortAttributes',\n};\n\nexport const DEFAULT_ATTRIBUTE_IDS = [\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.NAME],\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE_SIZE_2],\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE_TYPE_LABEL],\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.DIMENSIONS],\n];\n\nexport const ENFORCE_ATTRIBUTE_IDS = [\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE],\n\tATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.NAME],\n];\n","import React, {useMemo} from 'react';\nimport clsx from 'clsx';\n\nimport {i18n} from '@netx/core/i18n';\n\nimport {FormLabel, Skeleton} from '@mui/material';\nimport {createStyles, withStyles, WithStyles} from '@mui/styles';\nimport type {Theme} from '@netx/core-components/Theme';\n\nimport type {TextFieldProps} from './TextField';\nimport {isEmptyValue} from '@netx/core-components/Form';\n\nconst styles = ({mixins, palette, spacing}: Theme) =>\n\tcreateStyles({\n\t\troot: {\n\t\t\tmargin: spacing(0.75, 0),\n\t\t\tpadding: spacing(0, 1.75),\n\t\t\twidth: '100%',\n\t\t\t'&.disabled': {\n\t\t\t\t...mixins.disabled,\n\t\t\t},\n\t\t\t'&.pseudoValue': {\n\t\t\t\t'& $value': {\n\t\t\t\t\tcolor: palette.text.secondary,\n\t\t\t\t},\n\t\t\t},\n\t\t\t'&$limitHeightToContainer': {\n\t\t\t\tmaxHeight: '100%',\n\t\t\t\tdisplay: 'flex',\n\t\t\t\tflexDirection: 'column',\n\t\t\t\t'& $label': {\n\t\t\t\t\tflex: '0 0 auto',\n\t\t\t\t},\n\t\t\t\t'& $value': {\n\t\t\t\t\t...mixins.scrollable,\n\t\t\t\t},\n\t\t\t},\n\t\t\t'&$wrapLabel $label': {\n\t\t\t\twhiteSpace: 'initial',\n\t\t\t},\n\t\t},\n\t\tlabel: {\n\t\t\t...mixins.readOnlyLabel,\n\t\t},\n\t\tlimitHeightToContainer: {},\n\t\tvalue: {\n\t\t\t// for \\n etc (no need to parse a string and add
s etc)\n\t\t\twhiteSpace: 'pre-wrap',\n\t\t\twidth: '100%',\n\t\t\twordBreak: 'break-word',\n\t\t},\n\t\tskeleton: {},\n\t\twrapLabel: {},\n\t});\n\nexport interface ReadOnlyTextFieldProps\n\textends Omit {\n\tlimitHeightToContainer?: boolean;\n\twrapLabel?: boolean;\n}\n\nconst ReadOnlyTextField = ({\n\tclasses,\n\tclassName,\n\tdisabled,\n\tlabel = '',\n\tlimitHeightToContainer,\n\tloading,\n\tloadingValue,\n\tmultipleValues,\n\twrapLabel,\n\tvalue,\n}: WithStyles & ReadOnlyTextFieldProps) => {\n\tvalue = value == null ? '' : value;\n\n\tconst pseudoValue = isEmptyValue(value) || multipleValues;\n\n\tconst displayLabel = useMemo(() => {\n\t\tif (label == null || label === '') return null;\n\t\tif (loading) return ;\n\t\treturn (\n\t\t\t\n\t\t\t\t{label}\n\t\t\t\n\t\t);\n\t}, [label]);\n\n\tconst displayValue = useMemo(() => {\n\t\tif (loading || loadingValue)\n\t\t\treturn ;\n\t\tif (multipleValues) return i18n.t('i18n.multipleValues');\n\t\tif (value === '') return '(none)';\n\t\treturn value;\n\t}, [loading, loadingValue, multipleValues, value]);\n\n\treturn (\n\t\t\n\t\t\t{displayLabel}\n\t\t\t
{displayValue}
\n\t\t
\n\t);\n};\n\nexport default withStyles(styles, {\n\tname: 'ReadOnlyTextField',\n})(React.memo(ReadOnlyTextField));\n","/**\n * @class\n */\nimport Base from './attribute';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\nimport {assetExpirationToDateString} from '@netx/core-asset-expiration/utils';\n\nexport default class Attribute_Date extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.date,\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @param {number} truncateAt Truncate at index\n\t * @return {mixed} Formatted value\n\t */\n\tformat(value, truncateAt) {\n\t\t// In all cases (currently), except one, we want `yyyy-mm-dd`\n\t\t// The dam will sometimes send us mm/dd/yyyy and we want to normalize this\n\t\t// except for `expirationDate` - which is a time and a time that we want to\n\t\t// show in a relative format\n\t\tif (this.get('system') && this.get('name') === 'expirationDate') {\n\t\t\tif (value) {\n\t\t\t\tvalue = `${i18n.t('i18n.expires')}: ${assetExpirationToDateString(\n\t\t\t\t\tvalue,\n\t\t\t\t)}`;\n\t\t\t}\n\t\t\treturn value === 0 ? '' : value;\n\t\t}\n\n\t\tvalue = this.parseInValue(value);\n\t\treturn super.format(value);\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @return {mixed} Parsed in value\n\t */\n\tparseInValue(value) {\n\t\tvalue = super.parseInValue(value);\n\n\t\tif (_.isArray(value)) {\n\t\t\tvalue = _.map(value, (v) => {\n\t\t\t\tif (v.includes('/')) {\n\t\t\t\t\tv = _.dateToHTML(v);\n\t\t\t\t}\n\t\t\t\treturn v;\n\t\t\t});\n\t\t} else if (value && (_.isNumber(value) || value.includes('/'))) {\n\t\t\tvalue = _.dateToHTML(value);\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @return {mixed} Parsed out value\n\t */\n\tparseOutValue(value) {\n\t\tvalue = super.parseOutValue(value);\n\n\t\tif (_.isArray(value)) {\n\t\t\tvalue = _.map(value, (d) => {\n\t\t\t\tif (_.isNumber(d)) {\n\t\t\t\t\treturn d;\n\t\t\t\t}\n\t\t\t\treturn d.replace(/(\\d+)-(\\d+)-(\\d+)/, '$2/$3/$1');\n\t\t\t});\n\t\t} else if (value) {\n\t\t\tvalue = _.isNumber(value)\n\t\t\t\t? value\n\t\t\t\t: value.replace(/(\\d+)-(\\d+)-(\\d+)/, '$2/$3/$1');\n\t\t}\n\n\t\t// Ensure leading zero's or server side validation will fail\n\t\tif (_.isString(value) && value.length) {\n\t\t\tvalue = value\n\t\t\t\t.split('/')\n\t\t\t\t.map((v) => {\n\t\t\t\t\treturn v.padStart(2, '0');\n\t\t\t\t})\n\t\t\t\t.join('/');\n\t\t}\n\t\treturn value;\n\t}\n\n\t/** @method */\n\tvalidator(val) {\n\t\tif (val === '' || val == null) return true;\n\n\t\tconst valid =\n\t\t\tval.search(/\\d\\d\\/\\d\\d\\/\\d\\d\\d\\d/) > -1 ||\n\t\t\tval.search(/\\d\\d\\d\\d-\\d\\d-\\d\\d/) > -1;\n\n\t\tif (!valid) return new Error('Invalid date');\n\t\treturn true;\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Date';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Multiselect extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.multiselect,\n\t\t};\n\t}\n\n\t/** @type {boolean} */\n\tget isCSV() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @return {mixed} Parsed in value\n\t */\n\tparseInValue(value) {\n\t\t// DAM-15267 - if there are no commas, one value, the regex in csvToArray()\n\t\t// will return null if the single value contains a single apostrophe\n\t\tif (_.isString(value) && value.indexOf(',') > -1) {\n\t\t\tvalue = _.csvToArray(value);\n\t\t}\n\t\treturn super.parseInValue(value) || [];\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @return {mixed} Parsed out value\n\t */\n\tparseOutValue(value) {\n\t\treturn super.parseOutValue(value) || [];\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Multiselect';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute';\n\nimport {ids as attributeTypeIds, numberTypes} from '../properties/attributes';\n\n// Polyfill\n// Safari did not have this prior to version 10 (currently at v11 but just to be safe)\nif (!window.Intl) {\n\twindow.Intl = {\n\t\tNumberFormat(locale, options) {\n\t\t\tconst digits = '0123456789';\n\t\t\tthis.format = n => {\n\t\t\t\tlet s = n.toString();\n\t\t\t\tif (\n\t\t\t\t\t!options ||\n\t\t\t\t\toptions.useGrouping === undefined ||\n\t\t\t\t\toptions.useGrouping\n\t\t\t\t) {\n\t\t\t\t\tvar dp = s.indexOf('.');\n\t\t\t\t\tif (dp < 0) {\n\t\t\t\t\t\tdp = s.length;\n\t\t\t\t\t}\n\t\t\t\t\twhile ((dp -= 3) > 0 && digits.indexOf(s[dp - 1]) >= 0) {\n\t\t\t\t\t\ts = s.substr(0, dp) + ',' + s.substr(dp);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn s;\n\t\t\t};\n\t\t},\n\t};\n}\n/**\n * @function\n * @param {number} value Value\n * @return {number} Decimals\n */\nfunction getDecimalCount(value) {\n\tvalue = value + '';\n\n\tconst decimalSeparator = whatDecimalSeparator();\n\tconst decimals = value.split('.');\n\n\tif (!decimals[1]) {\n\t\treturn 0;\n\t}\n\n\treturn decimals[1].length;\n}\n/**\n * https://stackoverflow.com/questions/11665884/how-can-i-parse-a-string-with-a-comma-thousand-separator-to-a-number\n * @function\n * @param {mixed} value Value\n * @param {string} locale Locale\n * @return {number}\n */\nfunction parseNumber(value, locale) {\n\tvalue = value.toString();\n\tlocale = locale || navigator.language;\n\tconst example = Intl.NumberFormat(locale).format('1.1');\n\tconst cleanPattern = new RegExp('[^-+0-9' + example.charAt(1) + ']', 'g');\n\tconst cleaned = value.replace(cleanPattern, '');\n\tconst normalized = cleaned.replace(example.charAt(1), '.');\n\n\treturn parseFloat(normalized);\n}\n/**\n * @function\n * @return {string} Decimal separator for locale\n */\nfunction whatDecimalSeparator() {\n\tlet n = 1.1;\n\tn = n.toLocaleString().substring(1, 2);\n\treturn n;\n}\n\nexport default class Attribute_Number extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.number,\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @param {object} opts Options\n\t * @return {mixed} Formatted value\n\t */\n\tformat(value, opts = {}) {\n\t\tvalue = this.parseInValue(value);\n\n\t\t// Do not parse into locale string\n\t\tconst noLocale = opts.noLocale === true;\n\t\tconst numberType = numberTypes[this.get('spec2')] || {};\n\t\tconst maxDecimal = numberType.maxDecimal || 0;\n\n\t\t/**\n\t\t * @function\n\t\t * @param {number} value Value\n\t\t * @return Parsed number\n\t\t */\n\t\tconst parse = value => {\n\t\t\tvalue = parseNumber(value);\n\n\t\t\t// `Unlimited` number type\n\t\t\tif (maxDecimal === Infinity) {\n\t\t\t\treturn noLocale\n\t\t\t\t\t? value.toString()\n\t\t\t\t\t: value.toLocaleString(undefined, {\n\t\t\t\t\t\t\tuseGrouping: false,\n\t\t\t\t\t\t\tmaximumFractionDigits: 20, // Maximum allowed by`toLocaleString`\n\t\t\t\t\t });\n\t\t\t} else {\n\t\t\t\treturn noLocale\n\t\t\t\t\t? value.toFixed(maxDecimal)\n\t\t\t\t\t: value.toLocaleString(undefined, {\n\t\t\t\t\t\t\tuseGrouping: false,\n\t\t\t\t\t\t\tminimumFractionDigits: maxDecimal,\n\t\t\t\t\t\t\tmaximumFractionDigits: maxDecimal,\n\t\t\t\t\t });\n\t\t\t}\n\t\t};\n\n\t\tif (this.get('system')) {\n\t\t\t// Normalize\n\t\t\tswitch (this.get('name')) {\n\t\t\t\tcase 'fileSize':\n\t\t\t\tcase 'fileSize2':\n\t\t\t\t\tvalue = _.bytes(value, true);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (value) {\n\t\t\tvalue = _.isArray(value) ? _.map(value, parse) : parse(value);\n\t\t}\n\n\t\treturn super.format(value);\n\t}\n\n\t/**\n\t * Fix for displaying floats with zeros\n\t * @override\n\t * @param {object|string} key The key or an object of key values\n\t * @param {mixed} value Either the value, or if the key is an object, the options\n\t * @param {object} opts Either the options, or if the key is an object, undefined\n\t */\n\tset(key, value, opts) {\n\t\t// Make life easier\n\t\tlet attrs;\n\t\tif (_.isObject(key)) {\n\t\t\tattrs = key;\n\t\t\topts = value;\n\t\t} else {\n\t\t\tattrs = {\n\t\t\t\t[key]: value,\n\t\t\t};\n\t\t}\n\n\t\tif (attrs.value) {\n\t\t\t// Check if we are enforcing decimals via spec2 (a value of 4 means it is free - whole/decimal whatever)\n\t\t\tconst decimalPlaces = attrs.spec2 || this.get('spec2');\n\t\t\tif (decimalPlaces && decimalPlaces <= 3) {\n\t\t\t\tattrs.value = Number(attrs.value).toFixed(decimalPlaces);\n\t\t\t}\n\t\t}\n\n\t\t// Super\n\t\treturn super.set(attrs, opts);\n\t}\n\n\t/**\n\t * @method\n\t * @param {mixed} value Value\n\t * @return {boolean} Invalid\n\t */\n\tinvalid(value) {\n\t\tlet valid = this.validator(value);\n\n\t\tif (valid === true) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (valid instanceof Error) {\n\t\t\treturn valid.message;\n\t\t}\n\n\t\treturn i18n.t('i18n.invalid');\n\t}\n\n\t/**\n\t * @method\n\t * @param {mixed} value Value\n\t * @return {boolean} Valid\n\t */\n\tvalidator(value) {\n\t\t// Empty values are fine\n\t\t// TODO: check for mandatory\n\t\tif (_.isNull(value) || _.isUndefined(value) || value === '') {\n\t\t\treturn true;\n\t\t}\n\n\t\tvalue = value.toString();\n\n\t\tconst numberType = numberTypes[this.get('spec2')] || false;\n\t\tconst maxDecimal = numberType && numberType.maxDecimal;\n\t\tconst maxLength =\n\t\t\tnumberType.key === 'whole' ? this.get('spec1') : undefined;\n\n\t\tconst decimalIndex = value.indexOf('.');\n\t\tif (decimalIndex > -1 && decimalIndex + 1 === value.length) {\n\t\t\treturn new Error('Invalid number');\n\t\t}\n\n\t\tif (maxLength && value.length > maxLength) {\n\t\t\treturn new Error(`Exceeds max length of ${maxLength}`);\n\t\t}\n\n\t\tif (isNaN(parseNumber(value))) {\n\t\t\treturn new Error('Invalid number format');\n\t\t}\n\n\t\t// Negative numbers are not allowed by the DAM\n\t\tif (numberType.key === 'unlimited' && value < 0) {\n\t\t\treturn new Error('Negative numbers are not allowed');\n\t\t}\n\n\t\tconst decimalCount = getDecimalCount(value);\n\t\tif (decimalCount > maxDecimal) {\n\t\t\treturn new Error(`Exceeds max decimals of ${maxDecimal}`);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Number';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Select extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.select,\n\t\t};\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Select';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute_multiselect';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Tag extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.tag,\n\t\t};\n\t}\n\n\t/**\n\t * isFlexible() returns true if this attribute is defined as having 'folksonomy'\n\t * and will therefore allow users to add terms via the select2 tagging system.\n\t * @override\n\t * @return {boolean} Is flexible\n\t */\n\tisFlexible() {\n\t\treturn this.get('spec2') === 1;\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Tag';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Text extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.text,\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @param {object} opts Options\n\t * @return {mixed} Formatted value\n\t */\n\tformat(value, opts) {\n\t\topts = opts || {};\n\n\t\tconst parsedInValue = this.parseInValue(value);\n\t\tvalue = parsedInValue != null ? parsedInValue : '';\n\n\t\tvar parseURL = opts.parseURL !== false,\n\t\t\ttruncateAt = opts.truncateAt;\n\n\t\tif (_.isArray(value)) {\n\t\t\tvalue = value.join(', ');\n\t\t}\n\n\t\tvalue = value.replace(//g, '>');\n\n\t\t// Truncate value\n\t\tif (truncateAt && truncateAt !== Infinity && value.length > truncateAt) {\n\t\t\tvar truncatedValue = value.substr(0, truncateAt).trim();\n\n\t\t\tif (parseURL) {\n\t\t\t\tvar urls = value.match(/(https?:\\/\\/.*?[^\\s]+)/g);\n\t\t\t\t// We need to check if any urls started prior to truncation that did not complete\n\t\t\t\t// before truncation\n\t\t\t\tif (urls) {\n\t\t\t\t\tvar valLength = truncatedValue.length,\n\t\t\t\t\t\tcutoffUrl,\n\t\t\t\t\t\tc,\n\t\t\t\t\t\ti,\n\t\t\t\t\t\tidx;\n\n\t\t\t\t\tfor (i = 0, c = urls.length; i < c; i++) {\n\t\t\t\t\t\tconst url = urls[i];\n\t\t\t\t\t\tidx = value.lastIndexOf(url);\n\t\t\t\t\t\tif (idx < valLength && idx + url.length > valLength) {\n\t\t\t\t\t\t\tcutoffUrl = url;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttruncatedValue = cutoffUrl\n\t\t\t\t\t\t? _.parseURLS(truncatedValue.substr(0, idx)) +\n\t\t\t\t\t\t '' +\n\t\t\t\t\t\t truncatedValue.substr(idx) +\n\t\t\t\t\t\t ''\n\t\t\t\t\t\t: _.parseURLS(truncatedValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn truncatedValue + '...';\n\t\t}\n\n\t\treturn parseURL ? _.parseURLS(value) || '' : value;\n\t}\n\n\t/**\n\t * Value only appendable if not a multivalue attribute\n\t * @override\n\t * @return {boolean} Value is appendable\n\t */\n\tisAppendable() {\n\t\treturn !this.isTrueMultivalue();\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Text';\n\t}\n}\n","/**\n * Attribute templates collection\n * This collection contains ALL attributes\n * It creates two sub collections of asset and clip attributes and maintains the two\n * No need to add to them individually - just add to this collection and they will get to where they need to be\n * @class\n */\nimport Base from '@netx/core/lib/netx-collection';\n\nimport Netx from '@netx/core/bootstrap';\n\nimport AssetAttributeDatumCollection from './assetAttributeDatum';\n\nimport BaseModel from '../models/attribute';\nimport DateModel from '../models/attribute_date';\nimport MultiselectModel from '../models/attribute_multiselect';\nimport NumberModel from '../models/attribute_number';\nimport SelectModel from '../models/attribute_select';\nimport SemanticModel from '../models/attribute_semantic';\nimport TagModel from '../models/attribute_tag';\nimport TagVocabModel from '../models/attribute_tagVocab';\nimport TextModel from '../models/attribute_text';\nimport TextareaModel from '../models/attribute_textarea';\n\nimport {checksumEnabled} from '@netx/core-asset/enablers';\nimport {ENFORCE_ATTRIBUTE_IDS} from '@netx/core-cms/services/settings/constants';\nimport hasUpdatedAttributesSystem from '@netx/core-cms/services/settings/utils/hasUpdatedAttributesSystem';\nimport {isPortal} from '@netx/core/lib/utils';\nimport {assetExpirationEnabled} from '@netx/core-asset-expiration/enablers';\n\nconst Models = {\n\tbase: BaseModel,\n\tdate: DateModel,\n\tmultiselect: MultiselectModel,\n\tnumber: NumberModel,\n\tselect: SelectModel,\n\tsemantic: SemanticModel,\n\ttag: TagModel,\n\ttagVocab: TagVocabModel,\n\ttext: TextModel,\n\ttextarea: TextareaModel,\n};\n\nimport {isEmptyValue} from '@netx/core/lib/underscore-netx';\nimport {\n\tids as typeIds,\n\ttypes,\n\tvocabularyAttributes,\n} from '../properties/attributes';\n\nconst getPortal = () => isPortal() && Netx.cms?.portal?.id && Netx.cms?.portal;\n\nexport default class Attributes extends Base {\n\t/**\n\t * @type {Netx.Rpc}\n\t * @private\n\t */\n\tget rpc() {\n\t\treturn true;\n\t}\n\t/**\n\t * @type {Netx.URL}\n\t * @private\n\t */\n\tget url() {\n\t\treturn Netx.URL.api;\n\t}\n\n\t/** @type {boolean} */\n\tget xhrTrackProgress() {\n\t\treturn true;\n\t}\n\n\t/** @type {object} */\n\tget xhrLoadingMessages() {\n\t\treturn {\n\t\t\tgetAttributeTemplates: 'Loading attributes',\n\t\t\tgetMetadataMapJson: 'Loading metadata maps',\n\t\t};\n\t}\n\n\t/** @type {object} */\n\tget xhrLoadedMessages() {\n\t\treturn {\n\t\t\tgetAttributeTemplates: 'Loaded attributes',\n\t\t\tgetMetadataMapJson: 'Loaded metadata maps',\n\t\t};\n\t}\n\n\t/**\n\t * Since we are overriding the model proeprty as a method\n\t * we need to point backbone into the right direction with model prototype accessing\n\t * This is the only method in all of the backbone collection code that relys on getting the a property from the model prototype\n\t * @override\n\t * @param {object} attrs Attributes\n\t * @return {mixed} Model id\n\t */\n\tmodelId(attrs) {\n\t\treturn attrs[Models.base.prototype.idAttribute || 'id'];\n\t}\n\n\t/**\n\t * Return an array of the IDs of the models in this collection.\n\t * Se note about `this.modelId` - this is an override of code in module:core/lib/netx-collection\n\t * @override\n\t * @param {boolean} omitSystem Omit system attributes\n\t * @return {array} Array of model ids\n\t */\n\tids(omitSystem) {\n\t\tconst ids = this.pluck(Models.base.prototype.idAttribute || 'id');\n\t\tif (!omitSystem) return ids;\n\n\t\t// Omit system attributes\n\t\treturn ids.filter((id) => id > 0);\n\t}\n\n\t/** @method */\n\tcomparator(attrA, attrB) {\n\t\t// DAM-20153: if there is a portal, sort by attributeIds array\n\t\tconst portal = getPortal();\n\t\tif (portal) {\n\t\t\tconst attributeIds = portal.get('attributeIds');\n\t\t\tconst detailAttributes = portal.get('detailAttributes') || [];\n\t\t\t// maintain order of detailAttributes if portal has not been\n\t\t\t// edited since attributes upgrade\n\t\t\tif (\n\t\t\t\t!hasUpdatedAttributesSystem(portal.attributes) &&\n\t\t\t\tdetailAttributes.length\n\t\t\t) {\n\t\t\t\tconst aIndex = detailAttributes.indexOf(attrA.id);\n\t\t\t\tconst bIndex = detailAttributes.indexOf(attrB.id);\n\t\t\t\tif (aIndex < 0 && bIndex > -1) return 1;\n\t\t\t\tif (aIndex > -1 && bIndex < 0) return -1;\n\t\t\t\tif (aIndex < 0 && bIndex < 0)\n\t\t\t\t\treturn (\n\t\t\t\t\t\tattributeIds.indexOf(attrA.id) - attributeIds.indexOf(attrB.id)\n\t\t\t\t\t);\n\t\t\t\treturn aIndex - bIndex;\n\t\t\t}\n\n\t\t\t// Edited since upgrade, use the explicit order in the portal\n\t\t\tif (hasUpdatedAttributesSystem(portal.attributes)) {\n\t\t\t\treturn attributeIds.indexOf(attrA.id) - attributeIds.indexOf(attrB.id);\n\t\t\t}\n\n\t\t\t// Not edited since upgrade and there are no detailAttributes defined\n\t\t\t// use the explicit order in the portal, except force `file` to the top like we would have in old portals\n\t\t\t// NOTE: if we just fall through to the classic comparator here, we do not line up with the list the user\n\t\t\t// would see when editing their portal. And any edit made (without explictely going in and managing the attrs)\n\t\t\t// would then cause us to hit the `if` just above and now your attributes are in an unpredictable order based\n\t\t\t// on what you would have just seen (in portal proper) prior to an edit.\n\t\t\tif (attrA.id === -101) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (attrB.id === -101) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\treturn attributeIds.indexOf(attrA.id) - attributeIds.indexOf(attrB.id);\n\t\t}\n\n\t\t// DAM-11580\n\t\t// If attrA is `file` it comes before\n\t\tif (attrA.id === -101) {\n\t\t\treturn -1;\n\t\t}\n\t\t// If attrB is `file`, attrA comes after\n\t\tif (attrB.id === -101) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (this.keepAlphabetical) {\n\t\t\tconst aName = attrA.get('name').toLowerCase();\n\t\t\tconst bName = attrB.get('name').toLowerCase();\n\t\t\t// This is then the standard sort you would expect by `name`\n\t\t\tif (aName < bName) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (bName < aName) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t} else {\n\t\t\tconst aOrderby = attrA.get('orderby');\n\t\t\tconst bOrderby = attrB.get('orderby');\n\t\t\t// This is then the standard sort you would expect by `orderby`\n\t\t\tif (aOrderby < bOrderby) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif (bOrderby < aOrderby) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\n\t\t// Equal\n\t\treturn 0;\n\t}\n\n\t/**\n\t * @property {object} methods - Collection RPC methods\n\t * @property {method} methods.read - Fetch attribute templates, metadata and metadata maps\n\t *\n\t * @property {method} methods.getAttributeTemplatesForCategoryContext - Provided an array of category ids, fetch all attribute templates, for those categories, that have editing permissions.\n\t * @property {method} methods.getAttributeTemplates - Fetch attribute templates\n\t * @property {method} methods.getAttributeObjects - Fetch attribute templates by id\n\t * @property {method} methods.getAllAttributeIds - Fetch attribute templates ids\n\t * @property {method} methods.getDataSetList - Fetch datasets (deprecated)\n\t * @property {method} methods.setAttributeTemplateOrder - Set new attribute template order\n\t * @property {method} methods.getMetadataMapJson - Fetch metadata map json\n\t * @property {method} methods._getMetadataMap - Fetch metadata map\n\t * @property {method} methods._setMetadataMap - Update metadata map\n\t */\n\tget methods() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tread(opts) {\n\t\t\t\t// First get the templates\n\t\t\t\treturn (this.categoryIds.length\n\t\t\t\t\t? this.getAttributeTemplatesForCategoryContext\n\t\t\t\t\t: this.getAttributeTemplates)(opts).then((attrs) => {\n\t\t\t\t\tthis.set(attrs);\n\t\t\t\t\t// Get all other pertinent attribute data\n\t\t\t\t\treturn this.when(\n\t\t\t\t\t\tthis.getMetadata(opts),\n\t\t\t\t\t\tthis.getMetadataMap(opts),\n\t\t\t\t\t).then(() => {\n\t\t\t\t\t\t// Resolve\n\t\t\t\t\t\treturn attrs;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t/** @method */\n\t\t\tgetAllAttributeIds: ['getAllAttributeIds'],\n\t\t\t/** @method */\n\t\t\tgetAttributeObjects: ['getAttributeObjects', 'attributeIds'],\n\t\t\t/** @method */\n\t\t\tgetAttributeTemplatesForCategoryContext() {\n\t\t\t\t// See @todo in constructor\n\t\t\t\tlet categoryIds = this.categoryIds;\n\t\t\t\tif (categoryIds.length > 1) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t'multiple ids are not actually supported for `getAttributeTemplatesForCategoryContext`. Ignoring all but the first id.',\n\t\t\t\t\t);\n\t\t\t\t\tcategoryIds = [categoryIds[0]];\n\t\t\t\t}\n\t\t\t\treturn [\n\t\t\t\t\t'getAttributeTemplatesForCategoryContext',\n\t\t\t\t\tcategoryIds,\n\t\t\t\t\tthis.writableOnly,\n\t\t\t\t];\n\t\t\t},\n\t\t\t/** @method */\n\t\t\tgetAttributeTemplates: ['getAttributeTemplates'],\n\t\t\t/**\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t * @deprecated\n\t\t\t * @see parsers.getDataSetList\n\t\t\t */\n\t\t\tgetDataSetList(opts) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t'Do not fetch datasets via the attributes collection. Method will be removed in 9.0 and will result in an error.',\n\t\t\t\t);\n\t\t\t\treturn ['getDataSetList', ''];\n\t\t\t},\n\t\t\t/** @method */\n\t\t\t_getMetadataMap: ['getMetadataMap'],\n\t\t\t/** @method */\n\t\t\tgetMetadataMapJson: ['getMetadataMapJson'],\n\t\t\t/**\n\t\t\t * @method\n\t\t\t * @param {array} ids IDs\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tsetAttributeTemplateOrder(ids, opts) {\n\t\t\t\treturn ['setAttributeTemplateOrder', ids, false];\n\t\t\t},\n\t\t\t/**\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\t_setMetadataMap(opts) {\n\t\t\t\treturn ['setMetadataMap', this.metadataMapArgs];\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * @property {object} parsers - Collection parsers\n\t * @property {function} parsers.getAllAttributeIds - Parse fetch of attribute ids\n\t * @property {function} parsers.getAttributeObjects - Parse fetch of attribute templates\n\t * @property {function} parsers.getAttributeTemplates - Parse fetch of attribute templates\n\t * @property {function} parsers.getAttributeTemplatesForCategoryContext - Parse fetch of attribute templates\n\t * @property {function} parsers.getDataSetList - Parse fetch of datasets (deprecated)\n\t * @property {function} parsers._getMetadataMap - Parse fetch of metadata map\n\t * @property {function} parsers.getMetadataMapJson - Parse fetch of metadata map json\n\t * @property {function} parsers.setAttributeTemplateOrder - Parse update of attribute template order\n\t * @property {function} parsers._setMetadataMap - parse update of metadata map\n\t */\n\tget parsers() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {array} ids Attribute ids\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetAllAttributeIds(ids, opts) {\n\t\t\t\t// NOTE: the attribute object's returned id field is 'attributeid', all lower case,\n\t\t\t\t// while the RPC call is getAllAttributeIds() (uppercase I).\n\t\t\t\t// I'm keeping with the somewhat standard \"Ids\" format used in the rest of the codebase.\n\t\t\t\tthis.attributeIds = ids;\n\t\t\t},\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {array} attributes Attribute templates\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetAttributeObjects(attributes, opts) {\n\t\t\t\tthis.set(this.parseAndCorrect(attributes), opts);\n\t\t\t},\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {array} attributes Attribute templates\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetAttributeTemplates(attributes, opts) {\n\t\t\t\treturn this.parseAndCorrect(attributes);\n\t\t\t},\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {array} attributes Attribute templates\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tgetAttributeTemplatesForCategoryContext(attributes, opts) {\n\t\t\t\treturn this.parseAndCorrect(attributes);\n\t\t\t},\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {array} datasets Datasets\n\t\t\t * @param {object} opts Request options\n\t\t\t * @deprecated\n\t\t\t */\n\t\t\tgetDataSetList(datasets, opts) {\n\t\t\t\t// TODO: No! thise objects are nothin like our models whatsoever\n\t\t\t\t// it does not look like anything is using this\n\t\t\t\t// Deprecating\n\t\t\t\tconsole.warn('How do you like them errors in the console?');\n\t\t\t\tthis.set(datasets, opts);\n\t\t\t},\n\t\t\t/**\n\t\t\t * We have fetched our metadata map - which contains parallel arrays of importIds/importValues and exportIds/exportValues\n\t\t\t * @method\n\t\t\t * @param {object} metadataMap Metadata map data object\n\t\t\t * @param {object} opts Request options\n\t\t\t * @example\n\t\t\t * {\n\t\t\t * \"exportIds\": [],\n\t\t\t * \"exportImagePortalBlockOnProcess\": false,\n\t\t\t * \"exportImagePortalBlockOnSave\": false,\n\t\t\t * \"exportValues\": [],\n\t\t\t * \"importIds\": [\n\t\t\t * 7\n\t\t\t * ],\n\t\t\t * \"importValues\": [\n\t\t\t * \"ID3:Track\"\n\t\t\t * ],\n\t\t\t * \"modUserId\": 0\n\t\t\t * }\n\t\t\t */\n\t\t\t_getMetadataMap(metadataMap, opts) {\n\t\t\t\t// We want a true clone - no reference to one another\n\t\t\t\tthis.metadataMapArgs = JSON.parse(JSON.stringify(metadataMap));\n\t\t\t\t// We want a true clone - no reference to one another\n\t\t\t\tthis.metadataMap = JSON.parse(JSON.stringify(metadataMap));\n\t\t\t},\n\t\t\t/**\n\t\t\t * We have fetched our metadata map json - which is an array of schemas with an array options within\n\t\t\t * The result of this call is used to populate the metadata sync options available to a user who can manage attribute templates\n\t\t\t * @method\n\t\t\t * @param {array} metadata Metadata options array\n\t\t\t * @param {object} opts Request options\n\t\t\t * @example\n\t\t\t * [\n\t\t\t * {\n\t\t\t * \"label\": \"Dublin Core\",\n\t\t\t * \"options\": [\n\t\t\t * {\n\t\t\t * \"direction\": \"both\",\n\t\t\t * \"label\": \"Dublin Core contributor\",\n\t\t\t * \"value\": \"dc:contributor\"\n\t\t\t * },\n\t\t\t * {\n\t\t\t * \"direction\": \"import\",\n\t\t\t * \"label\": \"Dublin Core format\",\n\t\t\t * \"value\": \"dc:format\"\n\t\t\t * },\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t * },\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t */\n\t\t\tgetMetadataMapJson(metadata, opts) {\n\t\t\t\tthis.metadata = metadata;\n\t\t\t},\n\t\t\t/**\n\t\t\t * @function\n\t\t\t * @param {null} response Null\n\t\t\t * @param {array} ids IDs\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\tsetAttributeTemplateOrder(response, ids, opts) {\n\t\t\t\t// Correct our models `orderby`\n\t\t\t\tlet model;\n\t\t\t\t_.each(ids, (id, idx) => {\n\t\t\t\t\tmodel = this.get(id);\n\t\t\t\t\t// Set silently as we will sort after this\n\t\t\t\t\t// If we trigger a change on each one we can cause the ui to become sluggish\n\t\t\t\t\t// as it will trigger renders and all sorts of unneeded checks\n\t\t\t\t\tmodel && model.set('orderby', idx + 1, {silent: true});\n\t\t\t\t});\n\t\t\t\tthis.sort();\n\t\t\t},\n\t\t\t/**\n\t\t\t * Updates attribute templates metadata synchronization\n\t\t\t * @method\n\t\t\t * @param {object} opts Request options\n\t\t\t */\n\t\t\t_setMetadataMap(opts) {\n\t\t\t\t// We want a true clone - no reference to one another\n\t\t\t\tthis.metadataMap = JSON.parse(JSON.stringify(this.metadataMapArgs));\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * @method\n\t * @param {array} attrs Attributes\n\t * @return {array}\n\t */\n\tparseAndCorrect(attrs) {\n\t\t// DAM-20153: this will one day be a feature of theme proper\n\t\tconst portal = getPortal();\n\t\tif (portal) {\n\t\t\tconst attributeIds = portal.get('attributeIds');\n\t\t\t// Right now the portal falls back to attribute -101 if no attributes are available\n\t\t\t// Due to attribute permission, this can happen regardless of what the server does\n\t\t\t// Though, the server should be enforcing that -100 and -101 are always returned until\n\t\t\t// we can properly address the hard coding in the portal\n\t\t\t// Also, the portal has no idea about clip only attributes\n\t\t\tconst filteredAttrs = attrs.filter(\n\t\t\t\t(attr) =>\n\t\t\t\t\tattributeIds.includes(attr.attributeid) &&\n\t\t\t\t\tattr.objectTypes.includes('asset'),\n\t\t\t);\n\t\t\tENFORCE_ATTRIBUTE_IDS.forEach((id) => {\n\t\t\t\tif (!filteredAttrs.find((attr) => attr.attributeid === id))\n\t\t\t\t\tfilteredAttrs.push(id);\n\t\t\t});\n\t\t\tattrs = filteredAttrs;\n\t\t}\n\n\t\treturn _.compact(\n\t\t\t_.map(attrs, (attr) => {\n\t\t\t\tlet attrName = attr.name;\n\n\t\t\t\t// We now allow some editing of system attributes as if they were regular attributes\n\t\t\t\t// turns out the server is not considering this data mandatory on their end\n\t\t\t\t// DAM-19292 - when this ticket is done we can remove this piece of code\n\t\t\t\tif ([-100, -101].includes(attr.attributeid)) {\n\t\t\t\t\tattr.mandatory = 1;\n\t\t\t\t\tattr.permission = Netx.getUserLevel() >= 7;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t(attrName !== 'checksum' || checksumEnabled()) &&\n\t\t\t\t\t(attrName !== 'expireDate' || assetExpirationEnabled()) &&\n\t\t\t\t\tattrName !== 'path' &&\n\t\t\t\t\tattrName !== 'modUser' &&\n\t\t\t\t\tattrName !== 'thumbPath'\n\t\t\t\t) {\n\t\t\t\t\tif (attr.system) {\n\t\t\t\t\t\tswitch (attrName) {\n\t\t\t\t\t\t\tcase 'fileSize':\n\t\t\t\t\t\t\t\tattrName = 'fileSize2';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'creationDate':\n\t\t\t\t\t\t\t\tattrName = 'creationdate';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'expireDate':\n\t\t\t\t\t\t\t\tattrName = 'expirationDate';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'fileType':\n\t\t\t\t\t\t\t\tattrName = 'filetypelabel';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'modDate':\n\t\t\t\t\t\t\t\tattrName = 'moddate';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn _.extend(attr, {\n\t\t\t\t\t\tname: attrName,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\t/** @override */\n\tconstructor(models, opts = {}) {\n\t\topts.model =\n\t\t\topts.model ||\n\t\t\tfunction (attrs, opts) {\n\t\t\t\tconst typeName = types[attrs.type];\n\t\t\t\tconst modelClass = Models[typeName] || Models.base;\n\t\t\t\treturn new modelClass(attrs, opts);\n\t\t\t};\n\n\t\t// Circular\n\t\t//AssetAttributeDatumCollection = require('./assetAttributeDatum');\n\t\tsuper(models, opts);\n\n\t\t/**\n\t\t * For use with `getAttributeTemplatesForCategoryContext`\n\t\t * Only respected when `permission.attributesEnabled` is true\n\t\t * @memberOf Netx.Collections.Attributes\n\t\t * @todo Andrew has noted that we will be eventually only allowing a single id here\n\t\t * We do not use more than one id as of yet and should not moving forward. The request\n\t\t * method will just send the first id and console log a warning if there is more than\n\t\t * one present in the mean time.\n\t\t * @alias categoryIds\n\t\t * @type {number}\n\t\t */\n\t\tthis.categoryIds =\n\t\t\t(Netx.getPreference('permission.attributesEnabled', true) &&\n\t\t\t\topts.categoryIds) ||\n\t\t\t[];\n\n\t\t/**\n\t\t * @memberof module:asset/collections/attributes\n\t\t * @alias keepAlphabetical\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.keepAlphabetical = Netx.getPreference(\n\t\t\t'metadata.keepListAlphabetical',\n\t\t\ttrue,\n\t\t);\n\n\t\t/**\n\t\t * Stores our metadata sync map\n\t\t * @type {object}\n\t\t * @default\n\t\t * @see this.getMetadataMap\n\t\t */\n\t\tthis.metadataMap = {\n\t\t\t// \"exportIds\": [\n\t\t\t// \t4,\n\t\t\t// \t5,\n\t\t\t// \t9\n\t\t\t// ],\n\t\t\t// \"exportImagePortalBlockOnProcess\": false,\n\t\t\t// \"exportImagePortalBlockOnSave\": false,\n\t\t\t// \"exportValues\": [\n\t\t\t// \t\"cdt:Type\",\n\t\t\t// \t\"fill:HasTransfo\",\n\t\t\t// \t\"pdf:Keywords\"\n\t\t\t// ],\n\t\t\t// \"importIds\": [\n\t\t\t// \t4,\n\t\t\t// \t5,\n\t\t\t// \t8\n\t\t\t// ],\n\t\t\t// \"importValues\": [\n\t\t\t// \t\"cdt:Type\",\n\t\t\t// \t\"fill:HasTransfo\",\n\t\t\t// \t\"ID3:Year\"\n\t\t\t// ],\n\t\t\t// \"modUserId\": 0\n\t\t};\n\n\t\t/**\n\t\t * Stores the metadata that is defined by the server as syncable\n\t\t * @type {array}\n\t\t * @default\n\t\t */\n\t\tthis.metadata = [\n\t\t\t// {\n\t\t\t// \t\"label\": \"Dublin Core\",\n\t\t\t// \t\"options\": [\n\t\t\t// \t\t{\n\t\t\t// \t\t\t\"direction\": \"both\",\n\t\t\t// \t\t\t\"label\": \"Dublin Core contributor\",\n\t\t\t// \t\t\t\"value\": \"dc:contributor\"\n\t\t\t// \t\t},\n\t\t\t// \t\t{\n\t\t\t// \t\t\t\"direction\": \"both\",\n\t\t\t// \t\t\t\"label\": \"Dublin Core coverage\",\n\t\t\t// \t\t\t\"value\": \"dc:coverage\"\n\t\t\t// \t\t}\n\t\t\t// \t]\n\t\t\t// }\n\t\t];\n\n\t\t/**\n\t\t * A clone of this.metadataMap (once fetched) so that we may make some comparisons\n\t\t * as to whether or not the metadata map needs saving - since it all gets saved at once\n\t\t * it can be quite expensive\n\t\t * @type {object}\n\t\t * @default\n\t\t * @see this.metadataMap\n\t\t */\n\t\tthis.metadataMapArgs = {\n\t\t\texportImagePortalBlockOnProcess: false,\n\t\t\texportImagePortalBlockOnSave: false,\n\t\t\texportIds: [],\n\t\t\texportValues: [],\n\t\t\timportIds: [],\n\t\t\timportValues: [],\n\t\t\tmodUserId: 0,\n\t\t};\n\n\t\t/**\n\t\t * @memberof module:asset/collections/attributes\n\t\t * @alias writableOnly\n\t\t * @type {boolean}\n\t\t */\n\t\tthis.writableOnly = opts.writableOnly === true;\n\n\t\t// Hey, listen!\n\t\tthis.listenTo(this, 'sync', (collection, results, opts) => {\n\t\t\t// Models sync too\n\t\t\tif (this !== collection) return;\n\n\t\t\tthis.stopListening(this, 'add change remove');\n\t\t\tthis.listenTo(this, 'add', this.attributeAdded);\n\t\t\tthis.listenTo(this, 'change', this.attributeChanged);\n\t\t\tthis.listenTo(this, 'remove', this.attributeRemoved);\n\t\t});\n\t}\n\n\t/**\n\t * @method\n\t * @param {Netx.Models.Attribute} model Attribute template model\n\t * @fires module:asset#asset:attribute:added\n\t */\n\tattributeAdded(model) {\n\t\t// Dispatch event\n\t\t// TODO: fix this, no dispatching from models/collections\n\t\tdispatcher.trigger('asset:attribute:added', model);\n\t}\n\n\t/**\n\t * @method\n\t * @param {Netx.Models.Attribute} model Attribute template model\n\t * @fires module:asset#asset:attribute:changed\n\t */\n\tattributeChanged(model) {\n\t\t// Dispatch event\n\t\t// TODO: fix this, no dispatching from models/collections\n\t\tdispatcher.trigger('asset:attribute:changed', model);\n\t}\n\n\t/**\n\t * @method\n\t * @param {Netx.Models.Attribute} model Attribute template model\n\t * @fires module:asset#asset:attribute:removed\n\t */\n\tattributeRemoved(model) {\n\t\t// Dispatch event\n\t\t// TODO: fix this, no dispatching from models/collections\n\t\tdispatcher.trigger('asset:attribute:removed', model);\n\t}\n\n\t/**\n\t * @method\n\t * @param {array} ids Array of attribute template ids\n\t */\n\tdeleteAttributes(ids) {\n\t\treturn this.deleteMultiple(ids);\n\t}\n\n\t/**\n\t * @method\n\t * @param {string} objectType Object type (asset/clip)\n\t */\n\tfilterByObjectType(objectType) {\n\t\tconst filter = () => {\n\t\t\treturn this.filter((model) => model.isForObjectType(objectType));\n\t\t};\n\n\t\t// When we change, so should the filtered collection\n\t\tconst collection = new this.constructor(filter());\n\t\treturn collection\n\t\t\t.listenTo(this, 'add', (attributes, attribute) => {\n\t\t\t\tcollection.add(attribute);\n\t\t\t})\n\t\t\t.listenTo(this, 'remove', (attributes, attribute) => {\n\t\t\t\tcollection.remove(attribute);\n\t\t\t})\n\t\t\t.listenTo(this, 'reset', (attributes) => {\n\t\t\t\tcollection.reset(filter());\n\t\t\t})\n\t\t\t.listenTo(this, 'sync', (attributes, data, opts) => {\n\t\t\t\tif (attributes !== this) return;\n\t\t\t\tcollection.set(filter(), opts);\n\t\t\t\tcollection.trigger('sync', collection);\n\t\t\t});\n\t}\n\n\t/**\n\t * @method\n\t * @param {array} types Types of attributes to return\n\t * @param {boolean} editableOnly Only return editable attributes\n\t * @return {Netx.Collection.Attributes}\n\t */\n\tfilterByTypes(types, editableOnly) {\n\t\t// Wrap\n\t\tif (!_.isArray(types)) {\n\t\t\ttypes = [types];\n\t\t}\n\n\t\t// For now we need to be the holders of this data\n\t\t// In 8.12 we will have flags on the templates themselves for this\n\t\tconst editableSystemAttributes = ['description', 'name'];\n\n\t\t// Support the user passing strings instead of type ids\n\t\t// Convert them over to type ids before going forward\n\t\ttypes = _.map(types, (type) =>\n\t\t\t!_.isNumeric(type) ? typeIds[type] : parseInt(type),\n\t\t);\n\n\t\t// Return filtered collection\n\t\treturn new this.constructor(\n\t\t\tthis.filter(\n\t\t\t\t(attr) =>\n\t\t\t\t\t// If we want only editable attributes then we need to omit any system attributes that cannot be edited - all other attribute types are editable by default\n\t\t\t\t\t_.contains(types, attr.get('type')) &&\n\t\t\t\t\t(!editableOnly ||\n\t\t\t\t\t\t!attr.get('system') ||\n\t\t\t\t\t\t_.contains(editableSystemAttributes, attr.get('name'))),\n\t\t\t),\n\t\t);\n\t}\n\n\t/**\n\t * @method\n\t * @return {module:asset/collections/attributes} Attributes tracking history\n\t */\n\tfilterByHistory() {\n\t\treturn new this.constructor(this.where({trackHistory: true}));\n\t}\n\n\t/**\n\t * @method\n\t * @return {module:asset/collections/assetAttributeDatum} Asset attribute datum\n\t */\n\tgetAttributeDatum(defaultValues) {\n\t\tconst attributeDatum = new AssetAttributeDatumCollection([\n\t\t\t{\n\t\t\t\tassetId: 0,\n\t\t\t\tattributes: [],\n\t\t\t},\n\t\t]);\n\n\t\tconst record = attributeDatum.at(0);\n\n\t\tthis.each((model) => {\n\t\t\tlet value = defaultValues ? model.get('value') : null;\n\n\t\t\tif (isEmptyValue(value)) {\n\t\t\t\tvalue = [];\n\t\t\t} else if (!_.isArray(value)) {\n\t\t\t\tvalue = [value];\n\t\t\t}\n\n\t\t\trecord.addAttribute({\n\t\t\t\tassetId: 0,\n\t\t\t\tmultivalue: model.get('multivalue'),\n\t\t\t\tpermission: 'w',\n\t\t\t\tvalues: value,\n\t\t\t\ttypeName: model.getTypeName(),\n\t\t\t\ttemplateId: model.id,\n\t\t\t\tname: model.get('name'),\n\t\t\t});\n\t\t});\n\n\t\treturn attributeDatum;\n\t}\n\n\t/**\n\t * For attr storage purposes: get an id for a name\n\t * Unfortunately in a lot of the old interface, attribute names were used over ids (diplayed attributes, attribute field sets etc)\n\t * @method\n\t * @param {string} name Attribute name\n\t * @return {number} Attribute id\n\t */\n\tgetIdByName(name) {\n\t\tconst attr = this.findWhere({name: name});\n\t\treturn attr ? attr.get('attributeid') : undefined;\n\t}\n\n\t/**\n\t * @method\n\t * @param {boolean} withoutDefaultValues Only return attributes without default values\n\t * @return {module:asset/collections/attributes}\n\t */\n\tgetMandatory(withoutDefaultValues, withoutSystem) {\n\t\treturn new this.constructor(\n\t\t\tthis.filter(\n\t\t\t\t(m) =>\n\t\t\t\t\tm.isMandatory() &&\n\t\t\t\t\t(!withoutDefaultValues || !m.hasDefaultValue()) &&\n\t\t\t\t\t(!withoutSystem || !m.get('system')),\n\t\t\t),\n\t\t);\n\t}\n\n\t/**\n\t * @method\n\t * @return {Netx.Collections.Attributes} Collection of system attributes\n\t */\n\tgetSystemAttributes() {\n\t\treturn new this.constructor(this.filter((attr) => attr.get('system')));\n\t}\n\n\t/**\n\t * Are there mandatory attributes?\n\t * @method\n\t * @return {array} List of attribute models that are mandatory, or 'undefined' (instead of empty array) if there are none.\n\t */\n\thasMandatory() {\n\t\tconst list = this.filter((m) => m.get('mandatory') == 1);\n\t\treturn list.length ? list : undefined;\n\t}\n\n\t/**\n\t * For asset sorting purposes, return an object of names of known attributes.\n\t * @method\n\t * @param {boolean} system Include system attributes\n\t * @return {object} names\n\t */\n\tnames(system) {\n\t\tconst names = {};\n\t\tthis.each((attr) => {\n\t\t\tif (system && attr.get('system') === true) {\n\t\t\t\tnames[attr.get('code')] = attr.get('name');\n\t\t\t} else if (attr.get('system') !== true) {\n\t\t\t\tnames[attr.get('name')] = attr.get('name');\n\t\t\t}\n\t\t});\n\t\treturn names;\n\t}\n\n\t/**\n\t * Vocabulary has been updated\n\t * @param {number} vocabularyId Vocabulary ID\n\t */\n\tupdatedVocabulary(vocabularyId) {\n\t\t// Every attribute that uses this vocab needs to be refetched\n\t\tthis.each((model) => {\n\t\t\tif (!vocabularyAttributes.includes(model.get('type'))) return;\n\t\t\tmodel.get('spec1') === vocabularyId && model.fetch();\n\t\t});\n\t}\n\n\t////////////////////////////////////\n\t// METADATA SYNC\n\t////////////////////////////////////\n\t/**\n\t * We have modified the metadata to sync on an attribute template\n\t * This is really fun - we do not have a call to simply update an attribute template's metadata sync parameters\n\t * we have to actually pass the whole updated thing at once - so we need to manually go through and deal with the parallel arrays\n\t * ourselves\n\t * @method\n\t * @param {module:asset/models/assetAttribute} model AssetAttribute model\n\t * @param {object} data Metadata sync data\n\t * @todo Get a call that can handle passing an array of attributes and their metadata sync values\n\t */\n\tattributeModifySyncMetadata(model, data) {\n\t\t// In this case, only `import` is allowed\n\t\tif (\n\t\t\tdata.syncMetadataType === '' &&\n\t\t\t!Netx.getPreference('share.metadata.roundtrip.enabled')\n\t\t) {\n\t\t\tdata.syncMetadataType = 'import';\n\t\t}\n\n\t\t// Find sync schema\n\t\tconst schema = _.findWhere(Netx.asset.attributes.metadata, {\n\t\t\tlabel: data.syncMetadataSchema,\n\t\t});\n\n\t\t// For memory sake\n\t\tconst exportIds = this.metadataMapArgs.exportIds || [];\n\t\tconst exportValues = this.metadataMapArgs.exportValues || [];\n\t\tconst importIds = this.metadataMapArgs.importIds || [];\n\t\tconst importValues = this.metadataMapArgs.importValues || [];\n\n\t\tlet value, validDirections;\n\t\t// Mapped schema\n\t\tif (schema) {\n\t\t\t// Find sync value on sync schema options\n\t\t\tvalue = _.findWhere(schema.options, {value: data.syncMetadataValue});\n\t\t\t// Found sync value\n\t\t\tif (value) {\n\t\t\t\t// Check valid direction\n\t\t\t\tif (value.direction === 'both') {\n\t\t\t\t\tvalidDirections = ['both', 'export', 'import'];\n\t\t\t\t} else {\n\t\t\t\t\tvalidDirections = [value.direction];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Assume custom schema\n\t\telse {\n\t\t\tvalidDirections = ['both', 'export', 'import'];\n\t\t}\n\n\t\t// Valid direction\n\t\tif (_.indexOf(validDirections, data.syncMetadataType) > -1) {\n\t\t\t// Find in imports\n\t\t\tconst importIdx = _.indexOf(this.metadataMap.importIds, model.id);\n\t\t\t// Find in exports\n\t\t\tconst exportIdx = _.indexOf(this.metadataMap.exportIds, model.id);\n\n\t\t\t// Is in the importIds array\n\t\t\tif (importIdx > -1) {\n\t\t\t\t// Is no longer valid as the directions do not match\n\t\t\t\tif (\n\t\t\t\t\tdata.syncMetadataType !== 'both' &&\n\t\t\t\t\tdata.syncMetadataType !== 'import'\n\t\t\t\t) {\n\t\t\t\t\timportIds.splice(importIdx, 1);\n\t\t\t\t\timportValues.splice(importIdx, 1);\n\t\t\t\t}\n\t\t\t\t// Update the value\n\t\t\t\telse {\n\t\t\t\t\timportValues.splice(importIdx, 1, data.syncMetadataValue);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Is not in the importIds array\n\t\t\telse if (\n\t\t\t\tdata.syncMetadataType === 'both' ||\n\t\t\t\tdata.syncMetadataType === 'import'\n\t\t\t) {\n\t\t\t\timportIds.push(model.id);\n\t\t\t\timportValues.push(data.syncMetadataValue);\n\t\t\t}\n\t\t\t// Is in the exportIds array\n\t\t\tif (exportIdx > -1) {\n\t\t\t\t// Is no longer valid as the directions do not match\n\t\t\t\tif (\n\t\t\t\t\tdata.syncMetadataType !== 'both' &&\n\t\t\t\t\tdata.syncMetadataType !== 'export'\n\t\t\t\t) {\n\t\t\t\t\texportIds.splice(exportIdx, 1);\n\t\t\t\t\texportValues.splice(exportIdx, 1);\n\t\t\t\t}\n\t\t\t\t// Update the value\n\t\t\t\telse {\n\t\t\t\t\texportValues.splice(exportIdx, 1, data.syncMetadataValue);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Is not in the exportIds array\n\t\t\telse if (\n\t\t\t\tdata.syncMetadataType === 'both' ||\n\t\t\t\tdata.syncMetadataType === 'export'\n\t\t\t) {\n\t\t\t\texportIds.push(model.id);\n\t\t\t\texportValues.push(data.syncMetadataValue);\n\t\t\t}\n\t\t}\n\t\t// Update on server\n\t\treturn this.setMetadataMap().then(() => {\n\t\t\tmodel.trigger('change', model);\n\t\t\tmodel.trigger('change:metadataSync', model, true);\n\t\t});\n\t}\n\n\t/**\n\t * Remove metadata sync from an attribute template\n\t * @method\n\t * @param {module:asset/models/assetAttribute} model AssetAttribute model\n\t */\n\tattributeRemoveSyncMetadata(model) {\n\t\tconst importIdx = _.indexOf(this.metadataMap.importIds, model.id);\n\t\tconst exportIdx = _.indexOf(this.metadataMap.exportIds, model.id);\n\t\tconst metadataMapArgs = this.metadataMapArgs;\n\n\t\t// Remove from import\n\t\tif (importIdx > -1) {\n\t\t\tmetadataMapArgs.importIds.splice(importIdx, 1);\n\t\t\tmetadataMapArgs.importValues.splice(importIdx, 1);\n\t\t}\n\t\t// Remove from export\n\t\tif (exportIdx > -1) {\n\t\t\tmetadataMapArgs.exportIds.splice(exportIdx, 1);\n\t\t\tmetadataMapArgs.exportValues.splice(exportIdx, 1);\n\t\t}\n\t\t// Update on server\n\t\treturn this.setMetadataMap().then(() => {\n\t\t\tmodel.trigger('change', model);\n\t\t\tmodel.trigger('change:metadataSync', model, false);\n\t\t});\n\t}\n\n\t/**\n\t * This fetches our metadata map json - which is an array of schemas with an array options within\n\t * The result of this call is used to populate the metadata sync options available to a user who can manage attribute templates\n\t * @method\n\t */\n\tgetMetadata() {\n\t\t// Should only need to fetch it once (and only for admins)\n\t\tif (Netx.getUserLevel() < 9 || this.metadata.length) {\n\t\t\treturn new $.Deferred().resolve(this.metadata);\n\t\t}\n\n\t\treturn this.getMetadataMapJson().then((response) => {\n\t\t\treturn this.metadata;\n\t\t});\n\t}\n\n\t/**\n\t * This fetches our metadata map - which contains parallel arrays of importIds/importValues and exportIds/exportValues\n\t * The values represent to the metadata to sync with the attribute and the ids are the attribute templates wishing to sync\n\t * If the same value and id match in the same position in both import and export, that is a round trip sync (both)\n\t * @method\n\t * @param {object} opts Request options\n\t */\n\tgetMetadataMap(opts) {\n\t\t// Should only need to fetch it once (and only for admins)\n\t\tif (Netx.getUserLevel() < 9 || !_.isEmpty(this.metadataMap.length)) {\n\t\t\treturn new $.Deferred().resolve(this.metadataMap);\n\t\t}\n\n\t\treturn this._getMetadataMap(opts).then((response) => {\n\t\t\treturn this.metadataMap;\n\t\t});\n\t}\n\n\t/**\n\t * Updates the metadata to sync with attribute templates\n\t * @method\n\t * @param {object} opts Request options\n\t */\n\tsetMetadataMap(opts) {\n\t\t// Check if any updating is needed\n\t\tif (_.isEqual(this.metadataMap, this.metadataMapArgs)) {\n\t\t\treturn new $.Deferred().resolve(this.metadataMap);\n\t\t}\n\n\t\treturn this._setMetadataMap(opts).then((response) => {\n\t\t\treturn this.metadataMap;\n\t\t});\n\t}\n\t////////////////////////////////////\n\t// !METADATA SYNC\n\t////////////////////////////////////\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attributes';\n\t}\n}\n","/**\n * @class\n * @deprecated\n */\nimport Base from './attribute_tag';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Semantic extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.semantic,\n\t\t};\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Semantic';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute_tag';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_TagVocab extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.tagVocab,\n\t\t};\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_TagVocab';\n\t}\n}\n","/**\n * @class\n */\nimport Base from './attribute_text';\n\nimport {ids as attributeTypeIds} from '@netx/core-asset/properties/attributes';\n\nexport default class Attribute_Textarea extends Base {\n\t/** @type {object} */\n\tget defaults() {\n\t\treturn {\n\t\t\t...super.defaults,\n\t\t\ttype: attributeTypeIds.textarea,\n\t\t};\n\t}\n\n\t/**\n\t * @override\n\t * @param {mixed} value Value\n\t * @param {object} opts Options\n\t * @return {mixed} Formatted value\n\t */\n\tformat(value, opts) {\n\t\topts = opts || {};\n\t\tvalue = super.format(value, opts);\n\n\t\treturn opts.html !== false ? value && value.replace(/\\n/g, '
') : value;\n\t}\n\n\t/** @type {string} */\n\tstatic get __name__() {\n\t\treturn 'Attribute_Textarea';\n\t}\n}\n","import { scheduleMicrotask } from './utils.esm.js';\n\nfunction createNotifyManager() {\n let queue = [];\n let transactions = 0;\n\n let notifyFn = callback => {\n callback();\n };\n\n let batchNotifyFn = callback => {\n callback();\n };\n\n const batch = callback => {\n let result;\n transactions++;\n\n try {\n result = callback();\n } finally {\n transactions--;\n\n if (!transactions) {\n flush();\n }\n }\n\n return result;\n };\n\n const schedule = callback => {\n if (transactions) {\n queue.push(callback);\n } else {\n scheduleMicrotask(() => {\n notifyFn(callback);\n });\n }\n };\n /**\n * All calls to the wrapped function will be batched.\n */\n\n\n const batchCalls = callback => {\n return (...args) => {\n schedule(() => {\n callback(...args);\n });\n };\n };\n\n const flush = () => {\n const originalQueue = queue;\n queue = [];\n\n if (originalQueue.length) {\n scheduleMicrotask(() => {\n batchNotifyFn(() => {\n originalQueue.forEach(callback => {\n notifyFn(callback);\n });\n });\n });\n }\n };\n /**\n * Use this method to set a custom notify function.\n * This can be used to for example wrap notifications with `React.act` while running tests.\n */\n\n\n const setNotifyFunction = fn => {\n notifyFn = fn;\n };\n /**\n * Use this method to set a custom function to batch notifications together into a single tick.\n * By default React Query will use the batch function provided by ReactDOM or React Native.\n */\n\n\n const setBatchNotifyFunction = fn => {\n batchNotifyFn = fn;\n };\n\n return {\n batch,\n batchCalls,\n schedule,\n setNotifyFunction,\n setBatchNotifyFunction\n };\n} // SINGLETON\n\nconst notifyManager = createNotifyManager();\n\nexport { createNotifyManager, notifyManager };\n//# sourceMappingURL=notifyManager.esm.js.map\n","import {ATTRIBUTE_SYSTEM_ID} from '@netx/core-attribute/constants';\nimport {SearchType} from './rules/constants';\n\nexport enum SearchMatchCriteria {\n\tAND = 0,\n\tOR = 1,\n\tNOT = 2,\n}\n\nexport enum SearchSortOrder {\n\tASC = 0,\n\tDESC = 1,\n}\n\nexport const DEFAULT_SEARCH_SORT_FIELD = 'file';\nexport const DEFAULT_SEARCH_SORT_ORDER = SearchSortOrder.ASC;\nexport const DEFAULT_SEARCH_MATCH_CRITERIA = SearchMatchCriteria.AND;\n\nexport enum MetadataSubType1 {\n\tMATCH_ALL_WHOLE_WORDS = 0,\n\tMATCH_EXACTLY = 1,\n\tMATCH_ANY_WHOLE_WORDS = 2,\n\tEXCLUDE = 3,\n\tMATCH_ALL_WILD_CARDS = 4,\n\tMATCH_ANY_WILD_CARDS = 5,\n\tMATCH_ANY_RANGE = 6,\n\tNO_VALUE = 11,\n\tANY_VALUE = 12,\n}\n\nexport const NON_SORTABLE_SEARCH_TYPES = [SearchType.CUSTOM, SearchType.VISUAL];\n\nexport const SEARCH_SORT_SYSTEM_ATTRIBUTES = [\n\tATTRIBUTE_SYSTEM_ID.checksum,\n\tATTRIBUTE_SYSTEM_ID.expireDate,\n\tATTRIBUTE_SYSTEM_ID.file,\n\tATTRIBUTE_SYSTEM_ID.name,\n\tATTRIBUTE_SYSTEM_ID.assetId,\n\tATTRIBUTE_SYSTEM_ID.fileFormatFamily,\n\tATTRIBUTE_SYSTEM_ID.fileSize2,\n\tATTRIBUTE_SYSTEM_ID.filetypelabel,\n\tATTRIBUTE_SYSTEM_ID.height,\n\tATTRIBUTE_SYSTEM_ID.importDate,\n\tATTRIBUTE_SYSTEM_ID.moddate,\n\tATTRIBUTE_SYSTEM_ID.creationdate,\n\tATTRIBUTE_SYSTEM_ID.dimensions,\n\tATTRIBUTE_SYSTEM_ID['smart labels'],\n\tATTRIBUTE_SYSTEM_ID.width,\n];\n\nexport const FACETS_SUPPORT_SEARCH_TYPES = [\n\tSearchType.ACTIVE_TEMPLATES,\n\tSearchType.ADVANCED_RAW,\n\tSearchType.ATTRIBUTE_HISTORY,\n\tSearchType.CART,\n\tSearchType.CATEGORY_ID,\n\tSearchType.CATEGORY_NAME,\n\tSearchType.CHECKOUTS,\n\tSearchType.CONTENTS,\n\tSearchType.DATE,\n\tSearchType.FILE_ASPECT,\n\tSearchType.FILE_FORMAT,\n\tSearchType.FILE_FORMAT_FAMILY,\n\tSearchType.FILE_SIZE,\n\tSearchType.KEYWORD,\n\tSearchType.METADATA,\n\tSearchType.SAVED_SEARCH,\n\tSearchType.THESAURUS,\n\tSearchType.VISUAL,\n];\n\nexport const SALO_STRING_MAP = {\n\ta: 'sortField',\n\tb: 'sortOrder',\n\tc: 'matchCriteria',\n\td: 'elementTypes',\n\te: 'elementSubType1s',\n\tf: 'elementSubType2s',\n\tg: 'elementValue1s',\n\th: 'elementValue2s',\n\ti: 'elementValue3s',\n};\n","function easeInOutSin(time) {\n return (1 + Math.sin(Math.PI * time - Math.PI / 2)) / 2;\n}\n\nexport default function animate(property, element, to, options = {}, cb = () => {}) {\n const {\n ease = easeInOutSin,\n duration = 300 // standard\n\n } = options;\n let start = null;\n const from = element[property];\n let cancelled = false;\n\n const cancel = () => {\n cancelled = true;\n };\n\n const step = timestamp => {\n if (cancelled) {\n cb(new Error('Animation cancelled'));\n return;\n }\n\n if (start === null) {\n start = timestamp;\n }\n\n const time = Math.min(1, (timestamp - start) / duration);\n element[property] = ease(time) * (to - from) + from;\n\n if (time >= 1) {\n requestAnimationFrame(() => {\n cb(null);\n });\n return;\n }\n\n requestAnimationFrame(step);\n };\n\n if (from === to) {\n cb(new Error('Element already at target position'));\n return cancel;\n }\n\n requestAnimationFrame(step);\n return cancel;\n}","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"onChange\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport debounce from '../utils/debounce';\nimport { ownerWindow } from '../utils';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst styles = {\n width: 99,\n height: 99,\n position: 'absolute',\n top: -9999,\n overflow: 'scroll'\n};\n/**\n * @ignore - internal component.\n * The component originates from https://github.com/STORIS/react-scrollbar-size.\n * It has been moved into the core in order to minimize the bundle size.\n */\n\nexport default function ScrollbarSize(props) {\n const {\n onChange\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const scrollbarHeight = React.useRef();\n const nodeRef = React.useRef(null);\n\n const setMeasurements = () => {\n scrollbarHeight.current = nodeRef.current.offsetHeight - nodeRef.current.clientHeight;\n };\n\n React.useEffect(() => {\n const handleResize = debounce(() => {\n const prevHeight = scrollbarHeight.current;\n setMeasurements();\n\n if (prevHeight !== scrollbarHeight.current) {\n onChange(scrollbarHeight.current);\n }\n });\n const containerWindow = ownerWindow(nodeRef.current);\n containerWindow.addEventListener('resize', handleResize);\n return () => {\n handleResize.clear();\n containerWindow.removeEventListener('resize', handleResize);\n };\n }, [onChange]);\n React.useEffect(() => {\n setMeasurements();\n onChange(scrollbarHeight.current);\n }, [onChange]);\n return /*#__PURE__*/_jsx(\"div\", _extends({\n style: styles,\n ref: nodeRef\n }, other));\n}\nprocess.env.NODE_ENV !== \"production\" ? ScrollbarSize.propTypes = {\n onChange: PropTypes.func.isRequired\n} : void 0;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTabScrollButtonUtilityClass(slot) {\n return generateUtilityClass('MuiTabScrollButton', slot);\n}\nconst tabScrollButtonClasses = generateUtilityClasses('MuiTabScrollButton', ['root', 'vertical', 'horizontal', 'disabled']);\nexport default tabScrollButtonClasses;","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\n\nvar _KeyboardArrowLeft, _KeyboardArrowRight;\n\nconst _excluded = [\"className\", \"direction\", \"orientation\", \"disabled\"];\n\n/* eslint-disable jsx-a11y/aria-role */\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';\nimport KeyboardArrowRight from '../internal/svg-icons/KeyboardArrowRight';\nimport ButtonBase from '../ButtonBase';\nimport useTheme from '../styles/useTheme';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport tabScrollButtonClasses, { getTabScrollButtonUtilityClass } from './tabScrollButtonClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n orientation,\n disabled\n } = ownerState;\n const slots = {\n root: ['root', orientation, disabled && 'disabled']\n };\n return composeClasses(slots, getTabScrollButtonUtilityClass, classes);\n};\n\nconst TabScrollButtonRoot = styled(ButtonBase, {\n name: 'MuiTabScrollButton',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.orientation && styles[ownerState.orientation]];\n }\n})(({\n ownerState\n}) => _extends({\n width: 40,\n flexShrink: 0,\n opacity: 0.8,\n [`&.${tabScrollButtonClasses.disabled}`]: {\n opacity: 0\n }\n}, ownerState.orientation === 'vertical' && {\n width: '100%',\n height: 40,\n '& svg': {\n transform: `rotate(${ownerState.isRtl ? -90 : 90}deg)`\n }\n}));\nconst TabScrollButton = /*#__PURE__*/React.forwardRef(function TabScrollButton(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTabScrollButton'\n });\n\n const {\n className,\n direction\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const theme = useTheme();\n const isRtl = theme.direction === 'rtl';\n\n const ownerState = _extends({\n isRtl\n }, props);\n\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(TabScrollButtonRoot, _extends({\n component: \"div\",\n className: clsx(classes.root, className),\n ref: ref,\n role: null,\n ownerState: ownerState,\n tabIndex: null\n }, other, {\n children: direction === 'left' ? _KeyboardArrowLeft || (_KeyboardArrowLeft = /*#__PURE__*/_jsx(KeyboardArrowLeft, {\n fontSize: \"small\"\n })) : _KeyboardArrowRight || (_KeyboardArrowRight = /*#__PURE__*/_jsx(KeyboardArrowRight, {\n fontSize: \"small\"\n }))\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? TabScrollButton.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * The content of the component.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The direction the button should indicate.\n */\n direction: PropTypes.oneOf(['left', 'right']).isRequired,\n\n /**\n * If `true`, the component is disabled.\n */\n disabled: PropTypes.bool,\n\n /**\n * The component orientation (layout flow direction).\n */\n orientation: PropTypes.oneOf(['horizontal', 'vertical']).isRequired,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default TabScrollButton;","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTabsUtilityClass(slot) {\n return generateUtilityClass('MuiTabs', slot);\n}\nconst tabsClasses = generateUtilityClasses('MuiTabs', ['root', 'vertical', 'flexContainer', 'flexContainerVertical', 'centered', 'scroller', 'fixed', 'scrollableX', 'scrollableY', 'hideScrollbar', 'scrollButtons', 'scrollButtonsHideMobile', 'indicator']);\nexport default tabsClasses;","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"aria-label\", \"aria-labelledby\", \"action\", \"centered\", \"children\", \"className\", \"component\", \"allowScrollButtonsMobile\", \"indicatorColor\", \"onChange\", \"orientation\", \"ScrollButtonComponent\", \"scrollButtons\", \"selectionFollowsFocus\", \"TabIndicatorProps\", \"TabScrollButtonProps\", \"textColor\", \"value\", \"variant\", \"visibleScrollbar\"];\nimport * as React from 'react';\nimport { isFragment } from 'react-is';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { refType } from '@mui/utils';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport styled from '../styles/styled';\nimport useThemeProps from '../styles/useThemeProps';\nimport useTheme from '../styles/useTheme';\nimport debounce from '../utils/debounce';\nimport { getNormalizedScrollLeft, detectScrollType } from '../utils/scrollLeft';\nimport animate from '../internal/animate';\nimport ScrollbarSize from './ScrollbarSize';\nimport TabScrollButton from '../TabScrollButton';\nimport useEventCallback from '../utils/useEventCallback';\nimport tabsClasses, { getTabsUtilityClass } from './tabsClasses';\nimport ownerDocument from '../utils/ownerDocument';\nimport ownerWindow from '../utils/ownerWindow';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nimport { jsxs as _jsxs } from \"react/jsx-runtime\";\n\nconst nextItem = (list, item) => {\n if (list === item) {\n return list.firstChild;\n }\n\n if (item && item.nextElementSibling) {\n return item.nextElementSibling;\n }\n\n return list.firstChild;\n};\n\nconst previousItem = (list, item) => {\n if (list === item) {\n return list.lastChild;\n }\n\n if (item && item.previousElementSibling) {\n return item.previousElementSibling;\n }\n\n return list.lastChild;\n};\n\nconst moveFocus = (list, currentFocus, traversalFunction) => {\n let wrappedOnce = false;\n let nextFocus = traversalFunction(list, currentFocus);\n\n while (nextFocus) {\n // Prevent infinite loop.\n if (nextFocus === list.firstChild) {\n if (wrappedOnce) {\n return;\n }\n\n wrappedOnce = true;\n } // Same logic as useAutocomplete.js\n\n\n const nextFocusDisabled = nextFocus.disabled || nextFocus.getAttribute('aria-disabled') === 'true';\n\n if (!nextFocus.hasAttribute('tabindex') || nextFocusDisabled) {\n // Move to the next element.\n nextFocus = traversalFunction(list, nextFocus);\n } else {\n nextFocus.focus();\n return;\n }\n }\n};\n\nconst useUtilityClasses = ownerState => {\n const {\n vertical,\n fixed,\n hideScrollbar,\n scrollableX,\n scrollableY,\n centered,\n scrollButtonsHideMobile,\n classes\n } = ownerState;\n const slots = {\n root: ['root', vertical && 'vertical'],\n scroller: ['scroller', fixed && 'fixed', hideScrollbar && 'hideScrollbar', scrollableX && 'scrollableX', scrollableY && 'scrollableY'],\n flexContainer: ['flexContainer', vertical && 'flexContainerVertical', centered && 'centered'],\n indicator: ['indicator'],\n scrollButtons: ['scrollButtons', scrollButtonsHideMobile && 'scrollButtonsHideMobile'],\n scrollableX: [scrollableX && 'scrollableX'],\n hideScrollbar: [hideScrollbar && 'hideScrollbar']\n };\n return composeClasses(slots, getTabsUtilityClass, classes);\n};\n\nconst TabsRoot = styled('div', {\n name: 'MuiTabs',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [{\n [`& .${tabsClasses.scrollButtons}`]: styles.scrollButtons\n }, {\n [`& .${tabsClasses.scrollButtons}`]: ownerState.scrollButtonsHideMobile && styles.scrollButtonsHideMobile\n }, styles.root, ownerState.vertical && styles.vertical];\n }\n})(({\n ownerState,\n theme\n}) => _extends({\n overflow: 'hidden',\n minHeight: 48,\n // Add iOS momentum scrolling for iOS < 13.0\n WebkitOverflowScrolling: 'touch',\n display: 'flex'\n}, ownerState.vertical && {\n flexDirection: 'column'\n}, ownerState.scrollButtonsHideMobile && {\n [`& .${tabsClasses.scrollButtons}`]: {\n [theme.breakpoints.down('sm')]: {\n display: 'none'\n }\n }\n}));\nconst TabsScroller = styled('div', {\n name: 'MuiTabs',\n slot: 'Scroller',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.scroller, ownerState.fixed && styles.fixed, ownerState.hideScrollbar && styles.hideScrollbar, ownerState.scrollableX && styles.scrollableX, ownerState.scrollableY && styles.scrollableY];\n }\n})(({\n ownerState\n}) => _extends({\n position: 'relative',\n display: 'inline-block',\n flex: '1 1 auto',\n whiteSpace: 'nowrap'\n}, ownerState.fixed && {\n overflowX: 'hidden',\n width: '100%'\n}, ownerState.hideScrollbar && {\n // Hide dimensionless scrollbar on macOS\n scrollbarWidth: 'none',\n // Firefox\n '&::-webkit-scrollbar': {\n display: 'none' // Safari + Chrome\n\n }\n}, ownerState.scrollableX && {\n overflowX: 'auto',\n overflowY: 'hidden'\n}, ownerState.scrollableY && {\n overflowY: 'auto',\n overflowX: 'hidden'\n}));\nconst FlexContainer = styled('div', {\n name: 'MuiTabs',\n slot: 'FlexContainer',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.flexContainer, ownerState.vertical && styles.flexContainerVertical, ownerState.centered && styles.centered];\n }\n})(({\n ownerState\n}) => _extends({\n display: 'flex'\n}, ownerState.vertical && {\n flexDirection: 'column'\n}, ownerState.centered && {\n justifyContent: 'center'\n}));\nconst TabsIndicator = styled('span', {\n name: 'MuiTabs',\n slot: 'Indicator',\n overridesResolver: (props, styles) => styles.indicator\n})(({\n ownerState,\n theme\n}) => _extends({\n position: 'absolute',\n height: 2,\n bottom: 0,\n width: '100%',\n transition: theme.transitions.create()\n}, ownerState.indicatorColor === 'primary' && {\n backgroundColor: (theme.vars || theme).palette.primary.main\n}, ownerState.indicatorColor === 'secondary' && {\n backgroundColor: (theme.vars || theme).palette.secondary.main\n}, ownerState.vertical && {\n height: '100%',\n width: 2,\n right: 0\n}));\nconst TabsScrollbarSize = styled(ScrollbarSize, {\n name: 'MuiTabs',\n slot: 'ScrollbarSize'\n})({\n overflowX: 'auto',\n overflowY: 'hidden',\n // Hide dimensionless scrollbar on macOS\n scrollbarWidth: 'none',\n // Firefox\n '&::-webkit-scrollbar': {\n display: 'none' // Safari + Chrome\n\n }\n});\nconst defaultIndicatorStyle = {};\nlet warnedOnceTabPresent = false;\nconst Tabs = /*#__PURE__*/React.forwardRef(function Tabs(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTabs'\n });\n const theme = useTheme();\n const isRtl = theme.direction === 'rtl';\n\n const {\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n action,\n centered = false,\n children: childrenProp,\n className,\n component = 'div',\n allowScrollButtonsMobile = false,\n indicatorColor = 'primary',\n onChange,\n orientation = 'horizontal',\n ScrollButtonComponent = TabScrollButton,\n scrollButtons = 'auto',\n selectionFollowsFocus,\n TabIndicatorProps = {},\n TabScrollButtonProps = {},\n textColor = 'primary',\n value,\n variant = 'standard',\n visibleScrollbar = false\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const scrollable = variant === 'scrollable';\n const vertical = orientation === 'vertical';\n const scrollStart = vertical ? 'scrollTop' : 'scrollLeft';\n const start = vertical ? 'top' : 'left';\n const end = vertical ? 'bottom' : 'right';\n const clientSize = vertical ? 'clientHeight' : 'clientWidth';\n const size = vertical ? 'height' : 'width';\n\n const ownerState = _extends({}, props, {\n component,\n allowScrollButtonsMobile,\n indicatorColor,\n orientation,\n vertical,\n scrollButtons,\n textColor,\n variant,\n visibleScrollbar,\n fixed: !scrollable,\n hideScrollbar: scrollable && !visibleScrollbar,\n scrollableX: scrollable && !vertical,\n scrollableY: scrollable && vertical,\n centered: centered && !scrollable,\n scrollButtonsHideMobile: !allowScrollButtonsMobile\n });\n\n const classes = useUtilityClasses(ownerState);\n\n if (process.env.NODE_ENV !== 'production') {\n if (centered && scrollable) {\n console.error('MUI: You can not use the `centered={true}` and `variant=\"scrollable\"` properties ' + 'at the same time on a `Tabs` component.');\n }\n }\n\n const [mounted, setMounted] = React.useState(false);\n const [indicatorStyle, setIndicatorStyle] = React.useState(defaultIndicatorStyle);\n const [displayScroll, setDisplayScroll] = React.useState({\n start: false,\n end: false\n });\n const [scrollerStyle, setScrollerStyle] = React.useState({\n overflow: 'hidden',\n scrollbarWidth: 0\n });\n const valueToIndex = new Map();\n const tabsRef = React.useRef(null);\n const tabListRef = React.useRef(null);\n\n const getTabsMeta = () => {\n const tabsNode = tabsRef.current;\n let tabsMeta;\n\n if (tabsNode) {\n const rect = tabsNode.getBoundingClientRect(); // create a new object with ClientRect class props + scrollLeft\n\n tabsMeta = {\n clientWidth: tabsNode.clientWidth,\n scrollLeft: tabsNode.scrollLeft,\n scrollTop: tabsNode.scrollTop,\n scrollLeftNormalized: getNormalizedScrollLeft(tabsNode, theme.direction),\n scrollWidth: tabsNode.scrollWidth,\n top: rect.top,\n bottom: rect.bottom,\n left: rect.left,\n right: rect.right\n };\n }\n\n let tabMeta;\n\n if (tabsNode && value !== false) {\n const children = tabListRef.current.children;\n\n if (children.length > 0) {\n const tab = children[valueToIndex.get(value)];\n\n if (process.env.NODE_ENV !== 'production') {\n if (!tab) {\n console.error([`MUI: The \\`value\\` provided to the Tabs component is invalid.`, `None of the Tabs' children match with \"${value}\".`, valueToIndex.keys ? `You can provide one of the following values: ${Array.from(valueToIndex.keys()).join(', ')}.` : null].join('\\n'));\n }\n }\n\n tabMeta = tab ? tab.getBoundingClientRect() : null;\n\n if (process.env.NODE_ENV !== 'production') {\n if (process.env.NODE_ENV !== 'test' && !warnedOnceTabPresent && tabMeta && tabMeta.width === 0 && tabMeta.height === 0) {\n tabsMeta = null;\n console.error(['MUI: The `value` provided to the Tabs component is invalid.', `The Tab with this \\`value\\` (\"${value}\") is not part of the document layout.`, \"Make sure the tab item is present in the document or that it's not `display: none`.\"].join('\\n'));\n warnedOnceTabPresent = true;\n }\n }\n }\n }\n\n return {\n tabsMeta,\n tabMeta\n };\n };\n\n const updateIndicatorState = useEventCallback(() => {\n const {\n tabsMeta,\n tabMeta\n } = getTabsMeta();\n let startValue = 0;\n let startIndicator;\n\n if (vertical) {\n startIndicator = 'top';\n\n if (tabMeta && tabsMeta) {\n startValue = tabMeta.top - tabsMeta.top + tabsMeta.scrollTop;\n }\n } else {\n startIndicator = isRtl ? 'right' : 'left';\n\n if (tabMeta && tabsMeta) {\n const correction = isRtl ? tabsMeta.scrollLeftNormalized + tabsMeta.clientWidth - tabsMeta.scrollWidth : tabsMeta.scrollLeft;\n startValue = (isRtl ? -1 : 1) * (tabMeta[startIndicator] - tabsMeta[startIndicator] + correction);\n }\n }\n\n const newIndicatorStyle = {\n [startIndicator]: startValue,\n // May be wrong until the font is loaded.\n [size]: tabMeta ? tabMeta[size] : 0\n }; // IE11 support, replace with Number.isNaN\n // eslint-disable-next-line no-restricted-globals\n\n if (isNaN(indicatorStyle[startIndicator]) || isNaN(indicatorStyle[size])) {\n setIndicatorStyle(newIndicatorStyle);\n } else {\n const dStart = Math.abs(indicatorStyle[startIndicator] - newIndicatorStyle[startIndicator]);\n const dSize = Math.abs(indicatorStyle[size] - newIndicatorStyle[size]);\n\n if (dStart >= 1 || dSize >= 1) {\n setIndicatorStyle(newIndicatorStyle);\n }\n }\n });\n\n const scroll = (scrollValue, {\n animation = true\n } = {}) => {\n if (animation) {\n animate(scrollStart, tabsRef.current, scrollValue, {\n duration: theme.transitions.duration.standard\n });\n } else {\n tabsRef.current[scrollStart] = scrollValue;\n }\n };\n\n const moveTabsScroll = delta => {\n let scrollValue = tabsRef.current[scrollStart];\n\n if (vertical) {\n scrollValue += delta;\n } else {\n scrollValue += delta * (isRtl ? -1 : 1); // Fix for Edge\n\n scrollValue *= isRtl && detectScrollType() === 'reverse' ? -1 : 1;\n }\n\n scroll(scrollValue);\n };\n\n const getScrollSize = () => {\n const containerSize = tabsRef.current[clientSize];\n let totalSize = 0;\n const children = Array.from(tabListRef.current.children);\n\n for (let i = 0; i < children.length; i += 1) {\n const tab = children[i];\n\n if (totalSize + tab[clientSize] > containerSize) {\n // If the first item is longer than the container size, then only scroll\n // by the container size.\n if (i === 0) {\n totalSize = containerSize;\n }\n\n break;\n }\n\n totalSize += tab[clientSize];\n }\n\n return totalSize;\n };\n\n const handleStartScrollClick = () => {\n moveTabsScroll(-1 * getScrollSize());\n };\n\n const handleEndScrollClick = () => {\n moveTabsScroll(getScrollSize());\n }; // TODO Remove as browser support for hidding the scrollbar\n // with CSS improves.\n\n\n const handleScrollbarSizeChange = React.useCallback(scrollbarWidth => {\n setScrollerStyle({\n overflow: null,\n scrollbarWidth\n });\n }, []);\n\n const getConditionalElements = () => {\n const conditionalElements = {};\n conditionalElements.scrollbarSizeListener = scrollable ? /*#__PURE__*/_jsx(TabsScrollbarSize, {\n onChange: handleScrollbarSizeChange,\n className: clsx(classes.scrollableX, classes.hideScrollbar)\n }) : null;\n const scrollButtonsActive = displayScroll.start || displayScroll.end;\n const showScrollButtons = scrollable && (scrollButtons === 'auto' && scrollButtonsActive || scrollButtons === true);\n conditionalElements.scrollButtonStart = showScrollButtons ? /*#__PURE__*/_jsx(ScrollButtonComponent, _extends({\n orientation: orientation,\n direction: isRtl ? 'right' : 'left',\n onClick: handleStartScrollClick,\n disabled: !displayScroll.start\n }, TabScrollButtonProps, {\n className: clsx(classes.scrollButtons, TabScrollButtonProps.className)\n })) : null;\n conditionalElements.scrollButtonEnd = showScrollButtons ? /*#__PURE__*/_jsx(ScrollButtonComponent, _extends({\n orientation: orientation,\n direction: isRtl ? 'left' : 'right',\n onClick: handleEndScrollClick,\n disabled: !displayScroll.end\n }, TabScrollButtonProps, {\n className: clsx(classes.scrollButtons, TabScrollButtonProps.className)\n })) : null;\n return conditionalElements;\n };\n\n const scrollSelectedIntoView = useEventCallback(animation => {\n const {\n tabsMeta,\n tabMeta\n } = getTabsMeta();\n\n if (!tabMeta || !tabsMeta) {\n return;\n }\n\n if (tabMeta[start] < tabsMeta[start]) {\n // left side of button is out of view\n const nextScrollStart = tabsMeta[scrollStart] + (tabMeta[start] - tabsMeta[start]);\n scroll(nextScrollStart, {\n animation\n });\n } else if (tabMeta[end] > tabsMeta[end]) {\n // right side of button is out of view\n const nextScrollStart = tabsMeta[scrollStart] + (tabMeta[end] - tabsMeta[end]);\n scroll(nextScrollStart, {\n animation\n });\n }\n });\n const updateScrollButtonState = useEventCallback(() => {\n if (scrollable && scrollButtons !== false) {\n const {\n scrollTop,\n scrollHeight,\n clientHeight,\n scrollWidth,\n clientWidth\n } = tabsRef.current;\n let showStartScroll;\n let showEndScroll;\n\n if (vertical) {\n showStartScroll = scrollTop > 1;\n showEndScroll = scrollTop < scrollHeight - clientHeight - 1;\n } else {\n const scrollLeft = getNormalizedScrollLeft(tabsRef.current, theme.direction); // use 1 for the potential rounding error with browser zooms.\n\n showStartScroll = isRtl ? scrollLeft < scrollWidth - clientWidth - 1 : scrollLeft > 1;\n showEndScroll = !isRtl ? scrollLeft < scrollWidth - clientWidth - 1 : scrollLeft > 1;\n }\n\n if (showStartScroll !== displayScroll.start || showEndScroll !== displayScroll.end) {\n setDisplayScroll({\n start: showStartScroll,\n end: showEndScroll\n });\n }\n }\n });\n React.useEffect(() => {\n const handleResize = debounce(() => {\n // If the Tabs component is replaced by Suspense with a fallback, the last\n // ResizeObserver's handler that runs because of the change in the layout is trying to\n // access a dom node that is no longer there (as the fallback component is being shown instead).\n // See https://github.com/mui/material-ui/issues/33276\n // TODO: Add tests that will ensure the component is not failing when\n // replaced by Suspense with a fallback, once React is updated to version 18\n if (tabsRef.current) {\n updateIndicatorState();\n updateScrollButtonState();\n }\n });\n const win = ownerWindow(tabsRef.current);\n win.addEventListener('resize', handleResize);\n let resizeObserver;\n\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(handleResize);\n Array.from(tabListRef.current.children).forEach(child => {\n resizeObserver.observe(child);\n });\n }\n\n return () => {\n handleResize.clear();\n win.removeEventListener('resize', handleResize);\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n };\n }, [updateIndicatorState, updateScrollButtonState]);\n const handleTabsScroll = React.useMemo(() => debounce(() => {\n updateScrollButtonState();\n }), [updateScrollButtonState]);\n React.useEffect(() => {\n return () => {\n handleTabsScroll.clear();\n };\n }, [handleTabsScroll]);\n React.useEffect(() => {\n setMounted(true);\n }, []);\n React.useEffect(() => {\n updateIndicatorState();\n updateScrollButtonState();\n });\n React.useEffect(() => {\n // Don't animate on the first render.\n scrollSelectedIntoView(defaultIndicatorStyle !== indicatorStyle);\n }, [scrollSelectedIntoView, indicatorStyle]);\n React.useImperativeHandle(action, () => ({\n updateIndicator: updateIndicatorState,\n updateScrollButtons: updateScrollButtonState\n }), [updateIndicatorState, updateScrollButtonState]);\n\n const indicator = /*#__PURE__*/_jsx(TabsIndicator, _extends({}, TabIndicatorProps, {\n className: clsx(classes.indicator, TabIndicatorProps.className),\n ownerState: ownerState,\n style: _extends({}, indicatorStyle, TabIndicatorProps.style)\n }));\n\n let childIndex = 0;\n const children = React.Children.map(childrenProp, child => {\n if (! /*#__PURE__*/React.isValidElement(child)) {\n return null;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n if (isFragment(child)) {\n console.error([\"MUI: The Tabs component doesn't accept a Fragment as a child.\", 'Consider providing an array instead.'].join('\\n'));\n }\n }\n\n const childValue = child.props.value === undefined ? childIndex : child.props.value;\n valueToIndex.set(childValue, childIndex);\n const selected = childValue === value;\n childIndex += 1;\n return /*#__PURE__*/React.cloneElement(child, _extends({\n fullWidth: variant === 'fullWidth',\n indicator: selected && !mounted && indicator,\n selected,\n selectionFollowsFocus,\n onChange,\n textColor,\n value: childValue\n }, childIndex === 1 && value === false && !child.props.tabIndex ? {\n tabIndex: 0\n } : {}));\n });\n\n const handleKeyDown = event => {\n const list = tabListRef.current;\n const currentFocus = ownerDocument(list).activeElement; // Keyboard navigation assumes that [role=\"tab\"] are siblings\n // though we might warn in the future about nested, interactive elements\n // as a a11y violation\n\n const role = currentFocus.getAttribute('role');\n\n if (role !== 'tab') {\n return;\n }\n\n let previousItemKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';\n let nextItemKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';\n\n if (orientation === 'horizontal' && isRtl) {\n // swap previousItemKey with nextItemKey\n previousItemKey = 'ArrowRight';\n nextItemKey = 'ArrowLeft';\n }\n\n switch (event.key) {\n case previousItemKey:\n event.preventDefault();\n moveFocus(list, currentFocus, previousItem);\n break;\n\n case nextItemKey:\n event.preventDefault();\n moveFocus(list, currentFocus, nextItem);\n break;\n\n case 'Home':\n event.preventDefault();\n moveFocus(list, null, nextItem);\n break;\n\n case 'End':\n event.preventDefault();\n moveFocus(list, null, previousItem);\n break;\n\n default:\n break;\n }\n };\n\n const conditionalElements = getConditionalElements();\n return /*#__PURE__*/_jsxs(TabsRoot, _extends({\n className: clsx(classes.root, className),\n ownerState: ownerState,\n ref: ref,\n as: component\n }, other, {\n children: [conditionalElements.scrollButtonStart, conditionalElements.scrollbarSizeListener, /*#__PURE__*/_jsxs(TabsScroller, {\n className: classes.scroller,\n ownerState: ownerState,\n style: {\n overflow: scrollerStyle.overflow,\n [vertical ? `margin${isRtl ? 'Left' : 'Right'}` : 'marginBottom']: visibleScrollbar ? undefined : -scrollerStyle.scrollbarWidth\n },\n ref: tabsRef,\n onScroll: handleTabsScroll,\n children: [/*#__PURE__*/_jsx(FlexContainer, {\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-orientation\": orientation === 'vertical' ? 'vertical' : null,\n className: classes.flexContainer,\n ownerState: ownerState,\n onKeyDown: handleKeyDown,\n ref: tabListRef,\n role: \"tablist\",\n children: children\n }), mounted && indicator]\n }), conditionalElements.scrollButtonEnd]\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? Tabs.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * Callback fired when the component mounts.\n * This is useful when you want to trigger an action programmatically.\n * It supports two actions: `updateIndicator()` and `updateScrollButtons()`\n *\n * @param {object} actions This object contains all possible actions\n * that can be triggered programmatically.\n */\n action: refType,\n\n /**\n * If `true`, the scroll buttons aren't forced hidden on mobile.\n * By default the scroll buttons are hidden on mobile and takes precedence over `scrollButtons`.\n * @default false\n */\n allowScrollButtonsMobile: PropTypes.bool,\n\n /**\n * The label for the Tabs as a string.\n */\n 'aria-label': PropTypes.string,\n\n /**\n * An id or list of ids separated by a space that label the Tabs.\n */\n 'aria-labelledby': PropTypes.string,\n\n /**\n * If `true`, the tabs are centered.\n * This prop is intended for large views.\n * @default false\n */\n centered: PropTypes.bool,\n\n /**\n * The content of the component.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n\n /**\n * Determines the color of the indicator.\n * @default 'primary'\n */\n indicatorColor: PropTypes\n /* @typescript-to-proptypes-ignore */\n .oneOfType([PropTypes.oneOf(['primary', 'secondary']), PropTypes.string]),\n\n /**\n * Callback fired when the value changes.\n *\n * @param {React.SyntheticEvent} event The event source of the callback. **Warning**: This is a generic event not a change event.\n * @param {any} value We default to the index of the child (number)\n */\n onChange: PropTypes.func,\n\n /**\n * The component orientation (layout flow direction).\n * @default 'horizontal'\n */\n orientation: PropTypes.oneOf(['horizontal', 'vertical']),\n\n /**\n * The component used to render the scroll buttons.\n * @default TabScrollButton\n */\n ScrollButtonComponent: PropTypes.elementType,\n\n /**\n * Determine behavior of scroll buttons when tabs are set to scroll:\n *\n * - `auto` will only present them when not all the items are visible.\n * - `true` will always present them.\n * - `false` will never present them.\n *\n * By default the scroll buttons are hidden on mobile.\n * This behavior can be disabled with `allowScrollButtonsMobile`.\n * @default 'auto'\n */\n scrollButtons: PropTypes\n /* @typescript-to-proptypes-ignore */\n .oneOf(['auto', false, true]),\n\n /**\n * If `true` the selected tab changes on focus. Otherwise it only\n * changes on activation.\n */\n selectionFollowsFocus: PropTypes.bool,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),\n\n /**\n * Props applied to the tab indicator element.\n * @default {}\n */\n TabIndicatorProps: PropTypes.object,\n\n /**\n * Props applied to the [`TabScrollButton`](/material-ui/api/tab-scroll-button/) element.\n * @default {}\n */\n TabScrollButtonProps: PropTypes.object,\n\n /**\n * Determines the color of the `Tab`.\n * @default 'primary'\n */\n textColor: PropTypes.oneOf(['inherit', 'primary', 'secondary']),\n\n /**\n * The value of the currently selected `Tab`.\n * If you don't want any selected `Tab`, you can set this prop to `false`.\n */\n value: PropTypes.any,\n\n /**\n * Determines additional display behavior of the tabs:\n *\n * - `scrollable` will invoke scrolling properties and allow for horizontally\n * scrolling (or swiping) of the tab bar.\n * -`fullWidth` will make the tabs grow to use all the available space,\n * which should be used for small views, like on mobile.\n * - `standard` will render the default state.\n * @default 'standard'\n */\n variant: PropTypes.oneOf(['fullWidth', 'scrollable', 'standard']),\n\n /**\n * If `true`, the scrollbar is visible. It can be useful when displaying\n * a long vertical list of tabs.\n * @default false\n */\n visibleScrollbar: PropTypes.bool\n} : void 0;\nexport default Tabs;","import React from 'react';\n\nimport {Tabs as MuiTabs, TabsProps as MuiTabsProps} from '@mui/material';\n\nimport {useTabsProvider} from './';\nimport {styled, WithMuiPropOverrides} from '../Theme';\n\nconst TabsRoot = styled(MuiTabs, {\n\tslot: 'Root',\n})(({theme}) => ({\n\tflex: '0 0 auto',\n}));\n\nexport interface TabsProps\n\textends Omit, 'onChange'> {\n\t// Overriding to enforce `number` as tab value\n\tonChange?: (event: React.SyntheticEvent, value: number) => void;\n}\n\n/**\n * Wrapper for `@material-ui/Tabs`\\\n * Provides some common overrides, and accepts all the same props as the component it wraps\n */\nexport const TabsPrimitive = (props: TabsProps) => {\n\tconst tabs = useTabsProvider();\n\treturn (\n\t\t\n\t);\n};\n\nexport const Tabs = React.memo(TabsPrimitive);\nexport default Tabs;\n","import {useCallback, useEffect, useState} from 'react';\nimport useWhenChangedEffect from '@netx/core-components/hooks/useWhenChangedEffect';\n\nexport interface UseTabsProps {\n\tafterChange?: (newIndex: number, oldIndex: number) => void;\n\t/**\n\t * Provides the ability to check the new tab index vs the current tab index\n\t * and return `false` if the switch should be ignored\n\t */\n\tbeforeChange?: (newIndex: number, currentIndex: number) => boolean | void;\n\t/**\n\t * Index to be considered `active`\\\n\t * NOTE: Changes from this will supress before/after callbacks\n\t */\n\tindex?: number;\n}\n\n/**\n * Active tab management\n * @param options \n * @example\n const handleBeforeChange = useCallback((newIndex, currentIndex) => {\n return foo !== \"bar\";\n }, [foo]);\n const tabs = useTabs({\n beforeChange: handleBeforeChange,\n });\n return (\n \n \n \n \n );\n */\nexport const useTabs = ({\n\tafterChange,\n\tbeforeChange,\n\tindex,\n}: UseTabsProps = {}) => {\n\tconst [activeTabIndex, setActiveTabIndex] = useState(index || 0);\n\n\tuseEffect(() => {\n\t\tsetActiveTabIndex(index || 0);\n\t}, [index]);\n\n\t// useWhenChangedEffect(index, setActiveTabIndex);\n\n\tconst setTab = useCallback(\n\t\t(index: number) => {\n\t\t\tsetActiveTabIndex((activeTabIndex) => {\n\t\t\t\t// If the index is the same, or the `beforeChange` callback opts to prevent\n\t\t\t\tif (\n\t\t\t\t\tactiveTabIndex === index ||\n\t\t\t\t\tbeforeChange?.(index, activeTabIndex) === false\n\t\t\t\t)\n\t\t\t\t\treturn activeTabIndex;\n\n\t\t\t\t// Notify and update\n\t\t\t\tafterChange?.(index, activeTabIndex);\n\t\t\t\treturn index;\n\t\t\t});\n\t\t},\n\t\t[afterChange, beforeChange],\n\t);\n\n\tconst handleChange = useCallback((event, index: number) => setTab(index), [\n\t\tsetTab,\n\t]);\n\n\treturn {\n\t\tactiveTabIndex,\n\t\thandleChange,\n\t\tsetTab,\n\t};\n};\n\nexport default useTabs;\n","import React, {createContext, useContext, useImperativeHandle} from 'react';\n\nimport type {ArgumentsType} from '@netx/core/typings';\nimport {useTabs} from './useTabs';\n\nexport type TabsContextType = ReturnType;\n\nexport type TabsProviderRef = React.RefObject;\n\nexport type TabsProviderChildrenProps = TabsContextType;\n\nexport const TabsContext = createContext(\n\tundefined,\n);\n\nexport const useTabsProvider = () => {\n\tconst context = useContext(TabsContext);\n\tif (context === undefined) {\n\t\tthrow new Error('`useTabsProvider` must be used within a `TabsProvider`');\n\t}\n\treturn context;\n};\n\nexport type TabsProviderProps = ArgumentsType[0] & {\n\tref?: TabsProviderRef;\n\tchildren:\n\t\t| React.ReactNode\n\t\t| ((props: TabsProviderChildrenProps) => React.ReactNode);\n};\n\nconst TabsProviderInner = (\n\t{children, ...props}: TabsProviderProps,\n\tref: TabsProviderRef,\n) => {\n\tconst tabs = useTabs(props);\n\n\tuseImperativeHandle(ref, () => tabs, [tabs]);\n\n\treturn (\n\t\t\n\t\t\t{typeof children === 'function' ? children(tabs) : children}\n\t\t\n\t);\n};\n\nexport const TabsProviderPrimitive = React.forwardRef<\n\tTabsContextType,\n\tTabsProviderProps\n>(TabsProviderInner);\n\n/**\n * Tabs context provider\n * @example\n * \n * \t...\n * \n * @example\n * \n * \t{(tabs) => (\n * \t\t...\n * \t)}\n * \n */\nexport const TabsProvider = TabsProviderPrimitive;\n\nexport default TabsProvider;\n","module.exports = function(obj){\nvar __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\nwith(obj||{}){\n__p+='\\n\\n\\n\t

\\n\t';\n\n\t// this i18n value is handled in the initialize method of assetConstituentView.js\n\t\n__p+='\\n\t
\\n\t
'+\n((__t=( title ))==null?'':__t)+\n'\\n
';\n}\nreturn __p;\n};\n","module.exports = function(obj){\nvar __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\nwith(obj||{}){\n__p+='\\n\\n\\n\t
\\n\t
\\n\t
\\n\t\t';\n if( keyframeReady ) { \n__p+='\\n\t\t\t

\\n\t\t';\n } \n__p+='\\n\t\t
\\n\t\t\t
\\n\t\t\t\t\\n\t\t\t
\\n\t\t\t
'+\n((__t=( progressMessage ))==null?'':__t)+\n'\\n\t\t
\\n\t
\\n
\\n\\n\t
\\n\t\t'+\n((__t=( title ))==null?'':__t)+\n'\\n\t
\\n\t
\\n\t\t'+\n((__t=( duration.pretty ))==null?'':__t)+\n'\\n\t
\\n
';\n}\nreturn __p;\n};\n","import NetxQueryDam, {SuccessResponse} from '@netx/core/lib/netx-query-dam';\nexport type {QueryError} from '@netx/core/lib/netx-query-dam';\n\nexport type SemanticObjectAutoListItem = {\n\tlabel: string;\n\tvalue: string; // value id\n};\n\n/**\n * `getSemanticObjectAutoList` request params\n * (what is used to send to server)\n */\nexport type GetSemanticObjectAutoListRequestOptions = {\n\tvalue: string;\n\tid: number; // TODO: semantic object id\n};\n\n/**\n * `getSemanticObjectAutoList` request\n * (what gets sent to the server)\n */\nexport type GetSemanticObjectAutoListRequest = [\n\tGetSemanticObjectAutoListRequestOptions['value'],\n\tGetSemanticObjectAutoListRequestOptions['id'],\n];\n\n/**\n * `getSemanticObjectAutoList` response\n * (what comes back from the server)\n */\nexport type GetSemanticObjectAutoListResponse = SuccessResponse<\n\tSemanticObjectAutoListItem[]\n>;\n\n/**\n * `getSemanticObjectAutoList` result\n * (what is utilized from the server response)\n */\nexport type GetSemanticObjectAutoListResult = SemanticObjectAutoListItem[];\n\nexport const getSemanticObjectAutoListEndpoint = 'getSemanticObjectAutoList';\n\n/**\n * Semantic object auto list\n */\nexport const getSemanticObjectAutoList = async ({\n\tid,\n\tvalue,\n}: GetSemanticObjectAutoListRequestOptions) => {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: GetSemanticObjectAutoListRequest = [value, id];\n\n\treturn client\n\t\t.post(\n\t\t\tgetSemanticObjectAutoListEndpoint,\n\t\t\trequestParams,\n\t\t)\n\t\t.then((response) => response.data.result);\n};\n\nexport default getSemanticObjectAutoList;\n","import NetxQueryDam, {SuccessResponse} from '@netx/core/lib/netx-query-dam';\nexport type {QueryError} from '@netx/core/lib/netx-query-dam';\n\nimport {AttributeId} from '../types';\n\n/**\n * `metadataAutoCompleteLookup` request params\n * (what is used to send to server)\n */\nexport type MetadataAutoCompleteLookupRequestOptions = {\n\tid: AttributeId;\n\tvalue: string;\n};\n\n/**\n * `metadataAutoCompleteLookup` request\n * (what gets sent to the server)\n */\nexport type MetadataAutoCompleteLookupRequest = [\n\tMetadataAutoCompleteLookupRequestOptions['id'],\n\tMetadataAutoCompleteLookupRequestOptions['value'],\n];\n\n/**\n * `metadataAutoCompleteLookup` response\n * (what comes back from the server)\n */\nexport type MetadataAutoCompleteLookupResponse = SuccessResponse<\n\tMetadataAutoCompleteLookupResult\n>;\n\n/**\n * `metadataAutoCompleteLookup` result\n * (what is utilized from the server response)\n */\nexport type MetadataAutoCompleteLookupResult = string[];\n\nexport const metadataAutoCompleteLookupEndpoint = 'metadataAutoCompleteLookup';\n\n/**\n * Metadata auto list (tags, which get the data from datasets)\n */\nexport const metadataAutoCompleteLookup = async ({\n\tid,\n\tvalue,\n}: MetadataAutoCompleteLookupRequestOptions) => {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: MetadataAutoCompleteLookupRequest = [id, value];\n\n\treturn client\n\t\t.post(\n\t\t\tmetadataAutoCompleteLookupEndpoint,\n\t\t\trequestParams,\n\t\t)\n\t\t.then((response) => response.data.result);\n};\n\nexport default metadataAutoCompleteLookup;\n","import NetxQueryDam, {SuccessResponse} from '@netx/core/lib/netx-query-dam';\nexport type {QueryError} from '@netx/core/lib/netx-query-dam';\n\nimport {AttributeId} from '../types';\n\n/**\n * `metadataDatasetAutoList` request params\n * (what is used to send to server)\n */\nexport type MetadataDatasetAutoListRequestOptions = {\n\tid: AttributeId;\n\tvalue: string;\n};\n\n/**\n * `metadataDatasetAutoList` request\n * (what gets sent to the server)\n */\nexport type MetadataDatasetAutoListRequest = [\n\tMetadataDatasetAutoListRequestOptions['id'],\n\tMetadataDatasetAutoListRequestOptions['value'],\n];\n\n/**\n * `metadataDatasetAutoList` response\n * (what comes back from the server)\n */\nexport type MetadataDatasetAutoListResponse = SuccessResponse<\n\tMetadataDatasetAutoListResult\n>;\n\n/**\n * `metadataDatasetAutoList` result\n * (what is utilized from the server response)\n */\nexport type MetadataDatasetAutoListResult = string[];\n\nexport const metadataDatasetAutoListEndpoint = 'metadataDatasetAutoList';\n\n/**\n * Metadata dataset auto list\n */\nexport const metadataDatasetAutoList = async ({\n\tid,\n\tvalue,\n}: MetadataDatasetAutoListRequestOptions) => {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: MetadataDatasetAutoListRequest = [id, value];\n\n\treturn client\n\t\t.post(\n\t\t\tmetadataDatasetAutoListEndpoint,\n\t\t\trequestParams,\n\t\t)\n\t\t.then((response) => response.data.result);\n};\n\nexport default metadataDatasetAutoList;\n","import NetxQueryDam, {SuccessResponse} from '@netx/core/lib/netx-query-dam';\nexport type {QueryError} from '@netx/core/lib/netx-query-dam';\n\nimport {AttributeId} from '../types';\n\n/**\n * `vocabularyValueLookup` request params\n * (what is used to send to server)\n */\nexport type VocabularyValueLookupRequestOptions = {\n\tid: AttributeId;\n\tvalue: string;\n};\n\n/**\n * `vocabularyValueLookup` request\n * (what gets sent to the server)\n */\nexport type VocabularyValueLookupRequest = [\n\tVocabularyValueLookupRequestOptions['id'],\n\tVocabularyValueLookupRequestOptions['value'],\n];\n\n/**\n * `vocabularyValueLookup` response\n * (what comes back from the server)\n */\nexport type VocabularyValueLookupResponse = SuccessResponse<\n\tVocabularyValueLookupResult\n>;\n\n/**\n * `vocabularyValueLookup` result\n * (what is utilized from the server response)\n */\nexport type VocabularyValueLookupResult = string[];\n\nexport const vocabularyValueLookupEndpoint = 'vocabularyValueLookup';\n\n/**\n * Vocabulary value auto list\n */\nexport const vocabularyValueLookup = async ({\n\tid,\n\tvalue,\n}: VocabularyValueLookupRequestOptions) => {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: VocabularyValueLookupRequest = [id, value];\n\n\treturn client\n\t\t.post(\n\t\t\tvocabularyValueLookupEndpoint,\n\t\t\trequestParams,\n\t\t)\n\t\t.then((response) => response.data.result);\n};\n\nexport default vocabularyValueLookup;\n","/**\n* Detect Element Resize Plugin for jQuery\n*\n* https://github.com/sdecima/javascript-detect-element-resize\n* Sebastian Decima\n*\n* version: 0.5.3\n**/\n\n+function( root, factory ) {\n\t// CommonJS\n\tif (typeof exports == \"object\") {\n\t\tmodule.exports = factory( module.exports, require('jquery') );\n\t}\n\t// Browser\n\telse {\n\t\tfactory( this, this.jQuery );\n\t}\n}( this, function ( root, $ ) {\n\t// Already on the $.fn namespace\n\tif( $.fn.resize.overriden ) {\n\t\treturn $.fn.resize;\n\t}\n\t\n\tvar attachEvent = document.attachEvent,\n\t\tstylesCreated = false;\n\t\n\tvar jQuery_resize = $.fn.resize;\n\t\n\t$.fn.resize = function(callback) {\n\t\treturn this.each(function() {\n\t\t\tif(this == window)\n\t\t\t\tjQuery_resize.call(jQuery(this), callback);\n\t\t\telse\n\t\t\t\taddResizeListener(this, callback);\n\t\t});\n\t}\n\n\t$.fn.removeResize = function(callback) {\n\t\treturn this.each(function() {\n\t\t\tremoveResizeListener(this, callback);\n\t\t});\n\t}\n\t\n\tif (!attachEvent) {\n\t\tvar requestFrame = (function(){\n\t\t\tvar raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||\n\t\t\t\t\t\t\t\tfunction(fn){ return window.setTimeout(fn, 20); };\n\t\t\treturn function(fn){ return raf(fn); };\n\t\t})();\n\t\t\n\t\tvar cancelFrame = (function(){\n\t\t\tvar cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||\n\t\t\t\t\t\t\t\t window.clearTimeout;\n\t\t return function(id){ return cancel(id); };\n\t\t})();\n\n\t\tfunction resetTriggers(element){\n\t\t\tvar triggers = element.__resizeTriggers__,\n\t\t\t\texpand = triggers.firstElementChild,\n\t\t\t\tcontract = triggers.lastElementChild,\n\t\t\t\texpandChild = expand.firstElementChild;\n\t\t\tcontract.scrollLeft = contract.scrollWidth;\n\t\t\tcontract.scrollTop = contract.scrollHeight;\n\t\t\texpandChild.style.width = expand.offsetWidth + 1 + 'px';\n\t\t\texpandChild.style.height = expand.offsetHeight + 1 + 'px';\n\t\t\texpand.scrollLeft = expand.scrollWidth;\n\t\t\texpand.scrollTop = expand.scrollHeight;\n\t\t};\n\n\t\tfunction checkTriggers(element){\n\t\t\treturn element.offsetWidth != element.__resizeLast__.width ||\n\t\t\t\t\t\t element.offsetHeight != element.__resizeLast__.height;\n\t\t}\n\t\t\n\t\tfunction scrollListener(e){\n\t\t\tvar element = this;\n\t\t\tresetTriggers(this);\n\t\t\tif (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);\n\t\t\tthis.__resizeRAF__ = requestFrame(function(){\n\t\t\t\tif (checkTriggers(element)) {\n\t\t\t\t\telement.__resizeLast__.width = element.offsetWidth;\n\t\t\t\t\telement.__resizeLast__.height = element.offsetHeight;\n\t\t\t\t\telement.__resizeListeners__.forEach(function(fn){\n\t\t\t\t\t\tfn.call(element, e);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\t/* Detect CSS Animations support to detect element display/re-attach */\n\t\tvar animation = false,\n\t\t\tanimationstring = 'animation',\n\t\t\tkeyframeprefix = '',\n\t\t\tanimationstartevent = 'animationstart',\n\t\t\tdomPrefixes = 'Webkit Moz O ms'.split(' '),\n\t\t\tstartEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),\n\t\t\tpfx = '';\n\t\t{\n\t\t\tvar elm = document.createElement('fakeelement');\n\t\t\tif( elm.style.animationName !== undefined ) { animation = true; } \n\t\t\t\n\t\t\tif( animation === false ) {\n\t\t\t\tfor( var i = 0; i < domPrefixes.length; i++ ) {\n\t\t\t\t\tif( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {\n\t\t\t\t\t\tpfx = domPrefixes[ i ];\n\t\t\t\t\t\tanimationstring = pfx + 'Animation';\n\t\t\t\t\t\tkeyframeprefix = '-' + pfx.toLowerCase() + '-';\n\t\t\t\t\t\tanimationstartevent = startEvents[ i ];\n\t\t\t\t\t\tanimation = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tvar animationName = 'resizeanim';\n\t\tvar animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';\n\t\tvar animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';\n\t}\n\t\n\tfunction createStyles() {\n\t\tif (!stylesCreated) {\n\t\t\t//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360\n\t\t\tvar css = (animationKeyframes ? animationKeyframes : '') +\n\t\t\t\t\t'.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +\n\t\t\t\t\t'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \\\" \\\"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',\n\t\t\t\thead = document.head || document.getElementsByTagName('head')[0],\n\t\t\t\tstyle = document.createElement('style');\n\t\t\t\n\t\t\tstyle.type = 'text/css';\n\t\t\tif (style.styleSheet) {\n\t\t\t\tstyle.styleSheet.cssText = css;\n\t\t\t} else {\n\t\t\t\tstyle.appendChild(document.createTextNode(css));\n\t\t\t}\n\n\t\t\thead.appendChild(style);\n\t\t\tstylesCreated = true;\n\t\t}\n\t}\n\t\n\twindow.addResizeListener = function(element, fn){\n\t\tif (attachEvent) element.attachEvent('onresize', fn);\n\t\telse {\n\t\t\tif (!element.__resizeTriggers__) {\n\t\t\t\tif (getComputedStyle(element).position == 'static') element.style.position = 'relative';\n\t\t\t\tcreateStyles();\n\t\t\t\telement.__resizeLast__ = {};\n\t\t\t\telement.__resizeListeners__ = [];\n\t\t\t\t(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';\n\t\t\t\telement.__resizeTriggers__.innerHTML = '' +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'';\n\t\t\t\telement.appendChild(element.__resizeTriggers__);\n\t\t\t\tresetTriggers(element);\n\t\t\t\telement.addEventListener('scroll', scrollListener, true);\n\t\t\t\t\n\t\t\t\t/* Listen for a css animation to detect element display/re-attach */\n\t\t\t\tanimationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {\n\t\t\t\t\tif(e.animationName == animationName)\n\t\t\t\t\t\tresetTriggers(element);\n\t\t\t\t});\n\t\t\t}\n\t\t\telement.__resizeListeners__.push(fn);\n\t\t}\n\t};\n\t\n\twindow.removeResizeListener = function(element, fn){\n\t\tif (attachEvent) element.detachEvent('onresize', fn);\n\t\telse {\n\t\t\telement.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);\n\t\t\tif (!element.__resizeListeners__.length) {\n\t\t\t\ttry {\n\t\t\t\t\telement.removeEventListener('scroll', scrollListener, true);\n\t\t\t\t\telement.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);\n\t\t\t\t}\n\t\t\t\tcatch( e ) {\n\t\t\t\t\t// If you hit this error then most likely the element was removed from the DOM prior to calling removeResizeListener\n\t\t\t\t\t// And you are probably in IE\n\t\t\t\t\t// console.log( e );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// jQuery already has a $.fn.resize\n\t$.fn.resize.overriden = true;\n\t\n\treturn $.fn.resize;\n} );","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const ACTION_MENU_CLASS_NAME = 'ActionMenu';\nexport const ACTION_MENU_CLASS_SLOTS = ['root', 'skeleton'] as const;\n\nexport type ActionMenuClassSlot = typeof ACTION_MENU_CLASS_SLOTS[number];\n\nexport interface ActionMenuClasses {\n\troot: string;\n\tskeleton: string;\n\tfab: string;\n\ticon: string;\n}\n\nexport type ActionMenuClassKey = keyof ActionMenuClasses;\n\nexport const getActionMenuUtilityClass = (slot: ActionMenuClassSlot) =>\n\tgenerateUtilityClass(ACTION_MENU_CLASS_NAME, slot);\n\nexport const actionMenuClasses = generateUtilityClasses<\n\tkeyof ActionMenuClasses\n>(ACTION_MENU_CLASS_NAME, ['root', 'skeleton', 'fab', 'icon']);\nexport default actionMenuClasses;\n","// TODO: There is a way to combine this with the header action component\n// I just need a little more time\nimport React, {useCallback, useEffect, useState} from 'react';\nimport clsx from 'clsx';\nimport {i18n} from '@netx/core/i18n';\n\nimport {faEllipsisV as EllipsisIcon} from '@fortawesome/pro-solid-svg-icons';\nimport {\n\tMenu as MuiMenu,\n\tMenuProps as MuiMenuProps,\n\tPopoverProps,\n\tSkeleton,\n\tSkeletonProps,\n\tDivider,\n} from '@mui/material';\nimport type {ReactAction} from '@netx/core/bootstrap';\nimport {\n\tcomposeClasses,\n\tstyled,\n\tWithClasses,\n\tWithMuiPropOverrides,\n} from '@netx/core-components/Theme';\nimport ActionButton, {ActionButtonProps} from '../ActionButton';\nimport MenuItem from '../MenuItem';\nimport {\n\tactionMenuClasses,\n\tgetActionMenuUtilityClass,\n\tActionMenuClasses,\n\tACTION_MENU_CLASS_NAME,\n} from './actionMenuClasses';\n\nexport type ActionMenuOwnerState = WithClasses<\n\tActionMenuClasses,\n\t{\n\t\tbuttonVariant: 'fab' | 'icon';\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: ActionMenuOwnerState) => {\n\tconst {buttonVariant, classes} = ownerState;\n\tconst slots = {\n\t\troot: ['root'],\n\t\tskeleton: ['skeleton', buttonVariant],\n\t};\n\treturn composeClasses(slots, getActionMenuUtilityClass, classes);\n};\n\nconst ActionMenuSkeleton = styled(Skeleton, {\n\tname: ACTION_MENU_CLASS_NAME,\n\tslot: 'Skeleton',\n})(({theme}) => ({\n\t[`&.${actionMenuClasses.fab}`]: {\n\t\theight: 56,\n\t\twidth: 56,\n\t},\n\t[`&.${actionMenuClasses.icon}`]: {\n\t\theight: 42,\n\t\twidth: 42,\n\t},\n}));\n\nexport interface ActionMenuProps\n\textends Partial>>,\n\t\tWithClasses {\n\tactions: Array;\n\tbuttonVariant?: 'fab' | 'icon';\n\talwaysUseEllipsis?: boolean;\n\tdisabled?: boolean;\n\tloading?: boolean;\n\ttitle?: string;\n\tActionButtonProps?: Partial;\n\tSkeletonProps?: Partial;\n\tonAction?: (action: ReactAction) => void;\n\tonClick?: () => void;\n}\n\nconst onActionDefault = (action: ReactAction) => action?.cb();\n\nconst ActionMenu = React.forwardRef(\n\t(\n\t\t{\n\t\t\tclasses: _classes,\n\t\t\tclassName,\n\t\t\tactions,\n\t\t\talwaysUseEllipsis,\n\t\t\tbuttonVariant = 'icon',\n\t\t\tdisabled,\n\t\t\tloading,\n\t\t\ttabIndex,\n\t\t\ttitle,\n\t\t\tActionButtonProps,\n\t\t\tonAction = onActionDefault,\n\t\t\tonClose,\n\t\t\tonClick,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst [anchorEl, setAnchorEl] = useState();\n\t\tconst [open, setOpen] = useState(false);\n\n\t\tconst ownerState: ActionMenuOwnerState = {\n\t\t\tbuttonVariant,\n\t\t};\n\t\tconst classes = useUtilityClasses(ownerState);\n\n\t\tuseEffect(() => {\n\t\t\treturn () => {\n\t\t\t\tonClose?.({}, '' as any);\n\t\t\t};\n\t\t}, [onClose]);\n\n\t\tconst handleClose = useCallback['onClose']>(\n\t\t\t(event: React.MouseEvent, reason) => {\n\t\t\t\tevent.persist();\n\t\t\t\tevent.stopPropagation();\n\n\t\t\t\tsetOpen(false);\n\t\t\t\tonClose?.(event, reason);\n\t\t\t},\n\t\t\t[onClose],\n\t\t);\n\n\t\t/** Menu exited */\n\t\tconst handleExited = useCallback(\n\t\t\t(node) => {\n\t\t\t\tsetAnchorEl(undefined);\n\t\t\t\tprops.TransitionProps?.onExited?.(node);\n\t\t\t},\n\t\t\t[props.TransitionProps?.onExited],\n\t\t);\n\n\t\tconst handleShowClick = useCallback(\n\t\t\t(event: React.MouseEvent) => {\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tonClick?.();\n\n\t\t\t\tsetAnchorEl(event.currentTarget);\n\t\t\t\tsetOpen(true);\n\t\t\t},\n\t\t\t[onClick],\n\t\t);\n\n\t\tconst handleActionClick = useCallback(\n\t\t\t(action: ReactAction) =>\n\t\t\t\t(\n\t\t\t\t\tevent: React.MouseEvent<\n\t\t\t\t\t\tHTMLAnchorElement | HTMLLIElement,\n\t\t\t\t\t\tMouseEvent\n\t\t\t\t\t>,\n\t\t\t\t) => {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t\tonAction(action);\n\t\t\t\t\tonClose?.(event, 'escapeKeyDown');\n\t\t\t\t},\n\t\t\t[onAction],\n\t\t);\n\n\t\tconst buttonTitle = title != null ? title : i18n.t('i18n.openMenu');\n\n\t\tif (!actions.length) return null;\n\t\t// TODO: we should just be doing this - need to see if anything is relying on us doing it the hard way below\n\t\t// if (loading) return \n\n\t\t// Just show the single action as an icon button\n\t\tif (\n\t\t\t!loading &&\n\t\t\t!alwaysUseEllipsis &&\n\t\t\tactions.length === 1 &&\n\t\t\t!Array.isArray(actions[0])\n\t\t) {\n\t\t\tconst action = actions[0];\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t\n\t\t\t\t>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{loading ? (\n\t\t\t\t\t\n\t\t\t\t) : (\n\t\t\t\t\t\n\t\t\t\t)}\n\t\t\t\t{anchorEl ? (\n\t\t\t\t\t {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tTransitionProps={{\n\t\t\t\t\t\t\t...props.TransitionProps,\n\t\t\t\t\t\t\tonExited: handleExited,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{actions.map((action, index) => {\n\t\t\t\t\t\t\tif (Array.isArray(action))\n\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\tindex > 0 ? : null,\n\t\t\t\t\t\t\t\t\t...action.map((action) => (\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t)),\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\n\t\t\t\t) : null}\n\t\t\t>\n\t\t);\n\t},\n);\n\nexport default ActionMenu;\n","import {ContextMenuServiceProvider} from './ContextMenuService';\nexport * from './ContextMenuService';\nexport * from './ContextMenu';\nexport default ContextMenuServiceProvider;\n\nexport * from './withContextMenu';\n","import {status as assetStatuses} from './properties/asset';\nimport AssetModel from './models/asset';\nimport {getViewCollection, getViewModel} from '@netx/core/lib/utils';\nimport {isMobile} from '@netx/core/lib/underscore-netx';\n\nimport Netx from '@netx/core/bootstrap';\n\n/**\n * @method\n * @return {boolean}\n */\nexport const assetCanRepurpose = (v) => {\n\t// DAM-13617\n\tif (isMobile()) return false;\n\n\tconst model = getViewModel(v);\n\n\t// Once the property repurposeAvailability is considering\n\t// the availability of the engines required to repurpose\n\t// an asset ( https://jira.netx.net/browse/DAM-4564 ) we\n\t// can rely more heavily on `repurposeAvailability` until\n\t// that time... ~SAK\n\t// Vars\n\tvar supported, viewNames;\n\n\t// var manualUserLevel = Netx.getPreference('sys.minUserLevelForManualRepurpose') || 0,\n\t// canManuallyRepurpose = Netx.getUserLevel() >= manualUserLevel;\n\n\tif (model) {\n\t\tviewNames = model.get('viewNames');\n\t\t// Video\n\t\tif (_.indexOf(viewNames, 'previewH264') > -1) {\n\t\t\tsupported = true;\n\t\t}\n\t\t// Document\n\t\telse if (_.indexOf(viewNames, 'previewPDF') > -1) {\n\t\t\t// Not supported\n\t\t}\n\t\t// Audio\n\t\telse if (_.indexOf(viewNames, 'previewMp3') > -1) {\n\t\t\tsupported = true;\n\t\t}\n\t\t// Image\n\t\telse if (_.indexOf(v.model.get('fileFormatFamily'), 'image') > -1) {\n\t\t\tsupported = true;\n\t\t}\n\t\t// We don't know what it is\n\t\telse {\n\t\t\tsupported = false;\n\t\t}\n\t}\n\treturn (\n\t\tsupported && assetIsPresent(v) && v.model.get('repurposeAvailability') > 0\n\t);\n};\n\n/**\n * Can asset be part of a review\n * @method\n * @return {boolean}\n */\nexport const assetCanReview = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && model.hasFormatFamily('image');\n};\n\n/**\n * Is asset expiration enabled\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetExpirationEnabled = (v) => {\n\treturn Netx.getPreference('asset.expire.enabled', true);\n};\n\n/**\n * Is asset set to expire\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetExpires = (v) => {\n\tconst model = getViewModel(v);\n\n\tif (!model) return false;\n\n\t// Verify we have a timestamp\n\tvar expirationDate = parseInt(model.get('expirationDate'));\n\tif (!expirationDate || isNaN(expirationDate)) return false;\n\n\t// Make into date\n\texpirationDate = new Date(expirationDate);\n\treturn (\n\t\tNetx.getPreference('asset.expire.enabled', true) &&\n\t\t!isNaN(expirationDate.getTime())\n\t);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasConstituents_clips = (v) => {\n\tconst model = getViewModel(v);\n\treturn (\n\t\tmodel &&\n\t\tNetx.getPreference('asset.constituent.videoClips.enabled', true) &&\n\t\t_.indexOf(model.get('fileFormatFamily'), 'video') > -1\n\t);\n};\n\nexport const assetHasClips = assetHasConstituents_clips;\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasConstituents_keyframes = (v) => {\n\tconst model = getViewModel(v);\n\treturn (\n\t\tmodel &&\n\t\tmodel.get('constituentType') === 'time' &&\n\t\t_.size(model.get('constituentIds'))\n\t);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasConstituents_layers = (v) => {\n\tconst model = getViewModel(v);\n\treturn (\n\t\tmodel &&\n\t\tmodel.get('constituentType') === 'layer' &&\n\t\t_.size(model.get('constituentIds'))\n\t);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasConstituents_pages = (v) => {\n\tconst model = getViewModel(v);\n\treturn (\n\t\tmodel &&\n\t\tmodel.get('constituentType') === 'page' &&\n\t\t_.size(model.get('constituentIds'))\n\t);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasDetail = (v) => {\n\treturn true;\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasLinks = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && model.get('relatedAvailable');\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasMetadata = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && model.get('metadataAvailable');\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasPreview = (v) => {\n\treturn true;\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasProjects = (v) => {\n\t// TODO: have the asset marked with a boolean as well\n\treturn Netx.getPreference('review.enabled', true);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasReviews = (v) => {\n\tconst canReview = assetCanReview(v);\n\t// TODO: have the asset marked with a boolean as well\n\treturn canReview && Netx.getPreference('review.enabled', true);\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasVersions = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && _.size(model.get('versionIds'));\n};\n\n/**\n * For react (non action enabler)\n */\nexport const assetIsEditable = (assetData) => {\n\tconst model = new AssetModel(assetData);\n\tconst canEdit = model.allows('modify');\n\tmodel.garbageCollect();\n\treturn canEdit;\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetHasViews = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && _.size(model.get('viewIds'));\n};\n\n/**\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetIsImage = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && _.indexOf(v.model.get('fileFormatFamily'), 'image') > -1;\n};\n\n/**\n * Asset status is set to 1\n * @param {Backbone.View} v Backbone view\n * @return {boolean}\n */\nexport const assetIsOnline = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model) return false;\n\tvar stat = model.get('status');\n\treturn stat === assetStatuses.ONLINE;\n};\n\n/**\n * This test is cribbed from Flex: it checks the asset.status value to make sure the asset file is actually available on the DAM.\n * @method\n * @param {Netx.View} v Instance of Netx View\n * @returns {boolean}\n */\nexport const assetIsPresent = (v) => {\n\tconst model = getViewModel(v);\n\n\tif (!model) return false;\n\tvar stat = model.get('status');\n\treturn (\n\t\tstat === assetStatuses.ONLINE ||\n\t\tstat === assetStatuses.TEMP ||\n\t\tstat === assetStatuses.NEARLINE\n\t);\n};\n\n/**\n * Asset locked\n * @method\n * @returns {boolean}\n */\nexport const assetLocked = (v) => {\n\tconst model = getViewModel(v);\n\treturn model.get('readOnly') === 1;\n};\n\n/**\n * @method\n * @returns {boolean}\n */\nexport const assetNotCheckedOut = (v) => {\n\tconst collection = getViewCollection(v);\n\tconst model = getViewModel(v);\n\tvar status;\n\tif (model && model.has('status')) {\n\t\t// check for model\n\t\tstatus = model.get('status');\n\t} else if (\n\t\tcollection &&\n\t\tcollection.length &&\n\t\tcollection.at(0).has('status')\n\t) {\n\t\t// check for first model in collection\n\t\tstatus = collection.at(0).get('status');\n\t} else {\n\t\t// Sometimes we hit this test before the collection on the view in question has any assets\n\t\t// I have provided the view in question with the console warn - in the case of DAM-8288 it is assetListView\n\t\t// and yes, the collection is not ready quite yet. The real thing is what is assetListView doing on an action\n\t\t// requestion this test in the first place\n\t\t// Something must be testing on sync before data is actually available(?)\n\t\t// Perhaps a reset is happening prior to setting data?\n\t\t// It is more than likely coming from the `share:asset:menu` or `share:asset:download` action\n\t\t// Can't imagine it is coming from the `asset:checkout` action\n\t\t// In any case there is no need to blow up the app over it\n\n\t\t// UPDATE: spotted in the wild ... a reset is indeed happening:\n\t\t// user clicks on a category, routing to #category/:id\n\t\t// #category/:id handler triggers category:routed,\n\t\t// category:routed triggers category:current:update,\n\t\t// category:current:update calls Netx.category.current.set(data) to update the ID ... **\n\t\t// change listener on categoryID calls Netx.category.current.fetch() to fetch category ...\n\t\t// a weird fetch wrapper in category.js triggers a fake 'sync' event, **\n\t\t// a sync listener on Netx.category.current triggers category:getAssets,\n\t\t// triggering Netx.category.assets.getCategoryAssets(),\n\t\t// which is a weird wrapper method that sets its own .selection object before fetching ... **\n\t\t// Netx.category.assets has a change listener on its .selection object to !!! call .reset() before a fetch !!! **\n\t\t// and that 'reset' event triggers .configureSyncActions() in the Netx.View actions code **\n\t\t// ... which triggers this enabler at a moment when v.collection.length is certain to be 0.\n\t\t//\n\t\t// Out of all that, at least the lines ending in ** are suspect. Possibly this will work\n\t\t// better as we start to untangle the spagetting of method wrapers & bad RPC method patterns.\n\t\t// (And I don't get why we need to reset categoryAssets before fetching ... the code says\n\t\t// it makes something faster, but we should revisit that.)\n\t\t//\n\t\t// On the other hand, there's no need to issue this warning when we have a collection without assets in it.\n\t\t// Simply disabling the action in that case seems sensible.\n\t\tif (collection && collection.length == 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Other than that, I'm not sure this ever happens -- but let's be warned if it does.\n\t\telse {\n\t\t\t// console.warn('tried to test asset checkout status on non-asset', v.template);\n\t\t\t// Just make the assumption it is checked out... because... well, logic is flawed somewhere and saying it is checked out\n\t\t\t// in this odd case won't hurt anyone\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn status !== assetStatuses.CHECKOUT;\n};\n\n/**\n * Check that asset isn't pending\n * @method\n * @return {boolean}\n */\nexport const assetNotPending = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && _.isUndefined(Netx.asset.pending.get(model.id));\n};\n\n/**\n * Are assets requests enabled?\n * @method\n * @return {boolean}\n */\nexport const assetRequestsEnabled = (v) => {\n\treturn Netx.getPreference('asset.assetRequestEnabled', true);\n};\n\n/**\n * Asset unlocked\n * @method\n * @returns {boolean}\n */\nexport const assetUnlocked = (v) => {\n\tconst model = getViewModel(v);\n\treturn model && model.get('readOnly') === 0;\n};\n\n/**\n * @method\n * @returns {boolean}\n */\nexport const canCheckIn = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model) return false;\n\n\tconst checkedOutBy = model.get('checkout');\n\tif (\n\t\tcheckedOutBy &&\n\t\tNetx.getUserLevel() < 9 &&\n\t\tcheckedOutBy !== Netx.getUser().id\n\t)\n\t\treturn false;\n\n\tconst status = model.get('status');\n\t// https://jira.netx.net/browse/DAM-13370\n\treturn (\n\t\tstatus === assetStatuses.NEARLINE ||\n\t\tstatus === assetStatuses.ONLINE ||\n\t\tstatus === assetStatuses.TEMP ||\n\t\tstatus === assetStatuses.CHECKOUT\n\t);\n};\n\n/**\n * @method\n * @returns {boolean}\n */\nexport const canCheckOut = (v) => {\n\tconst model = getViewModel(v);\n\tvar status = model.get('status');\n\n\treturn (\n\t\tassetNotCheckedOut(v) &&\n\t\t// https://jira.netx.net/browse/DAM-13370\n\t\t(status === assetStatuses.NEARLINE ||\n\t\t\tstatus === assetStatuses.ONLINE ||\n\t\t\tstatus === assetStatuses.TEMP)\n\t);\n};\n\n/**\n * Can delete attribute\n * @param {Backbone.View} v Backbone view\n * @return {boolean}\n */\nexport const canDeleteAttribute = (v) => {\n\t// Currently there is nothing to test since `asset.moveDescriptionToAttrTab` went away\n\treturn true;\n};\n\n/**\n * Can we download a version\n * @method\n * @return {boolean}\n */\nexport const canDownloadVersion = (v) => {\n\t// For now we must assume that we are dealing with the current asset\n\treturn Netx.asset.current.allows('download');\n};\n\n/**\n * Can edit attribute\n * @param {Backbone.View} v Backbone view\n * @return {boolean}\n */\nexport const canEditAttribute = (v) => {\n\t// Currently there is nothing to test since `asset.moveDescriptionToAttrTab` went away\n\treturn true;\n};\n\n/**\n * Can expire asset\n * @method\n * @returns {boolean}\n */\nexport const canExpire = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model) return false;\n\n\treturn (\n\t\tassetExpirationEnabled(v) &&\n\t\tNetx.getUserLevel() >= 7 &&\n\t\tmodel.allows('delete')\n\t);\n};\n\n/**\n * Can lock asset\n * @method\n * @returns {boolean}\n */\nexport const canLock = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model || !model.allows || !model.allows('modify')) return false;\n\n\treturn model && model.get('readOnly') !== 1 && Netx.getUserLevel() >= 9;\n};\n\n/**\n * Can manage versions\n * @method\n * @return {boolean}\n */\nexport const canManageVersions = (v) => {\n\t// For now we must assume that we are dealing with the current asset\n\t// we can not manage versions if the asset cannot be checked out\n\treturn (\n\t\tNetx.asset.current.allows('modify') &&\n\t\tcanCheckOut({model: Netx.asset.current})\n\t);\n};\n\n/**\n * Can an asset be removed from a category - an asset must belong to at least one category\n * If an asset does not have more than one category, it may not be removed.\n * This does not check permissions - for that use `module:core/lib/netx-enablers#categoryAndAssetCanEdit`\n * This just tests that an asset can be removed from a category (assuming permissions are good)\n * @param {Backbone.View} v Backbone view\n * @return {boolean}\n */\nexport const canRemoveAssetFromCategory = (v) => {\n\tconst model = getViewModel(v);\n\t// Where model is an asset category from an asset category list\n\tvar asset = model && model.get('asset');\n\treturn ((asset && asset.get('categories')) || []).length > 1;\n};\n\n/**\n * Can unlock asset\n * @method\n * @returns {boolean}\n */\nexport const canUnlock = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model) return false;\n\n\treturn model && model.get('readOnly') === 1 && Netx.getUserLevel() >= 9;\n};\n\n/**\n * @method\n * @returns {boolean}\n */\nexport const canZoomAsset = (v) => {\n\tconst model = getViewModel(v);\n\treturn (\n\t\tmodel &&\n\t\tassetIsPresent(v) &&\n\t\tmodel.get('zoomAvailable') &&\n\t\t// HACKaround for HTML-868:\n\t\tmodel.get('filewidth') > 0 &&\n\t\tmodel.get('fileheight') > 0\n\t);\n};\n\nexport const checksumEnabled = (v) => {\n\treturn Netx.getPreference('metadata.checksumEnabled', true);\n};\n\n/**\n * Can we use semantic metadata\n * @method\n */\nexport const semanticsEnabled = (v) => {\n\treturn Netx.getPreference('metadata.semantic.enabled', true);\n};\n\n/**\n * Can unexpire asset\n * @method\n * @returns {boolean}\n */\nexport const canUnexpire = (v) => {\n\tconst model = getViewModel(v);\n\tif (!model) return false;\n\n\tif (!assetExpires(v)) return false;\n\n\treturn Netx.getUserLevel() >= 7 && model.allows('delete');\n};\n","import {SearchTypeAdvancedRaw} from './advancedRaw/constants';\nimport {SearchTypeAttributeHistory} from './attributeHistory/constants';\nimport {SearchTypeCart} from './cart/constants';\nimport {SearchTypeCategoryId} from './categoryId/constants';\nimport {SearchTypeCheckouts} from './checkouts/constants';\nimport {SearchTypeContents} from './contents/constants';\nimport {SearchTypeDate} from './date/constants';\nimport {SearchTypeExpiration} from './expiration/constants';\nimport {SearchTypeFileAspect} from './fileAspect/constants';\nimport {SearchTypeFileFormat} from './fileFormat/constants';\nimport {SearchTypeFileFormatFamily} from './fileFormatFamily/constants';\nimport {SearchTypeFileSize} from './fileSize/constants';\nimport {SearchTypeKeyword} from './keyword/constants';\nimport {SearchTypeMetadata} from './metadata/constants';\nimport {SearchTypeSavedSearch} from './savedSearch/constants';\nimport {SearchTypeUser} from './user/constants';\nimport {SearchTypeVisual} from './visual/constants';\n\nexport enum SearchType {\n\tACTIVE_TEMPLATES = 28 as const,\n\tADVANCED_RAW = SearchTypeAdvancedRaw,\n\tATTRIBUTE_HISTORY = SearchTypeAttributeHistory,\n\tBRANCH_CHILDREN = 15 as const,\n\tCART = SearchTypeCart,\n\tCATEGORY_ID = SearchTypeCategoryId,\n\t/** not used - see CATEGORY_ID */\n\tCATEGORY_NAME = 5 as const,\n\tCHECKOUTS = SearchTypeCheckouts,\n\tCONTENTS = SearchTypeContents,\n\tCUSTOM = 9 as const,\n\tDATE = SearchTypeDate,\n\tEXPIRE = SearchTypeExpiration,\n\tFILE_ASPECT = SearchTypeFileAspect,\n\tFILE_FORMAT = SearchTypeFileFormat,\n\tFILE_FORMAT_FAMILY = SearchTypeFileFormatFamily,\n\tFILE_SIZE = SearchTypeFileSize,\n\tFILE_STATUS = 25 as const,\n\tKEYWORD = SearchTypeKeyword,\n\tLAST_SEARCH = 12 as const,\n\tLOCATION = 20 as const,\n\tMETADATA = SearchTypeMetadata,\n\tMETADATA_HISTORY = 18 as const,\n\tPROOF = 21 as const,\n\tRATING = 19 as const,\n\tRELATED_ASSETS = 11 as const,\n\tREVIEWS = 16 as const,\n\tSAVED_SEARCH = SearchTypeSavedSearch,\n\t/** no longer a thing really but still there */\n\tTHESAURUS = 14 as const,\n\tUSER = SearchTypeUser,\n\tVISUAL = SearchTypeVisual,\n}\n\nexport const EditableRuleTypes = [\n\tSearchType.ADVANCED_RAW,\n\tSearchType.CATEGORY_ID,\n\tSearchType.CHECKOUTS,\n\tSearchType.CONTENTS,\n\tSearchType.DATE,\n\tSearchType.FILE_ASPECT,\n\tSearchType.FILE_FORMAT,\n\tSearchType.FILE_FORMAT_FAMILY,\n\tSearchType.FILE_SIZE,\n\tSearchType.KEYWORD,\n\tSearchType.METADATA,\n\tSearchType.USER,\n\tSearchType.VISUAL,\n];\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const MENU_ITEM_CLASS_NAME = 'MenuItem';\n\nexport const MENU_ITEM_CLASS_SLOTS = ['root', 'icon'] as const;\n\nexport type MenuItemClassSlot = typeof MENU_ITEM_CLASS_SLOTS[number];\n\nexport interface MenuItemClasses {\n\troot: string;\n\ticon: string;\n\tseverityDefault: string;\n\tseverityError: string;\n}\n\nexport type MenuItemClassKey = keyof MenuItemClasses;\n\nexport const getMenuItemUtilityClass = (slot: MenuItemClassSlot) =>\n\tgenerateUtilityClass(MENU_ITEM_CLASS_NAME, slot);\n\nexport const menuItemClasses: MenuItemClasses = generateUtilityClasses(\n\tMENU_ITEM_CLASS_NAME,\n\t['root', 'icon', 'severityError', 'severityDefault'],\n);\n\nexport default menuItemClasses;\n","import React from 'react';\nimport clsx from 'clsx';\n\nimport {FontAwesomeIcon} from '@fortawesome/react-fontawesome';\nimport {IconProp} from '@fortawesome/fontawesome-svg-core';\nimport {\n\tListItemIcon,\n\tListItemText,\n\tMenuItem as MuiMenuItem,\n\tMenuItemProps as MuiMenuItemProps,\n} from '@mui/material';\nimport {unstable_capitalize} from '@mui/utils';\nimport {ColoredAvatar} from '@netx/core-components/ColoredAvatar';\nimport {\n\tcomposeClasses,\n\tstyled,\n\tWithClasses,\n\tWithMuiPropOverrides,\n} from '@netx/core-components/Theme';\nimport {\n\tmenuItemClasses,\n\tgetMenuItemUtilityClass,\n\tMenuItemClasses,\n\tMENU_ITEM_CLASS_NAME,\n} from './menuItemClasses';\n\ntype MenuItemUtiltiyClassProps = WithClasses<\n\tMenuItemClasses,\n\t{\n\t\tseverity: 'default' | 'error';\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: MenuItemUtiltiyClassProps) => {\n\tconst {classes, severity} = ownerState;\n\tconst slots = {\n\t\troot: ['root', severity && `severity${unstable_capitalize(severity)}`],\n\t\ticon: ['icon'],\n\t};\n\treturn composeClasses(slots, getMenuItemUtilityClass, classes);\n};\n\nconst MenuItemRoot = styled(MuiMenuItem, {\n\tname: MENU_ITEM_CLASS_NAME,\n\tslot: 'Root',\n})(({theme}) => ({\n\t[`&.${menuItemClasses.severityError}`]: {\n\t\tbackground: theme.palette.error.main,\n\t\t[`&, & .${menuItemClasses.icon}`]: {\n\t\t\tcolor: theme.palette.error.contrastText,\n\t\t},\n\t\t'&:hover, &:active, &:focus': {\n\t\t\tbackground: theme.palette.error.dark,\n\t\t},\n\t},\n}));\n\nconst MenuItemIcon = styled(ListItemIcon, {\n\tname: MENU_ITEM_CLASS_NAME,\n\tslot: 'Icon',\n})(({theme}) => ({\n\t// TODO: this is repeated in multiple places\n\t// need to see about getting it under one roof - possibly under the overrides in mui theme file\n\t// It is just too darn wide\n\tminWidth: 42,\n}));\n\nconst MenuItemColorAvatar = styled(ColoredAvatar)(({theme}) => ({\n\theight: 20,\n\twidth: 20,\n\tfontSize: 12,\n\tmarginRight: theme.spacing(2),\n}));\n\nexport interface MenuItemProps\n\textends Omit>, 'classes'>,\n\t\tWithClasses<\n\t\t\tMenuItemClasses,\n\t\t\t{\n\t\t\t\tcolorAvatar?: boolean;\n\t\t\t\ticon?: IconProp;\n\t\t\t\tsecondaryText?: string;\n\t\t\t\tseverity?: 'default' | 'error';\n\t\t\t\ttext: string;\n\t\t\t}\n\t\t> {}\n\nexport const MenuItemPrimitive = React.forwardRef(\n\t(\n\t\t{\n\t\t\tclasses: _classes,\n\t\t\tclassName,\n\t\t\tcolorAvatar,\n\t\t\ticon,\n\t\t\tsecondaryText,\n\t\t\tseverity = 'default',\n\t\t\ttext,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst classes = useUtilityClasses({classes: _classes, severity});\n\n\t\treturn (\n\t\t\t\n\t\t\t\t{icon ? (\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t) : colorAvatar ? (\n\t\t\t\t\t\n\t\t\t\t) : null}\n\t\t\t\t\n\t\t\t\n\t\t);\n\t},\n);\n\nexport const MenuItem = MenuItemPrimitive;\n\nexport default MenuItem;\n","import {AttributeAction, AttributeValue} from '../types';\nimport {ATTRIBUTE_ACTION} from '../constants';\n\nimport {isEmptyValue, valuesMatch} from '@netx/core-components/Form/util';\n\n/**\n * Does the applied action change the attributes value\n */\nexport const actionChangesValue = (\n\tcurrentValue: AttributeValue,\n\toriginalValue: AttributeValue,\n\taction: AttributeAction,\n) => {\n\treturn (\n\t\taction === ATTRIBUTE_ACTION.CLEAR ||\n\t\t([ATTRIBUTE_ACTION.APPEND, ATTRIBUTE_ACTION.REMOVE].includes(\n\t\t\taction as any,\n\t\t) &&\n\t\t\t!isEmptyValue(currentValue) &&\n\t\t\t!valuesMatch(currentValue, originalValue))\n\t);\n};\n\nexport default actionChangesValue;\n","import {\n\tDateAttribute,\n\tMultiSelectAttribute,\n\tNumberAttribute,\n\tSelectAttribute,\n\tSemanticAttribute,\n\tTagAttribute,\n\tTagVocabAttribute,\n\tTextAttribute,\n} from '../components/EditableAttribute';\n\nimport {AttributeType} from '../types';\n\n/** Given an attribute type, will return the attribute component */\nexport const getAttributeComponent = (type: AttributeType) => {\n\tswitch (type) {\n\t\tcase 1:\n\t\tcase 2: // Textarea\n\t\t\treturn TextAttribute;\n\t\tcase 3:\n\t\t\treturn SelectAttribute;\n\t\tcase 4:\n\t\t\treturn DateAttribute;\n\t\tcase 5:\n\t\t\treturn MultiSelectAttribute;\n\t\tcase 6:\n\t\t\treturn TagAttribute;\n\t\tcase 7:\n\t\t\treturn NumberAttribute;\n\t\tcase 12:\n\t\t\treturn SemanticAttribute;\n\t\tcase 13:\n\t\t\treturn TagVocabAttribute;\n\t}\n};\n\nexport default getAttributeComponent;\n","import type {AttributeTemplate, AttributesWorking} from '../types';\n\n/**\n * Get attribute templates that will be effected by a lookup\n * @param attributeTemplate The attribute template being lookup up from\n * @param attributeTemplates The attribute templates that could be involved\n * @return Attribute templates effected\n */\nexport const getTemplatesEffectedByLookup = (\n\tattributeTemplate: AttributeTemplate,\n\tattributeTemplates: AttributeTemplate[],\n) => {\n\treturn attributeTemplate.keyDatasets.reduce(\n\t\t(attributesWorking, id) => {\n\t\t\treturn {\n\t\t\t\t...attributesWorking,\n\t\t\t\t...attributeTemplates.reduce(\n\t\t\t\t\t(attributesWorking, attr) => {\n\t\t\t\t\t\tif (!attr.targetDatasets.includes(id)) return attributesWorking;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...attributesWorking,\n\t\t\t\t\t\t\t[attr.attributeid]: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t// the template passed in will be considered part of this\n\t\t\t[attributeTemplate.attributeid]: true,\n\t\t},\n\t);\n};\n\nexport default getTemplatesEffectedByLookup;\n","export const isSystemAttribute = (id: number) => {\n\treturn id < 0;\n};\n\nexport default isSystemAttribute;\n","import {isEmptyValue} from '@netx/core-components/Form/util';\nimport {AttributeValue} from '../types';\n\n/**\n * Normalize attribute value to array\\\n * In a lot of cases saving attribute values to the server, it wants an array\n * regardless of the multi-value ability of an attribute template type\\\n */\nexport const normalizeValue = (value: AttributeValue) => {\n\tif (isEmptyValue(value)) return [];\n\tif (!Array.isArray(value)) return [value];\n\treturn value;\n};\n\nexport default normalizeValue;\n","import type {PermissionMatrix} from '../types';\nimport {PERMISSION_MATRIX_NAMES, PermissionMatrixName} from '../constants';\n\nexport {PermissionMatrixName} from '../constants';\n\nexport const allows = (\n\tpermissionMatrix: PermissionMatrix,\n\tperm?: PermissionMatrixName | null,\n) => {\n\tif (perm == null) return false;\n\tconst matrixIndex = PERMISSION_MATRIX_NAMES.indexOf(perm);\n\treturn permissionMatrix[matrixIndex] === 1;\n};\n\nexport default allows;\n","import arrayWithHoles from \"./arrayWithHoles.js\";\nimport iterableToArrayLimit from \"./iterableToArrayLimit.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableRest from \"./nonIterableRest.js\";\nexport default function _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || unsupportedIterableToArray(arr, i) || nonIterableRest();\n}","export default function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}","export default function _iterableToArrayLimit(arr, i) {\n var _i = null == arr ? null : \"undefined\" != typeof Symbol && arr[Symbol.iterator] || arr[\"@@iterator\"];\n if (null != _i) {\n var _s,\n _e,\n _x,\n _r,\n _arr = [],\n _n = !0,\n _d = !1;\n try {\n if (_x = (_i = _i.call(arr)).next, 0 === i) {\n if (Object(_i) !== _i) return;\n _n = !1;\n } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);\n } catch (err) {\n _d = !0, _e = err;\n } finally {\n try {\n if (!_n && null != _i[\"return\"] && (_r = _i[\"return\"](), Object(_r) !== _r)) return;\n } finally {\n if (_d) throw _e;\n }\n }\n return _arr;\n }\n}","export default function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}","import toPropertyKey from \"./toPropertyKey.js\";\nexport default function _defineProperty(obj, key, value) {\n key = toPropertyKey(key);\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n return obj;\n}","import defineProperty from \"./defineProperty.js\";\nexport default function _objectSpread(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? Object(arguments[i]) : {};\n var ownKeys = Object.keys(source);\n if (typeof Object.getOwnPropertySymbols === 'function') {\n ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) {\n return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n }));\n }\n ownKeys.forEach(function (key) {\n defineProperty(target, key, source[key]);\n });\n }\n return target;\n}","export default function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}","import _typeof from \"./typeof.js\";\nimport assertThisInitialized from \"./assertThisInitialized.js\";\nexport default function _possibleConstructorReturn(self, call) {\n if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) {\n return call;\n } else if (call !== void 0) {\n throw new TypeError(\"Derived constructors may only return object or undefined\");\n }\n return assertThisInitialized(self);\n}","export default function _getPrototypeOf(o) {\n _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {\n return o.__proto__ || Object.getPrototypeOf(o);\n };\n return _getPrototypeOf(o);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inherits(subClass, superClass) {\n if (typeof superClass !== \"function\" && superClass !== null) {\n throw new TypeError(\"Super expression must either be null or a function\");\n }\n subClass.prototype = Object.create(superClass && superClass.prototype, {\n constructor: {\n value: subClass,\n writable: true,\n configurable: true\n }\n });\n Object.defineProperty(subClass, \"prototype\", {\n writable: false\n });\n if (superClass) setPrototypeOf(subClass, superClass);\n}","import _extends from '@babel/runtime/helpers/esm/extends';\nimport _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';\nimport _objectSpread from '@babel/runtime/helpers/esm/objectSpread';\nimport _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';\nimport _createClass from '@babel/runtime/helpers/esm/createClass';\nimport _possibleConstructorReturn from '@babel/runtime/helpers/esm/possibleConstructorReturn';\nimport _getPrototypeOf from '@babel/runtime/helpers/esm/getPrototypeOf';\nimport _inherits from '@babel/runtime/helpers/esm/inherits';\nimport _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';\nimport _defineProperty from '@babel/runtime/helpers/esm/defineProperty';\nimport { createElement, Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { findDOMNode } from 'react-dom';\nimport invariant from 'invariant';\nimport _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';\n\nvar Manager = function () {\n function Manager() {\n _classCallCheck(this, Manager);\n\n _defineProperty(this, \"refs\", {});\n }\n\n _createClass(Manager, [{\n key: \"add\",\n value: function add(collection, ref) {\n if (!this.refs[collection]) {\n this.refs[collection] = [];\n }\n\n this.refs[collection].push(ref);\n }\n }, {\n key: \"remove\",\n value: function remove(collection, ref) {\n var index = this.getIndex(collection, ref);\n\n if (index !== -1) {\n this.refs[collection].splice(index, 1);\n }\n }\n }, {\n key: \"isActive\",\n value: function isActive() {\n return this.active;\n }\n }, {\n key: \"getActive\",\n value: function getActive() {\n var _this = this;\n\n return this.refs[this.active.collection].find(function (_ref) {\n var node = _ref.node;\n return node.sortableInfo.index == _this.active.index;\n });\n }\n }, {\n key: \"getIndex\",\n value: function getIndex(collection, ref) {\n return this.refs[collection].indexOf(ref);\n }\n }, {\n key: \"getOrderedRefs\",\n value: function getOrderedRefs() {\n var collection = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.active.collection;\n return this.refs[collection].sort(sortByIndex);\n }\n }]);\n\n return Manager;\n}();\n\nfunction sortByIndex(_ref2, _ref3) {\n var index1 = _ref2.node.sortableInfo.index;\n var index2 = _ref3.node.sortableInfo.index;\n return index1 - index2;\n}\n\nfunction arrayMove(array, from, to) {\n if (process.env.NODE_ENV !== 'production') {\n if (typeof console !== 'undefined') {\n console.warn(\"Deprecation warning: arrayMove will no longer be exported by 'react-sortable-hoc' in the next major release. Please install the `array-move` package locally instead. https://www.npmjs.com/package/array-move\");\n }\n }\n\n array = array.slice();\n array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);\n return array;\n}\nfunction omit(obj, keysToOmit) {\n return Object.keys(obj).reduce(function (acc, key) {\n if (keysToOmit.indexOf(key) === -1) {\n acc[key] = obj[key];\n }\n\n return acc;\n }, {});\n}\nvar events = {\n end: ['touchend', 'touchcancel', 'mouseup'],\n move: ['touchmove', 'mousemove'],\n start: ['touchstart', 'mousedown']\n};\nvar vendorPrefix = function () {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return '';\n }\n\n var styles = window.getComputedStyle(document.documentElement, '') || ['-moz-hidden-iframe'];\n var pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1];\n\n switch (pre) {\n case 'ms':\n return 'ms';\n\n default:\n return pre && pre.length ? pre[0].toUpperCase() + pre.substr(1) : '';\n }\n}();\nfunction setInlineStyles(node, styles) {\n Object.keys(styles).forEach(function (key) {\n node.style[key] = styles[key];\n });\n}\nfunction setTranslate3d(node, translate) {\n node.style[\"\".concat(vendorPrefix, \"Transform\")] = translate == null ? '' : \"translate3d(\".concat(translate.x, \"px,\").concat(translate.y, \"px,0)\");\n}\nfunction setTransitionDuration(node, duration) {\n node.style[\"\".concat(vendorPrefix, \"TransitionDuration\")] = duration == null ? '' : \"\".concat(duration, \"ms\");\n}\nfunction closest(el, fn) {\n while (el) {\n if (fn(el)) {\n return el;\n }\n\n el = el.parentNode;\n }\n\n return null;\n}\nfunction limit(min, max, value) {\n return Math.max(min, Math.min(value, max));\n}\n\nfunction getPixelValue(stringValue) {\n if (stringValue.substr(-2) === 'px') {\n return parseFloat(stringValue);\n }\n\n return 0;\n}\n\nfunction getElementMargin(element) {\n var style = window.getComputedStyle(element);\n return {\n bottom: getPixelValue(style.marginBottom),\n left: getPixelValue(style.marginLeft),\n right: getPixelValue(style.marginRight),\n top: getPixelValue(style.marginTop)\n };\n}\nfunction provideDisplayName(prefix, Component$$1) {\n var componentName = Component$$1.displayName || Component$$1.name;\n return componentName ? \"\".concat(prefix, \"(\").concat(componentName, \")\") : prefix;\n}\nfunction getScrollAdjustedBoundingClientRect(node, scrollDelta) {\n var boundingClientRect = node.getBoundingClientRect();\n return {\n top: boundingClientRect.top + scrollDelta.top,\n left: boundingClientRect.left + scrollDelta.left\n };\n}\nfunction getPosition(event) {\n if (event.touches && event.touches.length) {\n return {\n x: event.touches[0].pageX,\n y: event.touches[0].pageY\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n return {\n x: event.changedTouches[0].pageX,\n y: event.changedTouches[0].pageY\n };\n } else {\n return {\n x: event.pageX,\n y: event.pageY\n };\n }\n}\nfunction isTouchEvent(event) {\n return event.touches && event.touches.length || event.changedTouches && event.changedTouches.length;\n}\nfunction getEdgeOffset(node, parent) {\n var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {\n left: 0,\n top: 0\n };\n\n if (!node) {\n return undefined;\n }\n\n var nodeOffset = {\n left: offset.left + node.offsetLeft,\n top: offset.top + node.offsetTop\n };\n\n if (node.parentNode === parent) {\n return nodeOffset;\n }\n\n return getEdgeOffset(node.parentNode, parent, nodeOffset);\n}\nfunction getTargetIndex(newIndex, prevIndex, oldIndex) {\n if (newIndex < oldIndex && newIndex > prevIndex) {\n return newIndex - 1;\n } else if (newIndex > oldIndex && newIndex < prevIndex) {\n return newIndex + 1;\n } else {\n return newIndex;\n }\n}\nfunction getLockPixelOffset(_ref) {\n var lockOffset = _ref.lockOffset,\n width = _ref.width,\n height = _ref.height;\n var offsetX = lockOffset;\n var offsetY = lockOffset;\n var unit = 'px';\n\n if (typeof lockOffset === 'string') {\n var match = /^[+-]?\\d*(?:\\.\\d*)?(px|%)$/.exec(lockOffset);\n invariant(match !== null, 'lockOffset value should be a number or a string of a ' + 'number followed by \"px\" or \"%\". Given %s', lockOffset);\n offsetX = parseFloat(lockOffset);\n offsetY = parseFloat(lockOffset);\n unit = match[1];\n }\n\n invariant(isFinite(offsetX) && isFinite(offsetY), 'lockOffset value should be a finite. Given %s', lockOffset);\n\n if (unit === '%') {\n offsetX = offsetX * width / 100;\n offsetY = offsetY * height / 100;\n }\n\n return {\n x: offsetX,\n y: offsetY\n };\n}\nfunction getLockPixelOffsets(_ref2) {\n var height = _ref2.height,\n width = _ref2.width,\n lockOffset = _ref2.lockOffset;\n var offsets = Array.isArray(lockOffset) ? lockOffset : [lockOffset, lockOffset];\n invariant(offsets.length === 2, 'lockOffset prop of SortableContainer should be a single ' + 'value or an array of exactly two values. Given %s', lockOffset);\n\n var _offsets = _slicedToArray(offsets, 2),\n minLockOffset = _offsets[0],\n maxLockOffset = _offsets[1];\n\n return [getLockPixelOffset({\n height: height,\n lockOffset: minLockOffset,\n width: width\n }), getLockPixelOffset({\n height: height,\n lockOffset: maxLockOffset,\n width: width\n })];\n}\n\nfunction isScrollable(el) {\n var computedStyle = window.getComputedStyle(el);\n var overflowRegex = /(auto|scroll)/;\n var properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.find(function (property) {\n return overflowRegex.test(computedStyle[property]);\n });\n}\n\nfunction getScrollingParent(el) {\n if (!(el instanceof HTMLElement)) {\n return null;\n } else if (isScrollable(el)) {\n return el;\n } else {\n return getScrollingParent(el.parentNode);\n }\n}\nfunction getContainerGridGap(element) {\n var style = window.getComputedStyle(element);\n\n if (style.display === 'grid') {\n return {\n x: getPixelValue(style.gridColumnGap),\n y: getPixelValue(style.gridRowGap)\n };\n }\n\n return {\n x: 0,\n y: 0\n };\n}\nvar KEYCODE = {\n TAB: 9,\n ESC: 27,\n SPACE: 32,\n LEFT: 37,\n UP: 38,\n RIGHT: 39,\n DOWN: 40\n};\nvar NodeType = {\n Anchor: 'A',\n Button: 'BUTTON',\n Canvas: 'CANVAS',\n Input: 'INPUT',\n Option: 'OPTION',\n Textarea: 'TEXTAREA',\n Select: 'SELECT'\n};\nfunction cloneNode(node) {\n var selector = 'input, textarea, select, canvas, [contenteditable]';\n var fields = node.querySelectorAll(selector);\n var clonedNode = node.cloneNode(true);\n\n var clonedFields = _toConsumableArray(clonedNode.querySelectorAll(selector));\n\n clonedFields.forEach(function (field, i) {\n if (field.type !== 'file') {\n field.value = fields[i].value;\n }\n\n if (field.type === 'radio' && field.name) {\n field.name = \"__sortableClone__\".concat(field.name);\n }\n\n if (field.tagName === NodeType.Canvas && fields[i].width > 0 && fields[i].height > 0) {\n var destCtx = field.getContext('2d');\n destCtx.drawImage(fields[i], 0, 0);\n }\n });\n return clonedNode;\n}\n\nfunction sortableHandle(WrappedComponent) {\n var _class, _temp;\n\n var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n withRef: false\n };\n return _temp = _class = function (_React$Component) {\n _inherits(WithSortableHandle, _React$Component);\n\n function WithSortableHandle() {\n _classCallCheck(this, WithSortableHandle);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(WithSortableHandle).apply(this, arguments));\n }\n\n _createClass(WithSortableHandle, [{\n key: \"componentDidMount\",\n value: function componentDidMount() {\n var node = findDOMNode(this);\n node.sortableHandle = true;\n }\n }, {\n key: \"getWrappedInstance\",\n value: function getWrappedInstance() {\n invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableHandle() call');\n return this.refs.wrappedInstance;\n }\n }, {\n key: \"render\",\n value: function render() {\n var ref = config.withRef ? 'wrappedInstance' : null;\n return createElement(WrappedComponent, _extends({\n ref: ref\n }, this.props));\n }\n }]);\n\n return WithSortableHandle;\n }(Component), _defineProperty(_class, \"displayName\", provideDisplayName('sortableHandle', WrappedComponent)), _temp;\n}\nfunction isSortableHandle(node) {\n return node.sortableHandle != null;\n}\n\nvar AutoScroller = function () {\n function AutoScroller(container, onScrollCallback) {\n _classCallCheck(this, AutoScroller);\n\n this.container = container;\n this.onScrollCallback = onScrollCallback;\n }\n\n _createClass(AutoScroller, [{\n key: \"clear\",\n value: function clear() {\n if (this.interval == null) {\n return;\n }\n\n clearInterval(this.interval);\n this.interval = null;\n }\n }, {\n key: \"update\",\n value: function update(_ref) {\n var _this = this;\n\n var translate = _ref.translate,\n minTranslate = _ref.minTranslate,\n maxTranslate = _ref.maxTranslate,\n width = _ref.width,\n height = _ref.height;\n var direction = {\n x: 0,\n y: 0\n };\n var speed = {\n x: 1,\n y: 1\n };\n var acceleration = {\n x: 10,\n y: 10\n };\n var _this$container = this.container,\n scrollTop = _this$container.scrollTop,\n scrollLeft = _this$container.scrollLeft,\n scrollHeight = _this$container.scrollHeight,\n scrollWidth = _this$container.scrollWidth,\n clientHeight = _this$container.clientHeight,\n clientWidth = _this$container.clientWidth;\n var isTop = scrollTop === 0;\n var isBottom = scrollHeight - scrollTop - clientHeight === 0;\n var isLeft = scrollLeft === 0;\n var isRight = scrollWidth - scrollLeft - clientWidth === 0;\n\n if (translate.y >= maxTranslate.y - height / 2 && !isBottom) {\n direction.y = 1;\n speed.y = acceleration.y * Math.abs((maxTranslate.y - height / 2 - translate.y) / height);\n } else if (translate.x >= maxTranslate.x - width / 2 && !isRight) {\n direction.x = 1;\n speed.x = acceleration.x * Math.abs((maxTranslate.x - width / 2 - translate.x) / width);\n } else if (translate.y <= minTranslate.y + height / 2 && !isTop) {\n direction.y = -1;\n speed.y = acceleration.y * Math.abs((translate.y - height / 2 - minTranslate.y) / height);\n } else if (translate.x <= minTranslate.x + width / 2 && !isLeft) {\n direction.x = -1;\n speed.x = acceleration.x * Math.abs((translate.x - width / 2 - minTranslate.x) / width);\n }\n\n if (this.interval) {\n this.clear();\n this.isAutoScrolling = false;\n }\n\n if (direction.x !== 0 || direction.y !== 0) {\n this.interval = setInterval(function () {\n _this.isAutoScrolling = true;\n var offset = {\n left: speed.x * direction.x,\n top: speed.y * direction.y\n };\n _this.container.scrollTop += offset.top;\n _this.container.scrollLeft += offset.left;\n\n _this.onScrollCallback(offset);\n }, 5);\n }\n }\n }]);\n\n return AutoScroller;\n}();\n\nfunction defaultGetHelperDimensions(_ref) {\n var node = _ref.node;\n return {\n height: node.offsetHeight,\n width: node.offsetWidth\n };\n}\n\nfunction defaultShouldCancelStart(event) {\n var interactiveElements = [NodeType.Input, NodeType.Textarea, NodeType.Select, NodeType.Option, NodeType.Button];\n\n if (interactiveElements.indexOf(event.target.tagName) !== -1) {\n return true;\n }\n\n if (closest(event.target, function (el) {\n return el.contentEditable === 'true';\n })) {\n return true;\n }\n\n return false;\n}\n\nvar propTypes = {\n axis: PropTypes.oneOf(['x', 'y', 'xy']),\n contentWindow: PropTypes.any,\n disableAutoscroll: PropTypes.bool,\n distance: PropTypes.number,\n getContainer: PropTypes.func,\n getHelperDimensions: PropTypes.func,\n helperClass: PropTypes.string,\n helperContainer: PropTypes.oneOfType([PropTypes.func, typeof HTMLElement === 'undefined' ? PropTypes.any : PropTypes.instanceOf(HTMLElement)]),\n hideSortableGhost: PropTypes.bool,\n keyboardSortingTransitionDuration: PropTypes.number,\n lockAxis: PropTypes.string,\n lockOffset: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]))]),\n lockToContainerEdges: PropTypes.bool,\n onSortEnd: PropTypes.func,\n onSortMove: PropTypes.func,\n onSortOver: PropTypes.func,\n onSortStart: PropTypes.func,\n pressDelay: PropTypes.number,\n pressThreshold: PropTypes.number,\n keyCodes: PropTypes.shape({\n lift: PropTypes.arrayOf(PropTypes.number),\n drop: PropTypes.arrayOf(PropTypes.number),\n cancel: PropTypes.arrayOf(PropTypes.number),\n up: PropTypes.arrayOf(PropTypes.number),\n down: PropTypes.arrayOf(PropTypes.number)\n }),\n shouldCancelStart: PropTypes.func,\n transitionDuration: PropTypes.number,\n updateBeforeSortStart: PropTypes.func,\n useDragHandle: PropTypes.bool,\n useWindowAsScrollContainer: PropTypes.bool\n};\nvar defaultKeyCodes = {\n lift: [KEYCODE.SPACE],\n drop: [KEYCODE.SPACE],\n cancel: [KEYCODE.ESC],\n up: [KEYCODE.UP, KEYCODE.LEFT],\n down: [KEYCODE.DOWN, KEYCODE.RIGHT]\n};\nvar defaultProps = {\n axis: 'y',\n disableAutoscroll: false,\n distance: 0,\n getHelperDimensions: defaultGetHelperDimensions,\n hideSortableGhost: true,\n lockOffset: '50%',\n lockToContainerEdges: false,\n pressDelay: 0,\n pressThreshold: 5,\n keyCodes: defaultKeyCodes,\n shouldCancelStart: defaultShouldCancelStart,\n transitionDuration: 300,\n useWindowAsScrollContainer: false\n};\nvar omittedProps = Object.keys(propTypes);\nfunction validateProps(props) {\n invariant(!(props.distance && props.pressDelay), 'Attempted to set both `pressDelay` and `distance` on SortableContainer, you may only use one or the other, not both at the same time.');\n}\n\nfunction _finallyRethrows(body, finalizer) {\n try {\n var result = body();\n } catch (e) {\n return finalizer(true, e);\n }\n\n if (result && result.then) {\n return result.then(finalizer.bind(null, false), finalizer.bind(null, true));\n }\n\n return finalizer(false, value);\n}\nfunction sortableContainer(WrappedComponent) {\n var _class, _temp;\n\n var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n withRef: false\n };\n return _temp = _class = function (_React$Component) {\n _inherits(WithSortableContainer, _React$Component);\n\n function WithSortableContainer(props) {\n var _this;\n\n _classCallCheck(this, WithSortableContainer);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(WithSortableContainer).call(this, props));\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"state\", {});\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleStart\", function (event) {\n var _this$props = _this.props,\n distance = _this$props.distance,\n shouldCancelStart = _this$props.shouldCancelStart;\n\n if (event.button === 2 || shouldCancelStart(event)) {\n return;\n }\n\n _this.touched = true;\n _this.position = getPosition(event);\n var node = closest(event.target, function (el) {\n return el.sortableInfo != null;\n });\n\n if (node && node.sortableInfo && _this.nodeIsChild(node) && !_this.state.sorting) {\n var useDragHandle = _this.props.useDragHandle;\n var _node$sortableInfo = node.sortableInfo,\n index = _node$sortableInfo.index,\n collection = _node$sortableInfo.collection,\n disabled = _node$sortableInfo.disabled;\n\n if (disabled) {\n return;\n }\n\n if (useDragHandle && !closest(event.target, isSortableHandle)) {\n return;\n }\n\n _this.manager.active = {\n collection: collection,\n index: index\n };\n\n if (!isTouchEvent(event) && event.target.tagName === NodeType.Anchor) {\n event.preventDefault();\n }\n\n if (!distance) {\n if (_this.props.pressDelay === 0) {\n _this.handlePress(event);\n } else {\n _this.pressTimer = setTimeout(function () {\n return _this.handlePress(event);\n }, _this.props.pressDelay);\n }\n }\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"nodeIsChild\", function (node) {\n return node.sortableInfo.manager === _this.manager;\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleMove\", function (event) {\n var _this$props2 = _this.props,\n distance = _this$props2.distance,\n pressThreshold = _this$props2.pressThreshold;\n\n if (!_this.state.sorting && _this.touched && !_this._awaitingUpdateBeforeSortStart) {\n var position = getPosition(event);\n var delta = {\n x: _this.position.x - position.x,\n y: _this.position.y - position.y\n };\n var combinedDelta = Math.abs(delta.x) + Math.abs(delta.y);\n _this.delta = delta;\n\n if (!distance && (!pressThreshold || combinedDelta >= pressThreshold)) {\n clearTimeout(_this.cancelTimer);\n _this.cancelTimer = setTimeout(_this.cancel, 0);\n } else if (distance && combinedDelta >= distance && _this.manager.isActive()) {\n _this.handlePress(event);\n }\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleEnd\", function () {\n _this.touched = false;\n\n _this.cancel();\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"cancel\", function () {\n var distance = _this.props.distance;\n var sorting = _this.state.sorting;\n\n if (!sorting) {\n if (!distance) {\n clearTimeout(_this.pressTimer);\n }\n\n _this.manager.active = null;\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handlePress\", function (event) {\n try {\n var active = _this.manager.getActive();\n\n var _temp6 = function () {\n if (active) {\n var _temp7 = function _temp7() {\n var index = _node.sortableInfo.index;\n var margin = getElementMargin(_node);\n var gridGap = getContainerGridGap(_this.container);\n\n var containerBoundingRect = _this.scrollContainer.getBoundingClientRect();\n\n var dimensions = _getHelperDimensions({\n index: index,\n node: _node,\n collection: _collection\n });\n\n _this.node = _node;\n _this.margin = margin;\n _this.gridGap = gridGap;\n _this.width = dimensions.width;\n _this.height = dimensions.height;\n _this.marginOffset = {\n x: _this.margin.left + _this.margin.right + _this.gridGap.x,\n y: Math.max(_this.margin.top, _this.margin.bottom, _this.gridGap.y)\n };\n _this.boundingClientRect = _node.getBoundingClientRect();\n _this.containerBoundingRect = containerBoundingRect;\n _this.index = index;\n _this.newIndex = index;\n _this.axis = {\n x: _axis.indexOf('x') >= 0,\n y: _axis.indexOf('y') >= 0\n };\n _this.offsetEdge = getEdgeOffset(_node, _this.container);\n\n if (_isKeySorting) {\n _this.initialOffset = getPosition(_objectSpread({}, event, {\n pageX: _this.boundingClientRect.left,\n pageY: _this.boundingClientRect.top\n }));\n } else {\n _this.initialOffset = getPosition(event);\n }\n\n _this.initialScroll = {\n left: _this.scrollContainer.scrollLeft,\n top: _this.scrollContainer.scrollTop\n };\n _this.initialWindowScroll = {\n left: window.pageXOffset,\n top: window.pageYOffset\n };\n _this.helper = _this.helperContainer.appendChild(cloneNode(_node));\n setInlineStyles(_this.helper, {\n boxSizing: 'border-box',\n height: \"\".concat(_this.height, \"px\"),\n left: \"\".concat(_this.boundingClientRect.left - margin.left, \"px\"),\n pointerEvents: 'none',\n position: 'fixed',\n top: \"\".concat(_this.boundingClientRect.top - margin.top, \"px\"),\n width: \"\".concat(_this.width, \"px\")\n });\n\n if (_isKeySorting) {\n _this.helper.focus();\n }\n\n if (_hideSortableGhost) {\n _this.sortableGhost = _node;\n setInlineStyles(_node, {\n opacity: 0,\n visibility: 'hidden'\n });\n }\n\n _this.minTranslate = {};\n _this.maxTranslate = {};\n\n if (_isKeySorting) {\n var _ref = _useWindowAsScrollContainer ? {\n top: 0,\n left: 0,\n width: _this.contentWindow.innerWidth,\n height: _this.contentWindow.innerHeight\n } : _this.containerBoundingRect,\n containerTop = _ref.top,\n containerLeft = _ref.left,\n containerWidth = _ref.width,\n containerHeight = _ref.height;\n\n var containerBottom = containerTop + containerHeight;\n var containerRight = containerLeft + containerWidth;\n\n if (_this.axis.x) {\n _this.minTranslate.x = containerLeft - _this.boundingClientRect.left;\n _this.maxTranslate.x = containerRight - (_this.boundingClientRect.left + _this.width);\n }\n\n if (_this.axis.y) {\n _this.minTranslate.y = containerTop - _this.boundingClientRect.top;\n _this.maxTranslate.y = containerBottom - (_this.boundingClientRect.top + _this.height);\n }\n } else {\n if (_this.axis.x) {\n _this.minTranslate.x = (_useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - _this.boundingClientRect.left - _this.width / 2;\n _this.maxTranslate.x = (_useWindowAsScrollContainer ? _this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - _this.boundingClientRect.left - _this.width / 2;\n }\n\n if (_this.axis.y) {\n _this.minTranslate.y = (_useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - _this.boundingClientRect.top - _this.height / 2;\n _this.maxTranslate.y = (_useWindowAsScrollContainer ? _this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - _this.boundingClientRect.top - _this.height / 2;\n }\n }\n\n if (_helperClass) {\n _helperClass.split(' ').forEach(function (className) {\n return _this.helper.classList.add(className);\n });\n }\n\n _this.listenerNode = event.touches ? _node : _this.contentWindow;\n\n if (_isKeySorting) {\n _this.listenerNode.addEventListener('wheel', _this.handleKeyEnd, true);\n\n _this.listenerNode.addEventListener('mousedown', _this.handleKeyEnd, true);\n\n _this.listenerNode.addEventListener('keydown', _this.handleKeyDown);\n } else {\n events.move.forEach(function (eventName) {\n return _this.listenerNode.addEventListener(eventName, _this.handleSortMove, false);\n });\n events.end.forEach(function (eventName) {\n return _this.listenerNode.addEventListener(eventName, _this.handleSortEnd, false);\n });\n }\n\n _this.setState({\n sorting: true,\n sortingIndex: index\n });\n\n if (_onSortStart) {\n _onSortStart({\n node: _node,\n index: index,\n collection: _collection,\n isKeySorting: _isKeySorting,\n nodes: _this.manager.getOrderedRefs(),\n helper: _this.helper\n }, event);\n }\n\n if (_isKeySorting) {\n _this.keyMove(0);\n }\n };\n\n var _this$props3 = _this.props,\n _axis = _this$props3.axis,\n _getHelperDimensions = _this$props3.getHelperDimensions,\n _helperClass = _this$props3.helperClass,\n _hideSortableGhost = _this$props3.hideSortableGhost,\n updateBeforeSortStart = _this$props3.updateBeforeSortStart,\n _onSortStart = _this$props3.onSortStart,\n _useWindowAsScrollContainer = _this$props3.useWindowAsScrollContainer;\n var _node = active.node,\n _collection = active.collection;\n var _isKeySorting = _this.manager.isKeySorting;\n\n var _temp8 = function () {\n if (typeof updateBeforeSortStart === 'function') {\n _this._awaitingUpdateBeforeSortStart = true;\n\n var _temp9 = _finallyRethrows(function () {\n var index = _node.sortableInfo.index;\n return Promise.resolve(updateBeforeSortStart({\n collection: _collection,\n index: index,\n node: _node,\n isKeySorting: _isKeySorting\n }, event)).then(function () {});\n }, function (_wasThrown, _result) {\n _this._awaitingUpdateBeforeSortStart = false;\n if (_wasThrown) throw _result;\n return _result;\n });\n\n if (_temp9 && _temp9.then) return _temp9.then(function () {});\n }\n }();\n\n return _temp8 && _temp8.then ? _temp8.then(_temp7) : _temp7(_temp8);\n }\n }();\n\n return Promise.resolve(_temp6 && _temp6.then ? _temp6.then(function () {}) : void 0);\n } catch (e) {\n return Promise.reject(e);\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleSortMove\", function (event) {\n var onSortMove = _this.props.onSortMove;\n\n if (typeof event.preventDefault === 'function') {\n event.preventDefault();\n }\n\n _this.updateHelperPosition(event);\n\n _this.animateNodes();\n\n _this.autoscroll();\n\n if (onSortMove) {\n onSortMove(event);\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleSortEnd\", function (event) {\n var _this$props4 = _this.props,\n hideSortableGhost = _this$props4.hideSortableGhost,\n onSortEnd = _this$props4.onSortEnd;\n var _this$manager = _this.manager,\n collection = _this$manager.active.collection,\n isKeySorting = _this$manager.isKeySorting;\n\n var nodes = _this.manager.getOrderedRefs();\n\n if (_this.listenerNode) {\n if (isKeySorting) {\n _this.listenerNode.removeEventListener('wheel', _this.handleKeyEnd, true);\n\n _this.listenerNode.removeEventListener('mousedown', _this.handleKeyEnd, true);\n\n _this.listenerNode.removeEventListener('keydown', _this.handleKeyDown);\n } else {\n events.move.forEach(function (eventName) {\n return _this.listenerNode.removeEventListener(eventName, _this.handleSortMove);\n });\n events.end.forEach(function (eventName) {\n return _this.listenerNode.removeEventListener(eventName, _this.handleSortEnd);\n });\n }\n }\n\n _this.helper.parentNode.removeChild(_this.helper);\n\n if (hideSortableGhost && _this.sortableGhost) {\n setInlineStyles(_this.sortableGhost, {\n opacity: '',\n visibility: ''\n });\n }\n\n for (var i = 0, len = nodes.length; i < len; i++) {\n var _node2 = nodes[i];\n var el = _node2.node;\n _node2.edgeOffset = null;\n _node2.boundingClientRect = null;\n setTranslate3d(el, null);\n setTransitionDuration(el, null);\n _node2.translate = null;\n }\n\n _this.autoScroller.clear();\n\n _this.manager.active = null;\n _this.manager.isKeySorting = false;\n\n _this.setState({\n sorting: false,\n sortingIndex: null\n });\n\n if (typeof onSortEnd === 'function') {\n onSortEnd({\n collection: collection,\n newIndex: _this.newIndex,\n oldIndex: _this.index,\n isKeySorting: isKeySorting,\n nodes: nodes\n }, event);\n }\n\n _this.touched = false;\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"autoscroll\", function () {\n var disableAutoscroll = _this.props.disableAutoscroll;\n var isKeySorting = _this.manager.isKeySorting;\n\n if (disableAutoscroll) {\n _this.autoScroller.clear();\n\n return;\n }\n\n if (isKeySorting) {\n var translate = _objectSpread({}, _this.translate);\n\n var scrollX = 0;\n var scrollY = 0;\n\n if (_this.axis.x) {\n translate.x = Math.min(_this.maxTranslate.x, Math.max(_this.minTranslate.x, _this.translate.x));\n scrollX = _this.translate.x - translate.x;\n }\n\n if (_this.axis.y) {\n translate.y = Math.min(_this.maxTranslate.y, Math.max(_this.minTranslate.y, _this.translate.y));\n scrollY = _this.translate.y - translate.y;\n }\n\n _this.translate = translate;\n setTranslate3d(_this.helper, _this.translate);\n _this.scrollContainer.scrollLeft += scrollX;\n _this.scrollContainer.scrollTop += scrollY;\n return;\n }\n\n _this.autoScroller.update({\n height: _this.height,\n maxTranslate: _this.maxTranslate,\n minTranslate: _this.minTranslate,\n translate: _this.translate,\n width: _this.width\n });\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"onAutoScroll\", function (offset) {\n _this.translate.x += offset.left;\n _this.translate.y += offset.top;\n\n _this.animateNodes();\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleKeyDown\", function (event) {\n var keyCode = event.keyCode;\n var _this$props5 = _this.props,\n shouldCancelStart = _this$props5.shouldCancelStart,\n _this$props5$keyCodes = _this$props5.keyCodes,\n customKeyCodes = _this$props5$keyCodes === void 0 ? {} : _this$props5$keyCodes;\n\n var keyCodes = _objectSpread({}, defaultKeyCodes, customKeyCodes);\n\n if (_this.manager.active && !_this.manager.isKeySorting || !_this.manager.active && (!keyCodes.lift.includes(keyCode) || shouldCancelStart(event) || !_this.isValidSortingTarget(event))) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n\n if (keyCodes.lift.includes(keyCode) && !_this.manager.active) {\n _this.keyLift(event);\n } else if (keyCodes.drop.includes(keyCode) && _this.manager.active) {\n _this.keyDrop(event);\n } else if (keyCodes.cancel.includes(keyCode)) {\n _this.newIndex = _this.manager.active.index;\n\n _this.keyDrop(event);\n } else if (keyCodes.up.includes(keyCode)) {\n _this.keyMove(-1);\n } else if (keyCodes.down.includes(keyCode)) {\n _this.keyMove(1);\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"keyLift\", function (event) {\n var target = event.target;\n var node = closest(target, function (el) {\n return el.sortableInfo != null;\n });\n var _node$sortableInfo2 = node.sortableInfo,\n index = _node$sortableInfo2.index,\n collection = _node$sortableInfo2.collection;\n _this.initialFocusedNode = target;\n _this.manager.isKeySorting = true;\n _this.manager.active = {\n index: index,\n collection: collection\n };\n\n _this.handlePress(event);\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"keyMove\", function (shift) {\n var nodes = _this.manager.getOrderedRefs();\n\n var lastIndex = nodes[nodes.length - 1].node.sortableInfo.index;\n var newIndex = _this.newIndex + shift;\n var prevIndex = _this.newIndex;\n\n if (newIndex < 0 || newIndex > lastIndex) {\n return;\n }\n\n _this.prevIndex = prevIndex;\n _this.newIndex = newIndex;\n var targetIndex = getTargetIndex(_this.newIndex, _this.prevIndex, _this.index);\n var target = nodes.find(function (_ref2) {\n var node = _ref2.node;\n return node.sortableInfo.index === targetIndex;\n });\n var targetNode = target.node;\n var scrollDelta = _this.containerScrollDelta;\n var targetBoundingClientRect = target.boundingClientRect || getScrollAdjustedBoundingClientRect(targetNode, scrollDelta);\n var targetTranslate = target.translate || {\n x: 0,\n y: 0\n };\n var targetPosition = {\n top: targetBoundingClientRect.top + targetTranslate.y - scrollDelta.top,\n left: targetBoundingClientRect.left + targetTranslate.x - scrollDelta.left\n };\n var shouldAdjustForSize = prevIndex < newIndex;\n var sizeAdjustment = {\n x: shouldAdjustForSize && _this.axis.x ? targetNode.offsetWidth - _this.width : 0,\n y: shouldAdjustForSize && _this.axis.y ? targetNode.offsetHeight - _this.height : 0\n };\n\n _this.handleSortMove({\n pageX: targetPosition.left + sizeAdjustment.x,\n pageY: targetPosition.top + sizeAdjustment.y,\n ignoreTransition: shift === 0\n });\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"keyDrop\", function (event) {\n _this.handleSortEnd(event);\n\n if (_this.initialFocusedNode) {\n _this.initialFocusedNode.focus();\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"handleKeyEnd\", function (event) {\n if (_this.manager.active) {\n _this.keyDrop(event);\n }\n });\n\n _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), \"isValidSortingTarget\", function (event) {\n var useDragHandle = _this.props.useDragHandle;\n var target = event.target;\n var node = closest(target, function (el) {\n return el.sortableInfo != null;\n });\n return node && node.sortableInfo && !node.sortableInfo.disabled && (useDragHandle ? isSortableHandle(target) : target.sortableInfo);\n });\n\n validateProps(props);\n _this.manager = new Manager();\n _this.events = {\n end: _this.handleEnd,\n move: _this.handleMove,\n start: _this.handleStart\n };\n return _this;\n }\n\n _createClass(WithSortableContainer, [{\n key: \"getChildContext\",\n value: function getChildContext() {\n return {\n manager: this.manager\n };\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n var _this2 = this;\n\n var useWindowAsScrollContainer = this.props.useWindowAsScrollContainer;\n var container = this.getContainer();\n Promise.resolve(container).then(function (containerNode) {\n _this2.container = containerNode;\n _this2.document = _this2.container.ownerDocument || document;\n var contentWindow = _this2.props.contentWindow || _this2.document.defaultView || window;\n _this2.contentWindow = typeof contentWindow === 'function' ? contentWindow() : contentWindow;\n _this2.scrollContainer = useWindowAsScrollContainer ? _this2.document.scrollingElement || _this2.document.documentElement : getScrollingParent(_this2.container) || _this2.container;\n _this2.autoScroller = new AutoScroller(_this2.scrollContainer, _this2.onAutoScroll);\n Object.keys(_this2.events).forEach(function (key) {\n return events[key].forEach(function (eventName) {\n return _this2.container.addEventListener(eventName, _this2.events[key], false);\n });\n });\n\n _this2.container.addEventListener('keydown', _this2.handleKeyDown);\n });\n }\n }, {\n key: \"componentWillUnmount\",\n value: function componentWillUnmount() {\n var _this3 = this;\n\n if (this.helper && this.helper.parentNode) {\n this.helper.parentNode.removeChild(this.helper);\n }\n\n if (!this.container) {\n return;\n }\n\n Object.keys(this.events).forEach(function (key) {\n return events[key].forEach(function (eventName) {\n return _this3.container.removeEventListener(eventName, _this3.events[key]);\n });\n });\n this.container.removeEventListener('keydown', this.handleKeyDown);\n }\n }, {\n key: \"updateHelperPosition\",\n value: function updateHelperPosition(event) {\n var _this$props6 = this.props,\n lockAxis = _this$props6.lockAxis,\n lockOffset = _this$props6.lockOffset,\n lockToContainerEdges = _this$props6.lockToContainerEdges,\n transitionDuration = _this$props6.transitionDuration,\n _this$props6$keyboard = _this$props6.keyboardSortingTransitionDuration,\n keyboardSortingTransitionDuration = _this$props6$keyboard === void 0 ? transitionDuration : _this$props6$keyboard;\n var isKeySorting = this.manager.isKeySorting;\n var ignoreTransition = event.ignoreTransition;\n var offset = getPosition(event);\n var translate = {\n x: offset.x - this.initialOffset.x,\n y: offset.y - this.initialOffset.y\n };\n translate.y -= window.pageYOffset - this.initialWindowScroll.top;\n translate.x -= window.pageXOffset - this.initialWindowScroll.left;\n this.translate = translate;\n\n if (lockToContainerEdges) {\n var _getLockPixelOffsets = getLockPixelOffsets({\n height: this.height,\n lockOffset: lockOffset,\n width: this.width\n }),\n _getLockPixelOffsets2 = _slicedToArray(_getLockPixelOffsets, 2),\n minLockOffset = _getLockPixelOffsets2[0],\n maxLockOffset = _getLockPixelOffsets2[1];\n\n var minOffset = {\n x: this.width / 2 - minLockOffset.x,\n y: this.height / 2 - minLockOffset.y\n };\n var maxOffset = {\n x: this.width / 2 - maxLockOffset.x,\n y: this.height / 2 - maxLockOffset.y\n };\n translate.x = limit(this.minTranslate.x + minOffset.x, this.maxTranslate.x - maxOffset.x, translate.x);\n translate.y = limit(this.minTranslate.y + minOffset.y, this.maxTranslate.y - maxOffset.y, translate.y);\n }\n\n if (lockAxis === 'x') {\n translate.y = 0;\n } else if (lockAxis === 'y') {\n translate.x = 0;\n }\n\n if (isKeySorting && keyboardSortingTransitionDuration && !ignoreTransition) {\n setTransitionDuration(this.helper, keyboardSortingTransitionDuration);\n }\n\n setTranslate3d(this.helper, translate);\n }\n }, {\n key: \"animateNodes\",\n value: function animateNodes() {\n var _this$props7 = this.props,\n transitionDuration = _this$props7.transitionDuration,\n hideSortableGhost = _this$props7.hideSortableGhost,\n onSortOver = _this$props7.onSortOver;\n var containerScrollDelta = this.containerScrollDelta,\n windowScrollDelta = this.windowScrollDelta;\n var nodes = this.manager.getOrderedRefs();\n var sortingOffset = {\n left: this.offsetEdge.left + this.translate.x + containerScrollDelta.left,\n top: this.offsetEdge.top + this.translate.y + containerScrollDelta.top\n };\n var isKeySorting = this.manager.isKeySorting;\n var prevIndex = this.newIndex;\n this.newIndex = null;\n\n for (var i = 0, len = nodes.length; i < len; i++) {\n var _node3 = nodes[i].node;\n var index = _node3.sortableInfo.index;\n var width = _node3.offsetWidth;\n var height = _node3.offsetHeight;\n var offset = {\n height: this.height > height ? height / 2 : this.height / 2,\n width: this.width > width ? width / 2 : this.width / 2\n };\n var mustShiftBackward = isKeySorting && index > this.index && index <= prevIndex;\n var mustShiftForward = isKeySorting && index < this.index && index >= prevIndex;\n var translate = {\n x: 0,\n y: 0\n };\n var edgeOffset = nodes[i].edgeOffset;\n\n if (!edgeOffset) {\n edgeOffset = getEdgeOffset(_node3, this.container);\n nodes[i].edgeOffset = edgeOffset;\n\n if (isKeySorting) {\n nodes[i].boundingClientRect = getScrollAdjustedBoundingClientRect(_node3, containerScrollDelta);\n }\n }\n\n var nextNode = i < nodes.length - 1 && nodes[i + 1];\n var prevNode = i > 0 && nodes[i - 1];\n\n if (nextNode && !nextNode.edgeOffset) {\n nextNode.edgeOffset = getEdgeOffset(nextNode.node, this.container);\n\n if (isKeySorting) {\n nextNode.boundingClientRect = getScrollAdjustedBoundingClientRect(nextNode.node, containerScrollDelta);\n }\n }\n\n if (index === this.index) {\n if (hideSortableGhost) {\n this.sortableGhost = _node3;\n setInlineStyles(_node3, {\n opacity: 0,\n visibility: 'hidden'\n });\n }\n\n continue;\n }\n\n if (transitionDuration) {\n setTransitionDuration(_node3, transitionDuration);\n }\n\n if (this.axis.x) {\n if (this.axis.y) {\n if (mustShiftForward || index < this.index && (sortingOffset.left + windowScrollDelta.left - offset.width <= edgeOffset.left && sortingOffset.top + windowScrollDelta.top <= edgeOffset.top + offset.height || sortingOffset.top + windowScrollDelta.top + offset.height <= edgeOffset.top)) {\n translate.x = this.width + this.marginOffset.x;\n\n if (edgeOffset.left + translate.x > this.containerBoundingRect.width - offset.width) {\n if (nextNode) {\n translate.x = nextNode.edgeOffset.left - edgeOffset.left;\n translate.y = nextNode.edgeOffset.top - edgeOffset.top;\n }\n }\n\n if (this.newIndex === null) {\n this.newIndex = index;\n }\n } else if (mustShiftBackward || index > this.index && (sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left && sortingOffset.top + windowScrollDelta.top + offset.height >= edgeOffset.top || sortingOffset.top + windowScrollDelta.top + offset.height >= edgeOffset.top + height)) {\n translate.x = -(this.width + this.marginOffset.x);\n\n if (edgeOffset.left + translate.x < this.containerBoundingRect.left + offset.width) {\n if (prevNode) {\n translate.x = prevNode.edgeOffset.left - edgeOffset.left;\n translate.y = prevNode.edgeOffset.top - edgeOffset.top;\n }\n }\n\n this.newIndex = index;\n }\n } else {\n if (mustShiftBackward || index > this.index && sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left) {\n translate.x = -(this.width + this.marginOffset.x);\n this.newIndex = index;\n } else if (mustShiftForward || index < this.index && sortingOffset.left + windowScrollDelta.left <= edgeOffset.left + offset.width) {\n translate.x = this.width + this.marginOffset.x;\n\n if (this.newIndex == null) {\n this.newIndex = index;\n }\n }\n }\n } else if (this.axis.y) {\n if (mustShiftBackward || index > this.index && sortingOffset.top + windowScrollDelta.top + offset.height >= edgeOffset.top) {\n translate.y = -(this.height + this.marginOffset.y);\n this.newIndex = index;\n } else if (mustShiftForward || index < this.index && sortingOffset.top + windowScrollDelta.top <= edgeOffset.top + offset.height) {\n translate.y = this.height + this.marginOffset.y;\n\n if (this.newIndex == null) {\n this.newIndex = index;\n }\n }\n }\n\n setTranslate3d(_node3, translate);\n nodes[i].translate = translate;\n }\n\n if (this.newIndex == null) {\n this.newIndex = this.index;\n }\n\n if (isKeySorting) {\n this.newIndex = prevIndex;\n }\n\n var oldIndex = isKeySorting ? this.prevIndex : prevIndex;\n\n if (onSortOver && this.newIndex !== oldIndex) {\n onSortOver({\n collection: this.manager.active.collection,\n index: this.index,\n newIndex: this.newIndex,\n oldIndex: oldIndex,\n isKeySorting: isKeySorting,\n nodes: nodes,\n helper: this.helper\n });\n }\n }\n }, {\n key: \"getWrappedInstance\",\n value: function getWrappedInstance() {\n invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableContainer() call');\n return this.refs.wrappedInstance;\n }\n }, {\n key: \"getContainer\",\n value: function getContainer() {\n var getContainer = this.props.getContainer;\n\n if (typeof getContainer !== 'function') {\n return findDOMNode(this);\n }\n\n return getContainer(config.withRef ? this.getWrappedInstance() : undefined);\n }\n }, {\n key: \"render\",\n value: function render() {\n var ref = config.withRef ? 'wrappedInstance' : null;\n return createElement(WrappedComponent, _extends({\n ref: ref\n }, omit(this.props, omittedProps)));\n }\n }, {\n key: \"helperContainer\",\n get: function get() {\n var helperContainer = this.props.helperContainer;\n\n if (typeof helperContainer === 'function') {\n return helperContainer();\n }\n\n return this.props.helperContainer || this.document.body;\n }\n }, {\n key: \"containerScrollDelta\",\n get: function get() {\n var useWindowAsScrollContainer = this.props.useWindowAsScrollContainer;\n\n if (useWindowAsScrollContainer) {\n return {\n left: 0,\n top: 0\n };\n }\n\n return {\n left: this.scrollContainer.scrollLeft - this.initialScroll.left,\n top: this.scrollContainer.scrollTop - this.initialScroll.top\n };\n }\n }, {\n key: \"windowScrollDelta\",\n get: function get() {\n return {\n left: this.contentWindow.pageXOffset - this.initialWindowScroll.left,\n top: this.contentWindow.pageYOffset - this.initialWindowScroll.top\n };\n }\n }]);\n\n return WithSortableContainer;\n }(Component), _defineProperty(_class, \"displayName\", provideDisplayName('sortableList', WrappedComponent)), _defineProperty(_class, \"defaultProps\", defaultProps), _defineProperty(_class, \"propTypes\", propTypes), _defineProperty(_class, \"childContextTypes\", {\n manager: PropTypes.object.isRequired\n }), _temp;\n}\n\nvar propTypes$1 = {\n index: PropTypes.number.isRequired,\n collection: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n disabled: PropTypes.bool\n};\nvar omittedProps$1 = Object.keys(propTypes$1);\nfunction sortableElement(WrappedComponent) {\n var _class, _temp;\n\n var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n withRef: false\n };\n return _temp = _class = function (_React$Component) {\n _inherits(WithSortableElement, _React$Component);\n\n function WithSortableElement() {\n _classCallCheck(this, WithSortableElement);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(WithSortableElement).apply(this, arguments));\n }\n\n _createClass(WithSortableElement, [{\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.register();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate(prevProps) {\n if (this.node) {\n if (prevProps.index !== this.props.index) {\n this.node.sortableInfo.index = this.props.index;\n }\n\n if (prevProps.disabled !== this.props.disabled) {\n this.node.sortableInfo.disabled = this.props.disabled;\n }\n }\n\n if (prevProps.collection !== this.props.collection) {\n this.unregister(prevProps.collection);\n this.register();\n }\n }\n }, {\n key: \"componentWillUnmount\",\n value: function componentWillUnmount() {\n this.unregister();\n }\n }, {\n key: \"register\",\n value: function register() {\n var _this$props = this.props,\n collection = _this$props.collection,\n disabled = _this$props.disabled,\n index = _this$props.index;\n var node = findDOMNode(this);\n node.sortableInfo = {\n collection: collection,\n disabled: disabled,\n index: index,\n manager: this.context.manager\n };\n this.node = node;\n this.ref = {\n node: node\n };\n this.context.manager.add(collection, this.ref);\n }\n }, {\n key: \"unregister\",\n value: function unregister() {\n var collection = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props.collection;\n this.context.manager.remove(collection, this.ref);\n }\n }, {\n key: \"getWrappedInstance\",\n value: function getWrappedInstance() {\n invariant(config.withRef, 'To access the wrapped instance, you need to pass in {withRef: true} as the second argument of the SortableElement() call');\n return this.refs.wrappedInstance;\n }\n }, {\n key: \"render\",\n value: function render() {\n var ref = config.withRef ? 'wrappedInstance' : null;\n return createElement(WrappedComponent, _extends({\n ref: ref\n }, omit(this.props, omittedProps$1)));\n }\n }]);\n\n return WithSortableElement;\n }(Component), _defineProperty(_class, \"displayName\", provideDisplayName('sortableElement', WrappedComponent)), _defineProperty(_class, \"contextTypes\", {\n manager: PropTypes.object.isRequired\n }), _defineProperty(_class, \"propTypes\", propTypes$1), _defineProperty(_class, \"defaultProps\", {\n collection: 0\n }), _temp;\n}\n\nexport { sortableContainer as SortableContainer, sortableContainer, sortableElement as SortableElement, sortableElement, sortableHandle as SortableHandle, sortableHandle, arrayMove };\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport interface TabPanelClasses {\n\t/** Styles applied to the root element. */\n\troot: string;\n\tactive: string;\n\tpad: string;\n}\n\nexport function getTabPanelClass(slot: string) {\n\treturn generateUtilityClass('TabPanel', slot);\n}\n\nexport const tabPanelClasses = generateUtilityClasses('TabPanel', [\n\t'root',\n\t'active',\n\t'pad',\n]);\nexport default tabPanelClasses;\n","import React from 'react';\nimport clsx from 'clsx';\n\nimport {styled, composeClasses} from '@netx/core-components/Theme';\nimport tabPanelClasses, {\n\tgetTabPanelClass,\n\tTabPanelClasses,\n} from './tabPanelClasses';\n\nconst useUtilityClasses = (ownerState) => {\n\tconst {classes, active, disablePadding} = ownerState;\n\tconst slots = {\n\t\troot: ['root', active && 'active', !disablePadding && 'pad'],\n\t};\n\treturn composeClasses(slots, getTabPanelClass, classes);\n};\n\nconst TabPanelRoot = styled('div', {\n\tname: 'TabPanel',\n\tslot: 'Root',\n})(({theme}) => ({\n\tdisplay: 'flex',\n\tflex: '1 1 auto',\n\tminHeight: 0,\n\toverflow: 'hidden',\n\t[`&:not(.${tabPanelClasses.active})`]: {\n\t\tdisplay: 'none',\n\t},\n\t[`&.${tabPanelClasses.active}.${tabPanelClasses.pad}`]: {\n\t\tpadding: theme.spacing(2, 0, 0),\n\t},\n}));\n\nexport interface TabPanelProps\n\textends React.PropsWithChildren> {\n\tclasses?: TabPanelClasses;\n\tdisablePadding?: boolean;\n\tkeepMounted?: boolean;\n\tindex: number;\n\tvalue: number;\n}\n\n/**\n * A wrapper for tab content\\\n * To be used in conjunction with `useTabs`\n * @example\n const tabs = useTabs(options);\n return (\n <>\n \n \n \n \n ...\n ...\n >\n );\n */\nconst TabPanelPrimitive = (props: TabPanelProps) => {\n\tconst {\n\t\tchildren,\n\t\tclassName,\n\t\tdisablePadding,\n\t\tindex,\n\t\tkeepMounted,\n\t\tvalue,\n\t\t...sendProps\n\t} = props;\n\n\tconst active = value === index;\n\n\tconst ownerState = {\n\t\t...props,\n\t\tactive,\n\t};\n\tconst classes = useUtilityClasses(ownerState);\n\n\treturn (\n\t\t\n\t\t\t{keepMounted || active ? children : null}\n\t\t\n\t);\n};\n\nexport const TabPanel = React.memo(TabPanelPrimitive);\nexport default TabPanel;\n","class Subscribable {\n constructor() {\n this.listeners = [];\n this.subscribe = this.subscribe.bind(this);\n }\n\n subscribe(listener) {\n this.listeners.push(listener);\n this.onSubscribe();\n return () => {\n this.listeners = this.listeners.filter(x => x !== listener);\n this.onUnsubscribe();\n };\n }\n\n hasListeners() {\n return this.listeners.length > 0;\n }\n\n onSubscribe() {// Do nothing\n }\n\n onUnsubscribe() {// Do nothing\n }\n\n}\n\nexport { Subscribable };\n//# sourceMappingURL=subscribable.esm.js.map\n","import {useEffect, useState, useCallback, useRef} from 'react';\n\n// NOTE: ultimately we should have a user preference context but atm it is not worth doing since we\n// are so far from having our entire app wrapped/converted to react\nimport Netx from '@netx/core/bootstrap';\nimport {getPreference} from '@netx/core-user/utils/getPreference';\n\ntype PrefValue = Bool extends true\n\t? boolean\n\t: string | undefined;\ntype PrefInValue = Bool extends true\n\t? boolean\n\t: any | undefined;\ntype PrefOutValue = Bool extends true\n\t? boolean\n\t: boolean | string | number | undefined;\ntype ParseInFn> = (\n\tvalue: PrefValue,\n) => I;\ntype ParseOutFn<\n\tBool extends boolean = false,\n\tI = PrefInValue,\n\tO = PrefOutValue\n> = (value: I) => O;\n\ntype DefaultValue<\n\tBool extends boolean = false,\n\tI = PrefInValue\n> = I extends undefined ? PrefValue : I;\n\ntype Options<\n\tBool extends boolean = false,\n\tI extends PrefInValue | undefined = undefined,\n\tO extends PrefOutValue | undefined = PrefOutValue\n\t// D extends DefaultValue | undefined = undefined,\n> = {\n\tasBoolean?: Bool;\n\tdefaultValue?: DefaultValue;\n\tparseOut?: ParseOutFn : I, O>;\n} & (I extends PrefInValue\n\t? {parseIn: ParseInFn}\n\t: {parseIn?: (value: PrefValue) => PrefValue});\n\n// type UseUserPrefProps<\n// \tBool extends boolean = false,\n// \tI extends PrefInValue | undefined = undefined,\n// \tO extends PrefOutValue | undefined = PrefOutValue,\n// \tD extends DefaultValue | undefined = undefined,\n// > = {\n\n// } & (I extends PrefInValue ? {options: Options} : {options?: Options})\n\n/**\n * Get and track value for a user preference\n * @param preference User preference\n * @param asBoolean Value as boolean\n * @example\n const metadataLookupsEnabled = useUserPref('category.metadataDatasetLookupEnabled', true);\n */\nexport function useUserPref<\n\tBool extends boolean = false,\n\tI extends PrefInValue | undefined = undefined,\n\tO extends PrefOutValue | undefined = PrefOutValue\n>(preference = '', options?: Options) {\n\tconst {asBoolean, parseIn, parseOut, defaultValue = null} = options || {};\n\n\tconst parseInRef = useRef(parseIn);\n\tparseInRef.current = parseIn;\n\n\tconst parseOutRef = useRef(parseOut);\n\tparseOutRef.current = parseOut;\n\n\tconst [value, setValue] = useState : I>(\n\t\tparseIn\n\t\t\t? parseIn(getPreference(preference, asBoolean))\n\t\t\t: getPreference(preference, asBoolean),\n\t);\n\n\tuseEffect(() => {\n\t\tif (preference === '') return;\n\n\t\tconst update = () => {\n\t\t\tconst prefValue = getPreference(preference, asBoolean);\n\t\t\tsetValue(\n\t\t\t\tparseInRef.current\n\t\t\t\t\t? parseInRef.current(prefValue)\n\t\t\t\t\t: prefValue == null\n\t\t\t\t\t? defaultValue\n\t\t\t\t\t: prefValue,\n\t\t\t);\n\t\t};\n\t\tNetx.user?.prefs?.on('change sync saved', update);\n\n\t\tupdate();\n\n\t\treturn () => {\n\t\t\tNetx.user?.prefs?.off('change sync saved', update);\n\t\t};\n\t}, [preference, asBoolean, defaultValue]);\n\n\t// No need to re-evaluate the `setPref` callback when `preference` changes\n\tconst preferenceRef = useRef(preference);\n\tpreferenceRef.current = preference;\n\tconst setPref = useCallback(\n\t\t(value: I extends undefined ? PrefValue : I) => {\n\t\t\tconst prefValue = parseOutRef.current\n\t\t\t\t? parseOutRef.current(value)\n\t\t\t\t: value;\n\t\t\tsetValue(value);\n\t\t\tif (preferenceRef.current === '') return;\n\t\t\tNetx.setPreference(preferenceRef.current, prefValue);\n\t\t},\n\t\t[],\n\t);\n\n\treturn [value, setPref] as const;\n}\nexport default useUserPref;\n","import React from 'react';\n\nimport {CircularProgress, TextField} from '@mui/material';\nimport {createStyles, withStyles, WithStyles} from '@mui/styles';\nimport type {Theme} from '@netx/core-components/Theme';\n\nimport {CommonFieldPropsWithTextField} from '../../../';\n\nconst styles = (theme: Theme) =>\n\tcreateStyles({\n\t\tprogress: {\n\t\t\tposition: 'absolute',\n\t\t\tright: 11,\n\t\t\ttop: 'calc(50% - 10px)',\n\t\t},\n\t});\n\nexport interface VirtualizedInputProps\n\textends CommonFieldPropsWithTextField {\n\toptions?: string[];\n}\n\n/**\n * Input for virtualized select field\n */\nconst VirtualizedInput: React.FC<\n\tWithStyles & VirtualizedInputProps\n> = React.forwardRef(\n\t(\n\t\t{\n\t\t\tclasses,\n\t\t\terror,\n\t\t\tloading,\n\n\t\t\t...props\n\t\t},\n\t\tref: React.RefObject,\n\t) => {\n\t\treturn (\n\t\t\t\n\t\t\t\t\t\t\t{loading ? (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{props.InputProps?.endAdornment}\n\t\t\t\t\t\t>\n\t\t\t\t\t),\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t},\n);\n\nexport default withStyles(styles)(React.memo(VirtualizedInput));\n","import React, {\n\tcloneElement,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n\tChildren,\n\tuseEffect,\n\tuseRef,\n} from 'react';\nimport {createStyles, withStyles, WithStyles} from '@mui/styles';\nimport {\n\tListChildComponentProps,\n\tFixedSizeListProps,\n\tFixedSizeList,\n\tareEqual,\n} from 'react-window';\nimport {styled, Theme} from '@netx/core-components/Theme';\n\nimport useSharedRef from '@netx/core-components/hooks/useSharedRef';\n\ntype FixedSizeListEnforcedProps = Required;\n\nconst LISTBOX_PADDING = 8;\nconst ADDITIONAL_ITEM_HEIGHT = 2 * LISTBOX_PADDING;\n\nconst styles = (theme: Theme) => createStyles({});\n\nexport interface OuterElementProps {\n\t'aria-labelledby': string;\n\tclassName: string;\n\tid: string;\n\tonMouseDown(event: React.MouseEvent): void;\n\trole: string;\n}\nconst OuterElementContext = React.createContext>({});\nconst OuterElementType = React.forwardRef(\n\t(props, ref: React.Ref) => {\n\t\tconst outerProps = useContext(OuterElementContext);\n\t\treturn ;\n\t},\n);\n\nconst InnerElementRoot = styled('ul')({\n\tpadding: 0,\n\tmargin: 0,\n});\n\nconst renderRow = React.memo(\n\t({data, index, style}: ListChildComponentProps) => {\n\t\treturn cloneElement(data[index], {\n\t\t\tstyle: {\n\t\t\t\t...style,\n\t\t\t\ttop: (style.top as number) + LISTBOX_PADDING,\n\t\t\t},\n\t\t});\n\t},\n\tareEqual,\n);\nexport interface ListboxComponentProps extends OuterElementProps {\n\tinputRef: React.MutableRefObject;\n\tlistRef?: React.MutableRefObject;\n\tfixedSizeListRef?: React.MutableRefObject;\n}\n\n/**\n * Adapter for react-window's `VariableSizeList`\n * @private\n */\nconst ListboxComponent = React.forwardRef<\n\tHTMLDivElement,\n\tWithStyles & ListboxComponentProps\n>(({classes, children, inputRef, listRef, fixedSizeListRef, ...props}, ref) => {\n\tconst itemData = Children.toArray(children);\n\tconst itemCount = itemData.length;\n\tconst itemSize = 48;\n\n\tconst innerRef = useSharedRef(null, [ref]);\n\tconst innerFixedSizeListRef = useSharedRef(null, [\n\t\tfixedSizeListRef,\n\t]);\n\n\tconst justLoopedToRef = useRef(-1);\n\n\t// The autocomplete dropdown is a little funky with keyboard navigation\n\t// and virtualization\n\tuseEffect(() => {\n\t\tconst handleKeydown = (event) => {\n\t\t\tif (!innerFixedSizeListRef.current || !inputRef.current) return;\n\t\t\tlet prevent = false;\n\t\t\tconst itemCount = innerFixedSizeListRef.current.props.itemCount;\n\t\t\tconst activeIndex = parseInt(\n\t\t\t\t(\n\t\t\t\t\tinputRef.current.getAttribute('aria-activedescendant') || '-1'\n\t\t\t\t)?.replace(/^.*-option-/, ''),\n\t\t\t);\n\t\t\tif (activeIndex < 0) return;\n\n\t\t\tjustLoopedToRef.current = -1;\n\t\t\tswitch (event.key) {\n\t\t\t\tcase 'ArrowUp': {\n\t\t\t\t\tif (activeIndex === 0 && itemCount > 1) {\n\t\t\t\t\t\tjustLoopedToRef.current = itemCount - 1;\n\t\t\t\t\t\tinnerFixedSizeListRef.current.scrollTo(\n\t\t\t\t\t\t\t(itemCount - 1) * itemSize + LISTBOX_PADDING,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprevent = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'ArrowDown': {\n\t\t\t\t\tif (activeIndex === itemCount - 1 && itemCount > 1) {\n\t\t\t\t\t\tjustLoopedToRef.current = 0;\n\t\t\t\t\t\tinnerFixedSizeListRef.current.scrollTo(0);\n\t\t\t\t\t\tprevent = true;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'End':\n\t\t\t\t\tjustLoopedToRef.current = itemCount - 1;\n\t\t\t\t\tinnerFixedSizeListRef.current.scrollTo(\n\t\t\t\t\t\t(itemCount - 1) * itemSize + LISTBOX_PADDING,\n\t\t\t\t\t);\n\t\t\t\t\tprevent = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Home':\n\t\t\t\t\tjustLoopedToRef.current = 0;\n\t\t\t\t\tinnerFixedSizeListRef.current.scrollTo(0);\n\t\t\t\t\tprevent = true;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (prevent) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleKeydown, {capture: true});\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeydown, {capture: true});\n\t\t};\n\t}, []);\n\n\t// The focus event from the underlying `useAutocomplete` is firing before the item can be rendered\n\t// because the call to render comes after the mouse event\n\tconst handleItemRendered = useCallback<\n\t\tFixedSizeListEnforcedProps['onItemsRendered']\n\t>((props) => {\n\t\tif (!innerFixedSizeListRef.current || !innerRef.current) return;\n\n\t\tconst event = new MouseEvent('mouseover', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t});\n\n\t\tconst hasFocused = () =>\n\t\t\tinnerRef.current?.querySelector('[data-focus=\"true\"]') !== null;\n\n\t\tif (justLoopedToRef.current > -1) {\n\t\t\tconst option = innerRef.current?.querySelector(\n\t\t\t\t`[id*=\"option-${justLoopedToRef.current}\"]`,\n\t\t\t);\n\t\t\tif (option && !hasFocused()) option.dispatchEvent(event);\n\t\t\tjustLoopedToRef.current = -1;\n\t\t}\n\t}, []);\n\n\t// if you give it the actual height of what all the items would be\n\t// it will actually render them all - just keep in mind:\n\t// this is just the height of the content we want to display/in the\n\t// DOM\n\tconst height = useMemo(\n\t\t() => (itemCount > 8 ? 8 * itemSize : itemCount * itemSize), //itemData.map(getChildSize).reduce((a, b) => a + b, 0),\n\t\t[itemCount, itemSize],\n\t);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{renderRow}\n\t\t\t\t\n\t\t\t\n\t\t
\n\t);\n});\n\nexport default withStyles(styles)(React.memo(ListboxComponent));\n","import React, {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport {ConfirmationDialog, ConfirmationOptions} from './ConfirmationDialog';\n\nexport interface Options extends Omit {\n\tcatchOnCancel?: boolean;\n}\n\nexport type ConfirmationServiceContextType = (\n\toptions: Options,\n) => Promise;\n\nconst ConfirmationServiceContext = createContext<\n\tConfirmationServiceContextType | undefined\n>(undefined);\n\nexport const useConfirmation = () => {\n\tconst context = useContext(ConfirmationServiceContext);\n\tif (context === undefined) {\n\t\tthrow new Error(\n\t\t\t'`useConfirmation` must be used within a `ConfirmationServiceProvider`',\n\t\t);\n\t}\n\treturn context;\n};\n\n// due to how jsx is parsed, gernerics with only a single argument must extend\n// something or the parsing breaks\n// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint\nexport const ConfirmationServiceProvider = ({\n\tchildren,\n}) => {\n\tconst [catchOnCancel, setCatchOnCancel] = useState(false);\n\tconst [confirmationState, setConfirmationState] = useState();\n\n\tconst awaitingPromiseRef = useRef<{\n\t\tresolve: (...args: any) => void | Promise;\n\t\treject: () => void;\n\t}>();\n\n\tconst openConfirmation = useCallback(\n\t\t({catchOnCancel = false, ...options}: Options) => {\n\t\t\tsetCatchOnCancel(catchOnCancel);\n\t\t\tsetConfirmationState(options);\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tawaitingPromiseRef.current = {resolve, reject};\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleClose = useCallback(() => {\n\t\tcatchOnCancel && awaitingPromiseRef.current?.reject();\n\t\tawaitingPromiseRef.current = undefined;\n\t\tsetConfirmationState(undefined);\n\t}, [catchOnCancel]);\n\n\tconst handleSubmit = useCallback((...args: any) => {\n\t\tawaitingPromiseRef.current?.resolve(...args);\n\t\tsetConfirmationState(undefined);\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t\n\n\t\t\t\n\t\t>\n\t);\n};\n","export enum DrawerAnchor {\n\tLEFT = 'left',\n\tRIGHT = 'right',\n\tTOP = 'top',\n\tBOTTOM = 'bottom',\n}\n\nexport enum DrawerVariant {\n\tPERMANENT = 'permanent',\n\tTEMPORARY = 'temporary',\n}\n","import {i18n} from '@netx/core/i18n';\n\nexport const DrawerActionLabel = {\n\tCOLLAPSE: i18n.t('i18n.collapse'),\n\tCLOSE: i18n.t('i18n.close'),\n\tUNCOLLAPSE: i18n.t('i18n.uncollapse'),\n};\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const DRAWER_TOOLBAR_CLASS_NAME = 'DrawerToolbar';\nexport const DRAWER_TOOLBAR_CLASS_SLOTS = ['root', 'title', 'toggle'] as const;\n\nexport type DrawerToolbarClassSlot = typeof DRAWER_TOOLBAR_CLASS_SLOTS[number];\n\nexport interface DrawerToolbarClasses {\n\troot: string;\n\ttitle: string;\n\ttoggle: string;\n\n\tanchorLeft: string;\n\tanchorRight: string;\n\topen: string;\n}\n\nexport type DrawerToolbarClassKey = keyof DrawerToolbarClasses;\n\nexport const getDrawerToolbarUtilityClass = (slot: DrawerToolbarClassSlot) =>\n\tgenerateUtilityClass(DRAWER_TOOLBAR_CLASS_NAME, slot);\n\nexport const drawerToolbarClasses: DrawerToolbarClasses = generateUtilityClasses(\n\tDRAWER_TOOLBAR_CLASS_NAME,\n\t['root', 'anchorLeft', 'anchorRight', 'open', 'title', 'toggle'],\n);\n\nexport default drawerToolbarClasses;\n","import React, {useMemo} from 'react';\nimport clsx from 'clsx';\n\nimport {\n\tfaChevronLeft as ToggleIcon,\n\tfaTimes as TimesIcon,\n} from '@fortawesome/pro-solid-svg-icons';\nimport {unstable_capitalize as capitalize} from '@mui/utils';\nimport {\n\tIconButton,\n\tIconButtonProps,\n\ticonButtonClasses,\n} from '@netx/core-components/IconButton';\nimport {composeClasses, styled, WithClasses} from '@netx/core-components/Theme';\nimport {Title} from '@netx/core-components/Title';\nimport {DrawerAnchor} from './constants';\nimport {DrawerActionLabel} from './locales';\nimport {\n\tdrawerToolbarClasses,\n\tgetDrawerToolbarUtilityClass,\n\tDrawerToolbarClasses,\n\tDRAWER_TOOLBAR_CLASS_NAME,\n} from './drawerToolbarClasses';\n\nexport type DrawerOwnerState = WithClasses<\n\tDrawerToolbarClasses,\n\t{\n\t\tanchor: DrawerAnchor;\n\t\topen: boolean;\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: DrawerOwnerState) => {\n\tconst {classes, anchor, open} = ownerState;\n\tconst slots = {\n\t\troot: ['root', `anchor${capitalize(anchor)}`, open && 'open'],\n\t\ttoggle: ['toggle'],\n\t\ttitle: ['title'],\n\t};\n\treturn composeClasses(slots, getDrawerToolbarUtilityClass, classes);\n};\n\nconst DrawerToolbarRoot = styled('div', {\n\tname: DRAWER_TOOLBAR_CLASS_NAME,\n\tslot: 'Root',\n})(({theme}) => ({\n\tdisplay: 'flex',\n\talignItems: 'center',\n\tjustifyContent: 'flex-start',\n\tpadding: theme.spacing(0, 1.5, 0, 0.75),\n\tzIndex: 3,\n\t...(theme.mixins.toolbar as React.CSSProperties),\n\t[`&.${drawerToolbarClasses.anchorLeft}`]: {\n\t\t[`& .${drawerToolbarClasses.title}`]: {\n\t\t\tmarginRight: theme.spacing(1),\n\t\t},\n\t},\n\t[`&.${drawerToolbarClasses.anchorRight}`]: {\n\t\t[`& .${drawerToolbarClasses.title}`]: {\n\t\t\tmarginLeft: theme.spacing(1),\n\t\t},\n\t},\n\t[`&:not(.${drawerToolbarClasses.open})`]: {\n\t\t[`& .${drawerToolbarClasses.title}`]: {\n\t\t\tvisibility: 'hidden',\n\t\t\tmargin: 0,\n\t\t},\n\t},\n}));\n\nconst DrawerTitle = styled(Title, {\n\tname: DRAWER_TOOLBAR_CLASS_NAME,\n\tslot: 'Title',\n})(({theme}) => ({\n\tflex: '1 1 auto',\n\toverflow: 'hidden',\n\ttextOverflow: 'ellipsis',\n}));\n\nconst DrawerToggle = styled(IconButton, {\n\tname: DRAWER_TOOLBAR_CLASS_NAME,\n\tslot: 'Toggle',\n})(({theme}) => ({\n\t[`& .${iconButtonClasses.icon}`]: {\n\t\ttransition: theme.transitions.create('transform'),\n\t},\n}));\n\ntype IconButtonMethods = Required>;\n\nexport interface DrawerToolbarProps\n\textends React.DetailedHTMLProps<\n\t\t\tReact.HTMLAttributes,\n\t\t\tHTMLDivElement\n\t\t>,\n\t\tWithClasses<\n\t\t\tDrawerToolbarClasses,\n\t\t\t{\n\t\t\t\t// TODO: top and bottom are not supported just yet\n\t\t\t\tanchor: DrawerAnchor;\n\t\t\t\tcancelAsClose?: boolean;\n\t\t\t\tactions?: React.ReactNode;\n\t\t\t\tonCollapseToggle?: IconButtonMethods['onClick'];\n\t\t\t\topen?: boolean;\n\t\t\t\tsecondaryTitle?: React.ReactNode;\n\t\t\t\ttitle?: string;\n\t\t\t}\n\t\t> {}\n\nexport const DrawerToolbarPrimitive = ({\n\tclasses: _classes,\n\tchildren,\n\tclassName,\n\n\tactions,\n\tanchor,\n\tcancelAsClose,\n\tonCollapseToggle,\n\topen,\n\tsecondaryTitle,\n\ttitle = '',\n\t...props\n}: DrawerToolbarProps) => {\n\tconst ownerState = {\n\t\tclasses: _classes,\n\t\tanchor,\n\t\topen: open === true,\n\t};\n\n\tconst classes = useUtilityClasses(ownerState);\n\n\tconst Toggle = useMemo(\n\t\t() => (\n\t\t\t\n\t\t),\n\t\t[classes, anchor, open, onCollapseToggle, cancelAsClose],\n\t);\n\n\tconst Title = useMemo(\n\t\t() => (\n\t\t\t\n\t\t),\n\t\t[classes, secondaryTitle, title],\n\t);\n\n\tconst Actions = (open && actions) || null;\n\n\treturn (\n\t\t\n\t\t\t{anchor === DrawerAnchor.RIGHT ? (\n\t\t\t\t<>\n\t\t\t\t\t{Toggle}\n\t\t\t\t\t{Title}\n\t\t\t\t\t{Actions}\n\t\t\t\t>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t{Actions}\n\t\t\t\t\t{Title}\n\t\t\t\t\t{Toggle}\n\t\t\t\t>\n\t\t\t)}\n\t\t\n\t);\n};\n\nexport const DrawerToolbar = React.memo(DrawerToolbarPrimitive);\n\nexport default DrawerToolbar;\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const DRAWER_CLASS_NAME = 'Drawer';\nexport const DRAWER_CLASS_SLOTS = ['root', 'content', 'drawer'] as const;\n\nexport type DrawerClassSlot = typeof DRAWER_CLASS_SLOTS[number];\n\nexport interface DrawerClasses {\n\troot: string;\n\tcontent: string;\n\tdrawer: string;\n\n\tresizing: string;\n\topen: string;\n\ttemporary: string;\n}\n\nexport type DrawerClassKey = keyof DrawerClasses;\n\nexport const getDrawerUtilityClass = (slot: DrawerClassSlot) =>\n\tgenerateUtilityClass(DRAWER_CLASS_NAME, slot);\n\nexport const drawerClasses: DrawerClasses = generateUtilityClasses(\n\tDRAWER_CLASS_NAME,\n\t['root', 'content', 'drawer', 'open', 'resizing', 'temporary'],\n);\n\nexport default drawerClasses;\n","import React, {useCallback, useEffect, useState} from 'react';\nimport clsx from 'clsx';\n\nimport {FocusTrap} from '@mui/base';\nimport {\n\tDrawer as MuiDrawer,\n\tDrawerProps as MuiDrawerProps,\n\tpaperClasses,\n} from '@mui/material';\nimport {duration} from '@mui/material/styles/createTransitions';\nimport {\n\tDragResize,\n\tDragResizeDirection,\n\tdragResizeHandleClasses,\n} from '@netx/core-components/DragResize';\nimport useWhenChangedEffect from '@netx/core-components/hooks/useWhenChangedEffect';\nimport {useDocumentKeyDown} from '@netx/core-components/hooks/useDocumentKeyDown';\nimport {IconButtonProps} from '@netx/core-components/IconButton';\nimport {\n\tcomposeClasses,\n\tstyled,\n\tWithClasses,\n\tWithMuiPropOverrides,\n} from '@netx/core-components/Theme';\nimport {DrawerToolbar} from './DrawerToolbar';\nimport {DrawerAnchor, DrawerVariant} from './constants';\nimport {\n\tdrawerClasses,\n\tgetDrawerUtilityClass,\n\tDrawerClasses,\n\tDRAWER_CLASS_NAME,\n} from './drawerClasses';\n\nexport type DrawerOwnerState = WithClasses<\n\tDrawerClasses,\n\t{\n\t\topen: boolean;\n\t\tresizing: boolean;\n\t\ttemporary: boolean;\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: DrawerOwnerState) => {\n\tconst {classes, open, resizing, temporary} = ownerState;\n\tconst slots = {\n\t\troot: [\n\t\t\t'root',\n\t\t\topen && 'open',\n\t\t\tresizing && 'resizing',\n\t\t\ttemporary && 'temporary',\n\t\t],\n\t\tcontent: ['content'],\n\t\tdrawer: ['drawer', temporary && 'temporary'],\n\t};\n\treturn composeClasses(slots, getDrawerUtilityClass, classes);\n};\n\nconst DEFAULT_WIDTH = 300;\n\nconst DrawerRoot = styled(DragResize, {\n\tname: DRAWER_CLASS_NAME,\n\tslot: 'Root',\n})(({theme}) => ({\n\tdisplay: 'flex',\n\tposition: 'relative',\n\twhiteSpace: 'nowrap',\n\t[`&:not(:hover):not(.${drawerClasses.resizing}) .${dragResizeHandleClasses.root}`]:\n\t\t{\n\t\t\topacity: 0,\n\t\t},\n\t[`&.${drawerClasses.resizing}`]: {\n\t\twillChange: 'width',\n\t\t[`& .${drawerClasses.content}`]: {\n\t\t\tpointerEvents: 'none',\n\t\t},\n\t},\n\t[`&.${drawerClasses.open}`]: {\n\t\twidth: DEFAULT_WIDTH,\n\t\t[`&:not(.${drawerClasses.resizing})`]: {\n\t\t\ttransition: theme.transitions.create(['width', 'min-width'], {\n\t\t\t\teasing: theme.transitions.easing.sharp,\n\t\t\t\tduration: theme.transitions.duration.enteringScreen,\n\t\t\t}),\n\t\t},\n\t},\n\t[`&:not(.${drawerClasses.open})`]: {\n\t\ttransition: theme.transitions.create(['width', 'min-width'], {\n\t\t\teasing: theme.transitions.easing.sharp,\n\t\t\tduration: theme.transitions.duration.leavingScreen,\n\t\t}),\n\t\toverflowX: 'hidden',\n\t\twidth: `61px !important`,\n\t\tcursor: 'pointer',\n\t\t[`& .${drawerClasses.content}`]: {\n\t\t\tdisplay: 'none',\n\t\t},\n\t},\n\t[`&.${drawerClasses.temporary}`]: {\n\t\tposition: 'absolute',\n\t\tright: 0,\n\t\tbottom: 0,\n\t\ttop: 0,\n\t\t[`&:not(.${drawerClasses.open})`]: {\n\t\t\tposition: 'absolute',\n\t\t\twidth: `0 !important`,\n\t\t},\n\t},\n\t[`&:not(.${drawerClasses.temporary})`]: {\n\t\tminWidth: 61,\n\t},\n}));\n\nconst DrawerWrapper = styled(MuiDrawer)(({theme}) => ({\n\tdisplay: 'flex',\n\tflex: '1 1 auto',\n\tminHeight: 0,\n\t// Undo some paper styles in the drawer\n\t[`& .${paperClasses.root}`]: {\n\t\tflex: '1 1 auto',\n\t\theight: 'auto',\n\t\tminHeight: 0,\n\t\toverflow: 'visible',\n\t\tposition: 'relative',\n\t\twidth: '100%',\n\t\tzIndex: 'initial',\n\t},\n}));\n\nconst DrawerContent = styled('div')(({theme}) => ({\n\tflex: '1 1 auto',\n\tdisplay: 'flex',\n\tflexDirection: 'column',\n\tminHeight: 0,\n\toverflow: 'hidden',\n\tposition: 'relative',\n}));\n\ntype MuiDrawerMethods = Required>;\ntype IconButtonMethods = Required>;\n\nexport interface DrawerProps\n\textends Omit<\n\t\t\tWithMuiPropOverrides,\n\t\t\t'anchor' | 'classes' | 'variant'\n\t\t>,\n\t\tWithClasses<\n\t\t\tDrawerClasses,\n\t\t\t{\n\t\t\t\tanchor?: DrawerAnchor;\n\t\t\t\tcancelAsClose?: boolean;\n\t\t\t\theaderActions?: React.ReactNode;\n\t\t\t\tkeepMounted?: boolean;\n\t\t\t\tonCollapseToggle?: (collapsed: boolean) => void;\n\t\t\t\tonEntered?: () => void;\n\t\t\t\tonExited?: () => void;\n\t\t\t\tonResized?: (width: number) => void;\n\t\t\t\toverflowParent: React.RefObject;\n\t\t\t\tsecondaryTitle?: React.ReactNode;\n\t\t\t\ttitle?: string;\n\t\t\t\twidth?: number;\n\t\t\t\tvariant?: DrawerVariant;\n\t\t\t}\n\t\t> {}\n\nexport const DrawerPrimitive = ({\n\tclasses: _classes,\n\tchildren,\n\tclassName,\n\n\tanchor = DrawerAnchor.RIGHT,\n\tcancelAsClose,\n\theaderActions,\n\tkeepMounted = true,\n\tonCollapseToggle,\n\tonEntered,\n\tonExited,\n\tonResized,\n\topen = true,\n\toverflowParent,\n\tsecondaryTitle,\n\tstyle,\n\ttitle = '',\n\twidth = 0,\n\tvariant = DrawerVariant.PERMANENT,\n\t...props\n}: DrawerProps) => {\n\tconst [exited, setExited] = useState(!open);\n\tconst [isOpen, setIsOpen] = useState(open);\n\tconst [resizing, setResizing] = useState(false);\n\n\tconst temporary = variant === DrawerVariant.TEMPORARY;\n\n\tuseEffect(() => {\n\t\tsetIsOpen(open);\n\t}, [open]);\n\n\tuseWhenChangedEffect(\n\t\tisOpen,\n\t\tuseCallback(\n\t\t\t(isOpen) => {\n\t\t\t\tif (!isOpen) {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetExited(true);\n\t\t\t\t\t\tonExited?.();\n\t\t\t\t\t}, duration.leavingScreen);\n\t\t\t\t} else {\n\t\t\t\t\tsetExited(false);\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tonEntered?.();\n\t\t\t\t\t}, duration.enteringScreen + 20);\n\t\t\t\t}\n\n\t\t\t\tonCollapseToggle?.(isOpen);\n\t\t\t},\n\t\t\t[onEntered, onExited, onCollapseToggle],\n\t\t),\n\t);\n\n\tuseDocumentKeyDown(\n\t\t(event) => {\n\t\t\tswitch (event.key) {\n\t\t\t\tcase 'Escape':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tsetIsOpen(false);\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdisabled: !isOpen || !cancelAsClose,\n\t\t},\n\t);\n\n\tconst handleDrawerToggle = useCallback(\n\t\t(event) => {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\tsetIsOpen((isOpen) => !isOpen);\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleDrawerClick = useCallback(\n\t\t(event) => {\n\t\t\tif (isOpen) return;\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\tsetIsOpen(true);\n\t\t},\n\t\t[isOpen],\n\t);\n\n\tconst handleDrawerKeyDown = useCallback(\n\t\t(event) => {\n\t\t\tif (isOpen) return;\n\t\t\tconst key = event.keyCode || event.which;\n\t\t\t// Only `enter` and `spacebar` keys\n\t\t\tif (![13, 32].includes(key)) return;\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\tsetIsOpen(true);\n\t\t},\n\t\t[isOpen],\n\t);\n\n\tconst classes = useUtilityClasses({\n\t\tclasses: _classes,\n\t\topen: isOpen,\n\t\tresizing,\n\t\ttemporary,\n\t});\n\n\treturn (\n\t\t setResizing(true)}\n\t\t\tonResizeEnded={(size) => {\n\t\t\t\tsetResizing(false);\n\t\t\t\tonResized?.(size);\n\t\t\t}}\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{exited && !keepMounted ? null : children}\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nexport const Drawer = React.memo(DrawerPrimitive);\n\nexport default Drawer;\n","import React from 'react';\nimport Drawer, {DrawerProps} from './Drawer';\n\nexport interface WithDrawerProps {\n\tDrawerProps: DrawerProps;\n}\n\nexport default function withDrawer(Component: C) {\n\treturn ({\n\t\tDrawerProps,\n\t\t...props\n\t}: WithDrawerProps &\n\t\tJSX.IntrinsicAttributes &\n\t\tJSX.LibraryManagedAttributes>) => {\n\t\treturn (\n\t\t\t\n\t\t\t\t>)}\n\t\t\t\t/>\n\t\t\t\n\t\t);\n\t};\n}\n","export let contactSheet = {\n\tdefaultEngine: 'java',\n\tdefaultTemplates: {\n\t\t'1x1': {\n\t\t\tmaxAttributes: 10,\n\t\t},\n\t\t'2x2': {\n\t\t\tmaxAttributes: 5,\n\t\t},\n\t\t'3x3': {\n\t\t\tmaxAttributes: 3,\n\t\t},\n\t},\n};\n\nexport const ignoreDownloadWarningTypes = ['contactSheet', 'metadata'];\n\nexport let types = {\n\toriginal: 'original',\n\tproxy: 'proxy',\n\tassetView: 'assetView',\n\tpresetProcess: 'presetProcess',\n\thistorical: 'historical',\n\tmetadata: 'metadata',\n\tcontactSheet: 'contactSheet',\n\tthumb: 'thumb',\n\ttemplateCustomization: 'templateCustomization',\n\tpreview: 'preview',\n\t'1x1': '1x1',\n\t'2x2': '2x2',\n\t'3x3': '3x3',\n};\n\nexport default {contactSheet, ignoreDownloadWarningTypes, types};\n","/**\n * A time input element (not AM/PM) but hh::mm:ss:fff\n * Depends on document-register-element polyfill (http://caniuse.com/#feat=custom-elements)\n * @author Justin Sephiroth Enos \n */\nimport {pad} from '@netx/core/lib/underscore-netx';\n\n// Polyfill needed for Edge\nimport '@webcomponents/custom-elements';\n\n// Known issues:\n// Firefox number inputs will not respect padding numbers with leading 0s\n\nclass NxTime extends HTMLElement {\n\tget value() {\n\t\treturn this.getTotalSeconds();\n\t}\n\n\tset value(newValue) {\n\t\treturn this.parseSecondsToInputs(parseFloat(newValue), true);\n\t}\n\n\tstatic get observedAttributes() {\n\t\treturn ['disabled'];\n\t}\n\n\tconnectedCallback() {\n\t\t/**\n\t\t * @type {object}\n\t\t */\n\t\tthis.inputs = {};\n\n\t\t// Create an input for each thing\n\t\t['hour', 'minute', 'second', 'millisecond'].forEach((thing, idx) => {\n\t\t\t// Create and append input\n\t\t\tlet input = (this.inputs[thing] = document.createElement('input'));\n\t\t\tinput.setAttribute('type', 'number');\n\t\t\tinput.setAttribute('name', thing);\n\t\t\tinput.setAttribute('title', thing);\n\t\t\tthis.appendChild(input);\n\n\t\t\t// Listen for input change\n\t\t\tinput.addEventListener('change', e => {\n\t\t\t\t// For our eyes only\n\t\t\t\te.stopPropagation();\n\t\t\t\t// Parse inputs\n\t\t\t\tthis.parseSecondsToInputs();\n\t\t\t});\n\n\t\t\t// Stop scroll incrementing\n\t\t\tinput.addEventListener('mousewheel', e => {\n\t\t\t\te.preventDefault();\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\tinput.addEventListener('DOMMouseScroll', e => {\n\t\t\t\te.preventDefault();\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t// Create and append \":\" separator\n\t\t\tif (thing === 'hour' || thing == 'minute') {\n\t\t\t\tconst separator = document.createElement('span');\n\t\t\t\tconst separatorText = document.createTextNode(':');\n\t\t\t\tseparator.appendChild(separatorText);\n\t\t\t\tthis.appendChild(separator);\n\t\t\t}\n\t\t\t// Create and append \".\" separator\n\t\t\telse if (thing === 'second') {\n\t\t\t\tconst separator = document.createElement('span');\n\t\t\t\tconst separatorText = document.createTextNode('.');\n\t\t\t\tseparator.appendChild(separatorText);\n\t\t\t\tthis.appendChild(separator);\n\t\t\t}\n\t\t});\n\n\t\t_.defer(() => {\n\t\t\t// Set default time if none currently\n\t\t\tif(!this.getTotalSeconds()) {\n\t\t\t\t// Set initial time if one was provided on this element's value\n\t\t\t\tconst val = parseFloat(this.getAttribute('value'));\n\t\t\t\tthis.parseSecondsToInputs(!isNaN(val) ? val : 0, true);\n\t\t\t}\n\t\t});\n\t}\n\n\tattributeChangedCallback(name, previousValue, value) {\n\t\t// This is the only attribute I see mattering... for now\n\t\tif (name === 'disabled') {\n\t\t\t// Vars\n\t\t\tconst inputs = this.inputs;\n\t\t\t// Loop over inputs and mirror our attribute\n\t\t\tfor (let key in inputs) {\n\t\t\t\tif (inputs.hasOwnProperty(key)) {\n\t\t\t\t\tinputs[key][value ? 'setAttribute' : 'removeAttribute'](name, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tgetChangeEvent() {\n\t\tconst event = document.createEvent('Event');\n\t\tevent.initEvent('change', true, true);\n\t\treturn event;\n\t}\n\n\t/**\n\t * @method\n\t * @return {number} Total seconds\n\t */\n\tgetTotalSeconds() {\n\t\t// Vars\n\t\tlet seconds = 0;\n\n\t\t// Loop over inputs and tally up seconds\n\t\tfor (let key in this.inputs) {\n\t\t\tif (this.inputs.hasOwnProperty(key)) {\n\t\t\t\tlet val = parseInt(this.inputs[key].value);\n\t\t\t\tif (isNaN(val)) val = 0;\n\t\t\t\tif (key === 'hour') val = val * 3600;\n\t\t\t\telse if (key === 'minute') val = val * 60;\n\t\t\t\telse if (key === 'millisecond') val = val / 1000;\n\t\t\t\tseconds += val;\n\t\t\t}\n\t\t}\n\n\t\treturn seconds;\n\t}\n\n\t/**\n\t * @method\n\t * @param {number} seconds Seconds to set (will default to the inputs total value)\n\t * @param {boolean} bypassChangeEvent Set to true when you do not wish to fire a change event (like when this was set from the outside progrmatically)\n\t */\n\tparseSecondsToInputs(seconds, bypassChangeEvent) {\n\t\t// If no seconds (or invalid seconds) were passed, use this.getTotalSeconds();\n\t\tif (_.isUndefined(seconds) || isNaN(seconds))\n\t\t\tseconds = this.getTotalSeconds();\n\n\t\t// Vars\n\t\tlet time = seconds;\n\t\tlet timeObj = {\n\t\t\thour: 0,\n\t\t\tminute: 0,\n\t\t\tsecond: 0,\n\t\t\tmillisecond: 0,\n\t\t};\n\n\t\t// Parse seconds to respective time pieces\n\t\ttimeObj.hour = Math.floor(time / 3600);\n\t\ttime -= timeObj.hour * 3600;\n\t\ttimeObj.minute = Math.floor(time / 60);\n\t\ttime -= Math.floor(timeObj.minute * 60);\n\t\ttimeObj.second = Math.floor(time);\n\t\ttimeObj.millisecond = Math.round((time - timeObj.second) * 1000);\n\n\t\t// Loop over inputs and set proper values\n\t\tfor (let key in this.inputs) {\n\t\t\tif (this.inputs.hasOwnProperty(key)) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'hour':\n\t\t\t\t\tcase 'minute':\n\t\t\t\t\tcase 'second':\n\t\t\t\t\t\t// 00\n\t\t\t\t\t\tthis.inputs[key].value = pad(timeObj[key], 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'millisecond':\n\t\t\t\t\t\t// 000\n\t\t\t\t\t\tthis.inputs[key].value = pad(timeObj[key], 3);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if differs\n\t\tif (!bypassChangeEvent) {\n\t\t\tthis.dispatchEvent(this.getChangeEvent());\n\t\t}\n\n\t\t// Store\n\t\treturn seconds;\n\t}\n}\n\n// Our custom element\nwindow.customElements.define('nx-time', NxTime);\n\nexport default NxTime;\n","// Error boundaries must currently be classes see `ErrorBoundary` for our function wrapper\n// If you use this file directly you will not have a good time trying to get themed styles in\n\nimport React, {PropsWithChildren} from 'react';\n\nimport Button from '@netx/core-components/Button';\nimport {faExclamationCircle as ExclamationIcon} from '@fortawesome/pro-regular-svg-icons';\n\nimport {i18n} from '@netx/core/i18n';\n\nimport Fallback from '../Drawer/Fallback';\n\ninterface ErrorBoundaryState {\n\thasError: boolean;\n}\n\ninterface ErrorBoundaryProps {\n\tclassName?: string;\n\tstyles?: any;\n}\n\nclass ErrorBoundary extends React.Component<\n\tPropsWithChildren\n> {\n\tstate: ErrorBoundaryState;\n\n\tconstructor(props: ErrorBoundaryProps) {\n\t\tsuper(props);\n\t\tthis.state = {hasError: false};\n\t}\n\n\tstatic getDerivedStateFromError(error) {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn {hasError: true};\n\t}\n\n\tcomponentDidCatch(error, errorInfo) {\n\t\t// You can also log the error to an error reporting service\n\t\tconsole.log(error, errorInfo);\n\t}\n\n\trender() {\n\t\tconst {className, styles} = this.props;\n\t\tif (this.state.hasError) {\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t);\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n\n\treset() {\n\t\tthis.setState({hasError: false});\n\t}\n}\n\nexport default ErrorBoundary;\n","// Wrapper for the error boundary class for easier passing of styles with theme support\nimport React from 'react';\nimport type {CSSProperties} from '@mui/styles/withStyles';\n\nimport {createStyles, withStyles, WithStyles} from '@mui/styles';\nimport {useTheme, Theme} from '@netx/core-components/Theme';\n\nimport ErrorBoundaryClass from './_ErrorBoundary';\n\nconst styles = (theme: Theme) =>\n\tcreateStyles({\n\t\troot: {\n\t\t\tdisplay: 'flex',\n\t\t\tflex: '1 1 auto',\n\t\t\tflexDirection: 'column',\n\t\t\twidth: '100%',\n\t\t},\n\t});\n\nexport interface ErrorBoundaryProps {\n\tstyles?: (theme: Theme) => CSSProperties | CSSProperties;\n}\n\n/**\n * Wrapper for the error boundary class for easier passing of styles with theme support\n *\n * DEVNOTE: It is advised to place an error boundary at the highest level possible \\\n * Due to the nature of our app we will currently be wrapping the highest level \\\n * of our components as we can (without having a react wrapper around the whole app) \\\n * As we move forward and make progress we can remove the wrapper from lower levels \\\n * and keep moving up the tree until (one day) we get to the top of the app\n */\n// TODO: convert this to styled and anything that wants to use it can just wrap in styled\n// and we can do away with this `any` (`WithStyles` is deprecated and does not play well\n// with ts)\nconst ErrorBoundary = ({\n\tclasses,\n\tchildren,\n\tstyles,\n}: React.PropsWithChildren & ErrorBoundaryProps>) => {\n\tconst theme = useTheme();\n\t// Support passing theme to callback for styles\n\tconst _styles = typeof styles === 'function' ? styles(theme) : styles;\n\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t\n\t);\n};\n\nexport default withStyles(styles)(ErrorBoundary);\n","import React from 'react';\nimport ErrorBoundary, {ErrorBoundaryProps} from './ErrorBoundary';\n\n/**\n * Wrap component in error boundary \\\n * An error boundary catches all (un-catched) errors within its children \n * \n * DEVNOTE: It is advised to place an error boundary at the highest level possible \\\n * Due to the nature of our app we will currently be wrapping the highest level \\\n * of our components as we can (without having a react wrapper around the whole app) \\\n * As we move forward and make progress we can remove the wrapper from lower levels \\\n * and keep moving up the tree until (one day) we get to the top of the app\n * @example\n import Component from 'my-component';\n const ErrorBoundariedComponent = withErrorBoundary(Component);\n ...\n const MyComponent = withErrorBoundary((props: Props) => {...});\n ...\n const MyComponent = (props: Props) => {...};\n export default withErrorBoundary(MyComponent);\n */\nconst withErrorBoundary = function <\n\tC extends React.ComponentType>\n>(Component: C, styles?: ErrorBoundaryProps['styles']) {\n\treturn (props: React.ComponentProps) => {\n\t\treturn (\n\t\t\t\n\t\t\t\t{/** i do not have the energy to deal with this - the most important thing is the outside world is getting proper typing */}\n\t\t\t\t\n\t\t\t\n\t\t);\n\t};\n};\n\nexport default withErrorBoundary;\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const DIALOG_TITLE_CLASS_NAME = 'DialogTitle';\nexport const DIALOG_TITLE_CLASS_SLOTS = [\n\t'root',\n\t'actions',\n\t'icon',\n\t'title',\n] as const;\n\nexport type DialogTitleClassSlot = typeof DIALOG_TITLE_CLASS_SLOTS[number];\n\nexport interface DialogTitleClasses {\n\troot: string;\n\tactions: string;\n\ticon: string;\n\ttitle: string;\n\n\thasIcon: string;\n}\n\nexport type DialogTitleClassKey = keyof DialogTitleClasses;\n\nexport const getDialogTitleUtilityClass = (slot: DialogTitleClassSlot) =>\n\tgenerateUtilityClass(DIALOG_TITLE_CLASS_NAME, slot);\n\nexport const dialogTitleClasses: DialogTitleClasses = generateUtilityClasses(\n\tDIALOG_TITLE_CLASS_NAME,\n\t['root', 'actions', 'hasIcon', 'icon', 'title'],\n);\n\nexport default dialogTitleClasses;\n","import React from 'react';\nimport clsx from 'clsx';\n\nimport {FontAwesomeIconProps} from '@fortawesome/react-fontawesome';\nimport {faTimes} from '@fortawesome/pro-solid-svg-icons';\nimport {\n\tDialogTitle as MuiDialogTitle,\n\tdialogTitleClasses as muiDialogClasses,\n\tDialogTitleProps as MuiDialogTitleProps,\n} from '@mui/material';\nimport IconButton from '@netx/core-components/IconButton';\nimport {\n\tcomposeClasses,\n\tstyled,\n\tWithClasses,\n\tWithMuiPropOverrides,\n} from '@netx/core-components/Theme';\nimport Title, {TitleProps} from '../Title';\nimport {\n\tdialogTitleClasses,\n\tgetDialogTitleUtilityClass,\n\tDialogTitleClasses,\n\tDIALOG_TITLE_CLASS_NAME,\n} from './dialogTitleClasses';\n\ntype DialogTitleOwnerProps = WithClasses<\n\tDialogTitleClasses,\n\t{\n\t\thasIcon?: boolean;\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: DialogTitleOwnerProps) => {\n\tconst {classes, hasIcon} = ownerState;\n\n\tconst slots = {\n\t\troot: ['root', hasIcon && 'hasIcon'],\n\t\tactions: ['actions'],\n\t\tcontrols: ['controls'],\n\t\ticon: ['icon'],\n\t\ttitle: ['title'],\n\t};\n\treturn composeClasses(slots, getDialogTitleUtilityClass, classes);\n};\n\nconst DialogTitleRoot = styled(MuiDialogTitle, {\n\tname: DIALOG_TITLE_CLASS_NAME,\n\tslot: 'Root',\n})(({theme}) => ({\n\tdisplay: 'flex',\n\talignItems: 'center',\n\toverflow: 'hidden',\n\t[`&.${dialogTitleClasses.hasIcon}`]: {\n\t\tpaddingLeft: theme.spacing(2),\n\t},\n}));\n\nconst DialogTitleText = styled(Title, {\n\tname: DIALOG_TITLE_CLASS_NAME,\n\tslot: 'Title',\n})(({theme}) => ({\n\tflex: '1 1 auto',\n\toverflow: 'hidden',\n}));\n\nconst DialogTitleActions = styled('div', {\n\tname: DIALOG_TITLE_CLASS_NAME,\n\tslot: 'Title',\n})(({theme}) => ({\n\tflex: '0 0 auto',\n\tmarginLeft: theme.spacing(1),\n}));\n\nconst DialogTitleControls = styled('div', {\n\tname: DIALOG_TITLE_CLASS_NAME,\n\tslot: 'Controls',\n})(({theme}) => ({}));\n\nexport type DialogTitleProp =\n\t| string\n\t| {\n\t\t\tprimary: string;\n\t\t\tsecondary?: string;\n\t };\n\nexport interface DialogTitleProps\n\textends Omit<\n\t\t\tWithMuiPropOverrides,\n\t\t\t'classes' | 'variant'\n\t\t>,\n\t\tOmit,\n\t\tWithClasses<\n\t\t\tany,\n\t\t\t{\n\t\t\t\ticon?: FontAwesomeIconProps['icon'];\n\t\t\t\tonClose?: () => void;\n\t\t\t\tcontrols?: React.ReactNode;\n\t\t\t}\n\t\t> {}\n\nconst DialogTitleInner = ({\n\tclasses: _classes,\n\tclassName,\n\tcontrols,\n\ticon,\n\tloading,\n\tprimary,\n\tsecondary,\n\tonClose,\n\tPrimaryTitleProps,\n\tSecondaryTitleProps,\n\t...props\n}: DialogTitleProps) => {\n\tconst ownerState: DialogTitleOwnerProps = {\n\t\tclasses: _classes,\n\t\tclassName,\n\t\thasIcon: icon != null,\n\t};\n\n\tconst classes = useUtilityClasses(ownerState);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t{controls ? (\n\t\t\t\t\n\t\t\t\t\t{controls}\n\t\t\t\t\n\t\t\t) : null}\n\t\t\t{onClose ? (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t) : null}\n\t\t\n\t);\n};\n\nexport const DialogTitlePrimitive = DialogTitleInner;\n\nexport const DialogTitle = DialogTitlePrimitive;\n\nexport default DialogTitle;\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport const TOGGLE_BUTTON_CLASS_NAME = 'ToggleButton';\nexport const TOGGLE_BUTTON_CLASS_SLOTS = ['root', 'background'] as const;\n\nexport type ToggleButtonClassSlot = typeof TOGGLE_BUTTON_CLASS_SLOTS[number];\n\nexport interface ToggleButtonClasses {\n\troot: string;\n\tbackground: string;\n\tactive: string;\n\tfill: string;\n}\n\nexport type ToggleButtonClassKey = keyof ToggleButtonClasses;\n\nexport const getToggleButtonUtilityClass = (slot: ToggleButtonClassSlot) =>\n\tgenerateUtilityClass(TOGGLE_BUTTON_CLASS_NAME, slot);\n\nexport const toggleButtonClasses: ToggleButtonClasses = generateUtilityClasses(\n\tTOGGLE_BUTTON_CLASS_NAME,\n\t['root', 'active', 'background', 'fill'],\n);\n\nexport default toggleButtonClasses;\n","import React, {useCallback, useEffect, useState} from 'react';\nimport clsx from 'clsx';\n\nimport {darken, lighten} from '@mui/system';\nimport {composeClasses, styled, WithClasses} from '@netx/core-components/Theme';\nimport {useConfirmation} from '../Confirmation/ConfirmationService';\nimport IconButton, {IconButtonProps} from '../IconButton';\nimport {\n\ttoggleButtonClasses,\n\tgetToggleButtonUtilityClass,\n\tToggleButtonClasses,\n\tTOGGLE_BUTTON_CLASS_NAME,\n} from './toggleButtonClasses';\n\ntype IconButtonMethods = Required>;\n\ntype ToggleButtonUtiltiyClassProps = WithClasses<\n\tToggleButtonClasses,\n\t{\n\t\tactive?: boolean;\n\t\tcolor: Required['color'];\n\t\tfill?: boolean;\n\t}\n>;\n\nconst useUtilityClasses = (ownerState: ToggleButtonUtiltiyClassProps) => {\n\tconst {classes, active, fill} = ownerState;\n\tconst slots = {\n\t\troot: ['root', active && 'active', fill && 'fill'],\n\t\tbackground: ['background'],\n\t};\n\treturn composeClasses(slots, getToggleButtonUtilityClass, classes);\n};\n\nconst ToggleButtonRoot = styled(IconButton, {\n\tname: TOGGLE_BUTTON_CLASS_NAME,\n\tslot: 'Root',\n})(({theme, ...props}) => {\n\tconst light = theme.palette.mode === 'light';\n\tconst getBackgroundColor = light ? darken : lighten;\n\tconst ownerState = props.ownerState as ToggleButtonUtiltiyClassProps;\n\treturn {\n\t\t[`&.${toggleButtonClasses.active}`]: {\n\t\t\tcolor:\n\t\t\t\ttheme.palette[ownerState.color]?.contrastText ||\n\t\t\t\ttheme.palette.primary.contrastText,\n\t\t\t[`& .${toggleButtonClasses.background}`]: {\n\t\t\t\ttransform: 'scale(1)',\n\t\t\t},\n\t\t},\n\t\t[`& .${toggleButtonClasses.background}`]: {\n\t\t\tbackgroundColor:\n\t\t\t\townerState.color === 'inherit'\n\t\t\t\t\t? 'inherit'\n\t\t\t\t\t: getBackgroundColor(\n\t\t\t\t\t\t\ttheme.palette[ownerState.color]?.main ||\n\t\t\t\t\t\t\t\ttheme.palette.primary.main,\n\t\t\t\t\t\t\t0.05,\n\t\t\t\t\t ),\n\t\t\t...(ownerState.fill\n\t\t\t\t? {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tright: 0,\n\t\t\t\t\t\tbottom: 0,\n\t\t\t\t\t\tleft: 0,\n\t\t\t\t }\n\t\t\t\t: {\n\t\t\t\t\t\ttop: 4,\n\t\t\t\t\t\tright: 4,\n\t\t\t\t\t\tbottom: 4,\n\t\t\t\t\t\tleft: 4,\n\t\t\t\t }),\n\t\t},\n\t};\n});\n\nconst ToggleButtonBackground = styled('div', {\n\tname: TOGGLE_BUTTON_CLASS_NAME,\n\tslot: 'Background',\n})(({theme}) => ({\n\tdisplay: 'block',\n\tpointerEvents: 'none',\n\tborderRadius: '50%',\n\ttransformOrigin: 'center',\n\ttransform: 'scale(0)',\n\ttransition: 'transform .15s ease-in-out',\n\tposition: 'absolute',\n}));\n\ninterface ConfirmProps {\n\tmessage: string;\n\ttitle: string;\n}\n\nexport interface ToggleButtonProps\n\textends Omit,\n\t\tWithClasses<\n\t\t\tToggleButtonClasses,\n\t\t\t{\n\t\t\t\tconfirm?: ConfirmProps;\n\t\t\t\tfill?: boolean;\n\t\t\t\ton?: boolean;\n\t\t\t\tonToggle?: (\n\t\t\t\t\tevent: React.MouseEvent,\n\t\t\t\t\ton: boolean,\n\t\t\t\t) => void;\n\t\t\t}\n\t\t> {}\n\nexport const ToggleButtonPrimitive = ({\n\tclasses: _classes,\n\tclassName,\n\tcolor = 'default',\n\tconfirm,\n\tfill,\n\ton = false,\n\tonClick,\n\tonToggle,\n\t...props\n}: ToggleButtonProps) => {\n\tconst confirmation = useConfirmation();\n\n\t// TODO: fix this, on state should be solely controlled from the outside\n\tconst [isOn, setIsOn] = useState(on);\n\tuseEffect(() => {\n\t\tsetIsOn(on);\n\t}, [on]);\n\n\tconst ownerState = {\n\t\tclasses: _classes,\n\t\tactive: isOn,\n\t\tcolor,\n\t\tfill,\n\t};\n\n\tconst classes = useUtilityClasses(ownerState);\n\n\tconst toggle = useCallback(\n\t\t(event: React.MouseEvent) => {\n\t\t\tsetIsOn((isOn) => {\n\t\t\t\t// Gives the UI time to animate without choking on\n\t\t\t\t// what the toggle does\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tonToggle?.(event, !isOn);\n\t\t\t\t}, 1);\n\t\t\t\treturn !isOn;\n\t\t\t});\n\t\t},\n\t\t[onToggle],\n\t);\n\n\tconst handleClick = useCallback(\n\t\t(event: React.MouseEvent) => {\n\t\t\tevent.persist();\n\t\t\tonClick?.(event);\n\t\t\t// if (event.defaultPrevented) return;\n\n\t\t\tevent.stopPropagation();\n\t\t\tif (!confirm) return toggle(event);\n\t\t\tconfirmation({\n\t\t\t\tdescription: confirm.message,\n\t\t\t\ttitle: confirm.title,\n\t\t\t}).then(() => toggle(event));\n\t\t},\n\t\t[confirm, onClick, toggle],\n\t);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nexport const ToggleButton = ToggleButtonPrimitive;\n\nexport default ToggleButton;\n","import React from 'react';\n\nimport {WithMuiPropOverrides} from '@netx/core-components/Theme';\n\nimport MuiMenuList, {\n\tMenuListProps as MuiMenuListProps,\n} from '@mui/material/MenuList';\n\nexport interface MenuListProps\n\textends Partial> {}\n\nconst MenuList = React.forwardRef(\n\t(props, ref) => ,\n);\n\nexport default MenuList;\n","import {generateUtilityClass, generateUtilityClasses} from '@mui/base';\n\nexport interface SelectFieldClasses {\n\t/** Styles applied to the root element. */\n\troot: string;\n\tmultiple: string;\n\tautocomplete: string;\n\tselectedIcon: string;\n}\n\nexport const getSelectFieldUtilityClass = (slot: string) =>\n\tgenerateUtilityClass('SelectField', slot);\n\nexport const selectFieldClasses = generateUtilityClasses('SelectField', [\n\t'root',\n\t'autocomplete',\n\t'multiple',\n\t'selectedIcon',\n]);\nexport default selectFieldClasses;\n","// import {csvToArray} from '@netx/core/utils';\n\nexport const base = (value: any) => {\n\t// // Some things still use csv (gross)\n\t// if (value != null && !Array.isArray(value) && value.toString().includes('\"'))\n\t// \treturn csvToArray(value);\n\n\treturn value;\n};\n\nexport default base;\n","import React, {useMemo} from 'react';\n\nimport {Divider} from '@mui/material';\nimport MenuList, {MenuListProps} from '../MenuList';\nimport MenuItem from '../MenuItem';\n\nimport {ReactAction as Action} from '@netx/core/bootstrap';\n\nexport interface ActionMenuList {\n\tactions: Array;\n\tonAction: (action: Action) => void;\n}\n\nconst ActionMenuList: React.FunctionComponent<\n\tActionMenuList & MenuListProps\n> = React.forwardRef(\n\t({actions, onAction, ...props}, ref: React.RefObject) => {\n\t\treturn (\n\t\t\t\n\t\t\t\t{actions.map((action, index) => {\n\t\t\t\t\tif (Array.isArray(action)) {\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\tindex > 0 ? : null,\n\t\t\t\t\t\t\t...action.map((action) => (\n\t\t\t\t\t\t\t\t\n\t\t);\n\t},\n);\n\nexport default ActionMenuList;\n","import React from 'react';\n\nimport {compareProps} from '@netx/core-components/util';\nimport {FormType, FormValues} from './';\n\ntype Ref = React.ForwardedRef;\n\nexport interface FormProps\n\textends Omit<\n\t\tReact.DetailedHTMLProps<\n\t\t\tReact.HTMLAttributes,\n\t\t\tHTMLFormElement\n\t\t>,\n\t\t'noValidate' | 'onSubmit'\n\t> {\n\tform?: FormType;\n\tonSubmit?: (\n\t\tvalues: FormType['values'],\n\t\tchanges?: FormType['changes'],\n\t\tactions?: FormType['actions'],\n\t) => Promise;\n}\n\n/**\n * A helpful wrapper \n\t);\n};\n\nexport const FormPrimitive = React.forwardRef(FormInner) as (\n\tprops: FormProps,\n\tref?: Ref,\n) => JSX.Element;\n\nexport const Form = React.memo(FormPrimitive, compareProps([]));\n\nexport default Form;\n","import AttributesSetsCollection from '../assetAttributeSets';\nimport {assetAttributes as assetAttributesSingleton} from './attributes';\n\nexport const attributeSets = new AttributesSetsCollection([], {\n\tassetAttributes: assetAttributesSingleton,\n});\n\nexport default attributeSets;\n","import type Collection from '@netx/core/lib/netx-collection';\nimport _ from 'underscore';\n\nimport {useEffect, useState} from 'react';\nimport useComponentIsMounted from './useComponentIsMounted';\n\nexport default function useBackboneCollection<\n\tTCollection extends Collection = Collection\n>(collection: TCollection, fetchOnMount = true) {\n\tconst {act} = useComponentIsMounted();\n\n\tconst [attributes, setAttributes] = useState<\n\t\tTCollection['models'][number]['attributes'][]\n\t>([...collection.models.map((model) => ({...model.attributes}))]);\n\n\t// Subscribe to the model or collection on first render only\n\tuseEffect(() => {\n\t\t// Pull the attributes or array of attributes from model or collection\n\t\t// Set them on state\n\t\tconst pullAndSetData = () =>\n\t\t\tact(() =>\n\t\t\t\tsetAttributes([\n\t\t\t\t\t...collection.models.map((model) => ({...model.attributes})),\n\t\t\t\t]),\n\t\t\t);\n\n\t\tpullAndSetData();\n\n\t\tconst debouncedPullAndSetData = _.debounce(pullAndSetData, 20);\n\t\tcollection.on('add change remove reset sort sync', debouncedPullAndSetData);\n\n\t\tconst preferredFetchMethod = collection.preferredFetchMethod || 'fetch';\n\t\tfetchOnMount !== false && collection[preferredFetchMethod]();\n\n\t\t// Unsubscribe when component unmounted\n\t\treturn () => {\n\t\t\tcollection.off(undefined, debouncedPullAndSetData);\n\t\t};\n\t}, []);\n\n\treturn attributes;\n}\n","export enum DragResizeDirection {\n\tBOTTOM = 'bottom',\n\tLEFT = 'left',\n\tRIGHT = 'right',\n\tTOP = 'top',\n}\n\nexport enum Axis {\n\tX = 'X',\n\tY = 'Y',\n}\n\nexport enum ClientPosition {\n\tX = 'clientX',\n\tY = 'clientY',\n}\n\nexport enum ClientDimension {\n\tX = 'clientWidth',\n\tY = 'clientHeight',\n}\n\nexport enum ScrollDimension {\n\tX = 'scrollWidth',\n\tY = 'scrollHeight',\n}\n\nexport enum OffsetDimension {\n\tX = 'offsetWidth',\n\tY = 'offsetHeight',\n}\n\nexport const DRAG_RESIZE_DEFAULT_DIRECTION = DragResizeDirection.LEFT;\n","import React, {useEffect, useState} from 'react';\n\nimport {i18n} from '@netx/core/i18n';\n\nimport {\n\tButton,\n\tDialogContent,\n\tDialogActions,\n\tLinearProgress,\n\tTypography,\n} from '@mui/material';\n\nimport Dialog from '@netx/core-components/Dialog';\n\nexport interface DownloadOptions {\n\tdescription?: string;\n\ttitle?: string;\n\tonEmailWhenDone?: () => void;\n\tgetUUID(): Promise;\n}\n\nexport interface DownloadDialogProps extends DownloadOptions {\n\tcompleteUrl?: string;\n\tdisableEmailWhenDone?: boolean;\n\terror?: string;\n\temailWhenDoneLabel?: string;\n\topen: boolean;\n\tonClose?: () => void;\n\tprogress?: number;\n\tuuid?: string;\n}\n\nconst DownloadDialog: React.FunctionComponent<\n\tReact.PropsWithChildren\n> = ({\n\tcompleteUrl,\n\tdescription,\n\tdisableEmailWhenDone,\n\terror,\n\temailWhenDoneLabel,\n\topen,\n\tprogress,\n\ttitle,\n\tonClose,\n\tonEmailWhenDone,\n\tuuid,\n}) => {\n\treturn (\n\t\t\n\t);\n};\n\nexport default DownloadDialog;\n","export const ACTIONS = {\n\tSET_ERROR: 'SET_ERROR',\n\tSET_PROGRESS: 'SET_PROGRESS',\n\tSET_SUCCESS: 'SET_SUCCESS',\n\tSET_UUID: 'SET_UUID',\n};\n","import {ACTIONS} from './constants';\nimport type {Action} from './actions';\n\nexport type State = {\n\tcompleteUrl?: string;\n\terror?: string;\n\tprogress?: number;\n\tsuccess: boolean;\n\tuuid?: string;\n};\n\nexport const initialState: State = {\n\tsuccess: false,\n};\n\nconst reducer = (state: State, action: Action): State => {\n\tswitch (action.type) {\n\t\tcase ACTIONS.SET_ERROR:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\terror: action.error,\n\t\t\t\tsuccess: false,\n\t\t\t\tuuid: undefined,\n\t\t\t};\n\t\tcase ACTIONS.SET_PROGRESS:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tprogress: action.progress,\n\t\t\t};\n\t\tcase ACTIONS.SET_SUCCESS:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tcompleteUrl: action.completeUrl,\n\t\t\t\tsuccess: action.success,\n\t\t\t\tuuid: undefined,\n\t\t\t};\n\t\tcase ACTIONS.SET_UUID:\n\t\t\treturn action.uuid != null\n\t\t\t\t? {\n\t\t\t\t\t\t...state,\n\t\t\t\t\t\tcompleteUrl: undefined,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t\tuuid: action.uuid,\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tprogress: 0,\n\t\t\t\t }\n\t\t\t\t: {\n\t\t\t\t\t\t...state,\n\t\t\t\t\t\tcompleteUrl: undefined,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tprogress: undefined,\n\t\t\t\t\t\tuuid: undefined,\n\t\t\t\t };\n\t}\n};\n\nexport default reducer;\n","import React, {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseReducer,\n\tuseState,\n} from 'react';\n\nimport {openDownloadLink} from '@netx/core/utils';\nimport DownloadDialog, {DownloadOptions} from '../components/Dialog';\n\nimport {\n\tuseQuery,\n\tQueryClient,\n\tQueryClientProvider,\n\tQueryFunctionContext,\n} from '@tanstack/react-query';\n\nimport getProgressReport, {\n\tGetProgressReportResult,\n\tGetProgressReportRequestOptions,\n\tQueryError,\n} from './api/getProgressReport';\n\nimport setProgressReportNotify from './api/setProgressReportNotify';\n\nimport reducer, {initialState} from './reducer';\nimport {ACTIONS} from './constants';\n\nconst queryClient = new QueryClient();\n\nconst DownloadServiceContext = createContext<\n\t(options: DownloadOptions) => void\n>(() => {});\n\nexport const useDownload = () => useContext(DownloadServiceContext);\n\nexport type DownloadServiceProviderProps = React.PropsWithChildren<{\n\tdisableEmailWhenDone?: boolean;\n}>;\n\nexport const DownloadServiceProviderPrimitive = ({\n\tchildren,\n\tdisableEmailWhenDone,\n}: DownloadServiceProviderProps) => {\n\tconst [state, dispatch] = useReducer(reducer, initialState);\n\n\tconst [downloadState, setDownloadState] = useState();\n\n\tconst close = useCallback(() => setDownloadState(undefined), []);\n\n\tuseQuery({\n\t\tqueryKey: [\n\t\t\t'getProgressReport',\n\t\t\t{\n\t\t\t\tuuid: state.uuid,\n\t\t\t},\n\t\t],\n\t\tqueryFn: ({\n\t\t\tqueryKey,\n\t\t}: QueryFunctionContext<[string, GetProgressReportRequestOptions]>) =>\n\t\t\tgetProgressReport({...queryKey[1]}),\n\t\tenabled: !!state.uuid,\n\t\trefetchInterval: 500,\n\t\tonError: (error) => {\n\t\t\tdispatch({type: ACTIONS.SET_ERROR, error: error.message});\n\t\t},\n\t\t// Process data on success\n\t\tonSuccess: (data) => {\n\t\t\tdispatch({type: ACTIONS.SET_PROGRESS, progress: data.percentComplete});\n\t\t\tif (data.percentComplete >= 100 && data.completeUrl != null) {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: ACTIONS.SET_SUCCESS,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tcompleteUrl: data.completeUrl,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t});\n\n\tuseEffect(() => {\n\t\tif (!state.completeUrl) return;\n\n\t\topenDownloadLink(state.completeUrl);\n\t\tclose();\n\t}, [state.completeUrl]);\n\n\tconst openDownload = useCallback((options: DownloadOptions) => {\n\t\tsetDownloadState(options);\n\t\toptions\n\t\t\t.getUUID()\n\t\t\t.then((uuid) => dispatch({type: ACTIONS.SET_UUID, uuid}))\n\t\t\t.catch((error) =>\n\t\t\t\tdispatch({type: ACTIONS.SET_ERROR, error: error.message}),\n\t\t\t);\n\t}, []);\n\n\tconst handleEmailWhenDone = useCallback(() => {\n\t\tstate.uuid && setProgressReportNotify({uuid: state.uuid, notify: true});\n\t\tclose();\n\t\tdispatch({type: ACTIONS.SET_UUID});\n\t}, [state.uuid]);\n\n\tconst handleClose = useCallback(() => {\n\t\tclose();\n\t\tdispatch({type: ACTIONS.SET_UUID});\n\t}, [downloadState]);\n\n\treturn (\n\t\t<>\n\t\t\t\n\n\t\t\t\n\t\t>\n\t);\n};\n\nexport const DownloadServiceProvider = (\n\tprops: DownloadServiceProviderProps,\n) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nexport default DownloadServiceProvider;\n","import NetxQueryDam from '@netx/core/lib/netx-query-dam';\nexport {QueryError} from '@netx/core/lib/netx-query-dam';\n\nimport {BatchJobId as UUID} from '@netx/core-app/models/batchJob';\n\n/**\n * `getProgressReport` request params\n * (what is used to send to server)\n */\nexport interface GetProgressReportRequestOptions {\n\tuuid: UUID;\n}\n\n/**\n * `getProgressReport` request\n * (what gets sent to the server)\n */\nexport type GetProgressReportRequest = [\n\tGetProgressReportRequestOptions['uuid'],\n];\n\n/**\n * `getProgressReport` response\n * (what comes back from the server)\n */\nexport interface GetProgressReportResponse {\n\tresult: GetProgressReportResult;\n}\n\n/**\n * `getProgressReport` result\n * (what is utilized from the server response)\n */\nexport type GetProgressReportResult = {\n\tpercentComplete: number;\n\tjobTitle: string;\n\tsecondsToReload: number;\n\tcompleteUrl: null | string;\n\tdetails: string;\n\tincrement: number;\n\tstartTime: number;\n\trunningTime: number;\n\trunningTimeLabel: null | string;\n\testimatedTime: null | number;\n\tuserId: number;\n\tnotifyOnComplete: boolean;\n\tsize: number;\n\tprogressMessages: null | any; // TODO\n\tprogressMessageCount: number;\n\twarningObject: null | any; // TODO generic\n};\n\nexport const getProgressReportEndpoint = 'getProgressReport';\n\n/**\n * Get Progress\n * @param fetchParams Fetch params\n */\nexport default async function isTokenValid({\n\tuuid,\n}: GetProgressReportRequestOptions) {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: GetProgressReportRequest = [uuid];\n\n\treturn client\n\t\t.post(getProgressReportEndpoint, requestParams)\n\t\t.then((response) => response.data.result);\n}\n","import NetxQueryDam from '@netx/core/lib/netx-query-dam';\n\nimport {BatchJobId as UUID} from '@netx/core-app/models/batchJob';\n\n/**\n * `setProgressReportNotify` request params\n * (what is used to send to server)\n */\nexport interface SetProgressReportNotifyRequestOptions {\n\tuuid: UUID;\n\tnotify: boolean;\n}\n\n/**\n * `setProgressReportNotify` request\n * (what gets sent to the server)\n */\nexport type SetProgressReportNotifyRequest = [\n\tSetProgressReportNotifyRequestOptions['uuid'],\n\tSetProgressReportNotifyRequestOptions['notify'],\n];\n\n/**\n * `setProgressReportNotify` response\n * (what comes back from the server)\n */\nexport interface SetProgressReportNotifyResponse {\n\tresult: SetProgressReportNotifyResult;\n}\n\n/**\n * `setProgressReportNotify` result\n * (what is utilized from the server response)\n */\nexport type SetProgressReportNotifyResult = boolean;\n\nexport const setProgressReportNotifyEndpoint = 'setProgressReportNotify';\n\n/**\n * Notify when done\n * @param fetchParams Fetch params\n */\nexport default async function isTokenValid({\n\tuuid,\n\tnotify,\n}: SetProgressReportNotifyRequestOptions) {\n\tconst client = NetxQueryDam();\n\n\tconst requestParams: SetProgressReportNotifyRequest = [uuid, notify];\n\n\treturn client\n\t\t.post(\n\t\t\tsetProgressReportNotifyEndpoint,\n\t\t\trequestParams,\n\t\t)\n\t\t.then((response) => response.data.result);\n}\n","import React from 'react';\n\nimport {DownloadServiceProvider, DownloadServiceProviderProps} from './store';\n\n/**\n * wrap component in download dialog provider\n * @example\n\tconst WrappedComponenet = withDownloadDialog(Componenet, {...});\n */\nexport const withDownloadDialog = function (\n\tComponent: C,\n\tdefaults?: Partial,\n) {\n\treturn ({\n\t\tDownloadServiceProviderProps,\n\t\t...props\n\t}: JSX.IntrinsicAttributes &\n\t\tJSX.LibraryManagedAttributes> & {\n\t\t\tDownloadServiceProviderProps?: Partial;\n\t\t}) => {\n\t\treturn (\n\t\t\t\n\t\t\t\t>)}\n\t\t\t\t/>\n\t\t\t\n\t\t);\n\t};\n};\n\nexport default withDownloadDialog;\n","import React from 'react';\nimport {useCallback, useEffect} from 'react';\n\nimport scrollIntoView from 'scroll-into-view-if-needed';\n\nconst config = {childList: true};\n\ntype UseScrollAddedNodesIntoView = {\n\tenabled?: boolean;\n\tref: React.RefObject;\n};\n\nexport default function useScrollAddedNodesIntoView({\n\tenabled = true,\n\tref,\n}: UseScrollAddedNodesIntoView) {\n\tconst callback = useCallback((mutationsList) => {\n\t\tlet removed: Node[] = [];\n\t\tlet added: Node[] = [];\n\t\tfor (const {addedNodes, removedNodes, type} of mutationsList) {\n\t\t\tif (type !== 'childList') continue;\n\n\t\t\tremoved = removed.concat(Array.from(removedNodes));\n\n\t\t\tif (!addedNodes.length) continue;\n\n\t\t\tconst el = addedNodes[0] as HTMLElement;\n\t\t\t// If it was removed in this mutation as well, it was just a reorder\n\t\t\t// we only want to scroll into view new items in the container\n\t\t\tif (!removed.includes(el)) {\n\t\t\t\tadded = added.concat(Array.from(addedNodes));\n\t\t\t}\n\t\t}\n\n\t\t// If we added multiples lets just ignore\n\t\tif (added.length > 1 || added.length === 0) return;\n\n\t\t// TODO: scroll into view if it is not visible somehow?\n\t\t// If we want to do that we can use the browser version\n\t\t// which will scroll all parent elements\n\t\tscrollIntoView(added[0] as HTMLElement, {\n\t\t\tbehavior: 'smooth',\n\t\t\tblock: 'end',\n\t\t\tscrollMode: 'if-needed',\n\t\t\tskipOverflowHiddenElements: true,\n\t\t});\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!ref.current || !enabled) return;\n\n\t\tconst observer = new MutationObserver(callback);\n\t\tobserver.observe(ref.current, config);\n\t\treturn () => observer.disconnect();\n\t}, [callback, ref, enabled]);\n}\n","// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n// DEPRECATED: please see ScrollBorder\n// We can add support for shadow over border there - but it does not use scroll events\n// and i do not have the time atm to track down the few components that may be using this\n\n// (ORIGINAL) TODO: This is not the best - it tries to do too much\n// the scroll added nodes into view should be handled elsewhere\n// I wrote this before I fully understood how to combine refs\n\nimport React, {useCallback, useReducer, useRef} from 'react';\nimport clsx from 'clsx';\nimport _ from 'underscore';\n\nimport ReactResizeDetector from 'react-resize-detector';\n\nimport {createStyles, withStyles, WithStyles} from '@mui/styles';\nimport type {Theme} from '@netx/core-components/Theme';\n\nimport useScrollAddedNodesIntoView from './useScrollAddedNodesIntoView';\nimport useScrollListener from './useScrollListener';\n\nconst shadow = [\n\t'radial-gradient(farthest-side at 50% 0px, rgba(0,0,0,.2), rgba(0,0,0,0))', // Top\n\t'radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.2), rgba(0,0,0,0)) 0 100%', // Bottom\n];\nconst shadowSize = ['100% 6px', '100% 14px'];\nconst createShadow = (side: 'top' | 'bottom' | 'all') => {\n\tconst styles = {\n\t\tbackgroundRepeat: 'no-repeat',\n\t};\n\tswitch (side) {\n\t\tcase 'top':\n\t\t\treturn {\n\t\t\t\t...styles,\n\t\t\t\tbackground: shadow[0],\n\t\t\t\tbackgroundSize: shadowSize.join(),\n\t\t\t};\n\t\tcase 'bottom':\n\t\t\treturn {\n\t\t\t\t...styles,\n\t\t\t\tbackground: shadow[1],\n\t\t\t\tbackgroundSize: shadowSize.join(),\n\t\t\t};\n\t\tcase 'all':\n\t\t\treturn {\n\t\t\t\t...styles,\n\t\t\t\tbackground: shadow.join(),\n\t\t\t\tbackgroundSize: `${shadowSize[0]}, ${shadowSize[0]}, ${shadowSize[1]}, ${shadowSize[1]}`,\n\t\t\t};\n\t}\n};\n\nconst styles = (theme: Theme) =>\n\tcreateStyles({\n\t\toverflown: {\n\t\t\t'&:not($scrolled)': createShadow('bottom'),\n\t\t\t'&$scrollEnd': createShadow('top'),\n\t\t\t'&$scrolled:not($scrollEnd)': createShadow('all'),\n\t\t},\n\t\tscrolled: {},\n\t\tscrollEnd: {},\n\t});\n\nexport interface ScrollShadowWrapperProps {\n\tclassName?: string;\n\tscrollNewItemsIntoView?: boolean;\n}\n\nexport interface ScrollShadowWrapperChildProps {\n\tclassName: string;\n\tref:\n\t\t| ((instance: HTMLDivElement | null) => void)\n\t\t| React.RefObject\n\t\t| null;\n}\n\nconst initialState = {\n\tclientHeight: 0,\n\tisOverflown: false,\n\tisScrolled: false,\n\treachedScrollEnd: false,\n};\n\nconst reducer = (state = initialState, action): typeof initialState => {\n\tswitch (action.type) {\n\t\tcase 'RESIZE': {\n\t\t\tconst {clientHeight, scrollHeight, scrollTop} = action.data;\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tclientHeight,\n\t\t\t\tisOverflown: clientHeight < scrollHeight,\n\t\t\t\tisScrolled: scrollTop > 0,\n\t\t\t\treachedScrollEnd: scrollTop === scrollHeight - clientHeight,\n\t\t\t};\n\t\t}\n\t\tcase 'SCROLL': {\n\t\t\tconst {scrollHeight, scrollTop} = action.data;\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tisScrolled: scrollTop > 0,\n\t\t\t\treachedScrollEnd: scrollTop === scrollHeight - state.clientHeight,\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn state;\n\t}\n};\n\n// TODO: this only works for vertical scrolling ATM\n/**\n * Provide some auto-scroll/shadow functionality to your list components\n *\n * This will only look for nodes added as direct descendants so be sure\n * to apply this to the last level of your list\n *\n * The component being wrapped must utilize `React.forwardRef`\n * @deprecated\n * @example\n * const ListWrapper = ScrollShadowWrapper(\n * React.forwardRef((props, ref) => {\n * return ;\n * })\n * );\n * ...list items\n */\nconst ScrollShadowWrapper = (\n\tComponent: React.ForwardRefExoticComponent,\n) => {\n\treturn withStyles(styles)(\n\t\tReact.memo(\n\t\t\t({\n\t\t\t\tclasses,\n\t\t\t\tclassName,\n\t\t\t\tscrollNewItemsIntoView = false,\n\t\t\t\t...props\n\t\t\t}: WithStyles & ScrollShadowWrapperProps) => {\n\t\t\t\tconst [state, dispatch] = useReducer(reducer, initialState);\n\n\t\t\t\tconst ref = useRef(null);\n\n\t\t\t\tuseScrollAddedNodesIntoView({\n\t\t\t\t\tenabled: scrollNewItemsIntoView,\n\t\t\t\t\tref,\n\t\t\t\t});\n\n\t\t\t\tuseScrollListener({\n\t\t\t\t\tref,\n\t\t\t\t\tonScroll: useCallback(\n\t\t\t\t\t\t(container) => {\n\t\t\t\t\t\t\tdispatch({\n\t\t\t\t\t\t\t\ttype: 'SCROLL',\n\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\tscrollHeight: container.scrollHeight,\n\t\t\t\t\t\t\t\t\tscrollTop: container.scrollTop,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t\t[dispatch],\n\t\t\t\t\t),\n\t\t\t\t});\n\n\t\t\t\tconst handleResize = useCallback(() => {\n\t\t\t\t\tif (!ref.current) return;\n\t\t\t\t\tconst {scrollTop, scrollHeight, clientHeight} = ref.current;\n\t\t\t\t\tdispatch({\n\t\t\t\t\t\ttype: 'RESIZE',\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tclientHeight,\n\t\t\t\t\t\t\tscrollHeight,\n\t\t\t\t\t\t\tscrollTop,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}, []);\n\n\t\t\t\treturn (\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t);\n\t\t\t},\n\t\t),\n\t);\n};\n\nexport default ScrollShadowWrapper;\n","import React from 'react';\nimport _ from 'underscore';\n\ntype UseScrollListener = {\n\tref: React.RefObject;\n\tonScroll(el: HTMLElement): void;\n};\n\nexport default function useScrollListener({ref, onScroll}: UseScrollListener) {\n\tReact.useEffect(() => {\n\t\tif (!ref.current) return;\n\t\tconst scrollListener = _.throttle(\n\t\t\t() => {\n\t\t\t\tif (!ref.current) return;\n\t\t\t\tonScroll(ref.current);\n\t\t\t},\n\t\t\t16,\n\t\t\t{trailing: true},\n\t\t);\n\n\t\tref.current.addEventListener('scroll', scrollListener, true);\n\t\treturn () => {\n\t\t\tref.current?.removeEventListener('scroll', scrollListener, true);\n\t\t};\n\t}, [ref, onScroll]);\n}\n","import {i18n} from '@netx/core/i18n';\n\nimport {\n\tATTRIBUTE_TYPE,\n\tATTRIBUTE_SYSTEM,\n\tATTRIBUTE_SYSTEM_ID,\n} from './constants';\nimport {AttributeType, AttributeSystemType} from './types';\n\nexport const TYPE_LABELS: Record = {\n\t[ATTRIBUTE_TYPE.DATE]: i18n.t('i18n.date'),\n\t[ATTRIBUTE_TYPE.HIERARCHICAL]: i18n.t('i18n.hierarchical'),\n\t[ATTRIBUTE_TYPE.MULTISELECT]: i18n.t('i18n.multiSelectBox'),\n\t[ATTRIBUTE_TYPE.NUMBER]: i18n.t('i18n.number'),\n\t[ATTRIBUTE_TYPE.SELECT]: i18n.t('i18n.pulldown'),\n\t[ATTRIBUTE_TYPE.SEMANTIC]: i18n.t('i18n.semantic'),\n\t[ATTRIBUTE_TYPE.TAG]: i18n.t('i18n.tag'),\n\t[ATTRIBUTE_TYPE.TAG_VOCAB]: i18n.t('i18n.tagVocab'),\n\t[ATTRIBUTE_TYPE.TEXT]: i18n.t('i18n.text'),\n\t[ATTRIBUTE_TYPE.TEXTAREA]: i18n.t('i18n.textarea'),\n};\n\nexport const SYSTEM_ATTRIBUTE_LABELS: Record = <\n\tconst\n>{\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.ASSET_ID]]: i18n.t('i18n.assetId'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.CATEGORY_PATHS]]: i18n.t(\n\t\t'i18n.folderPath',\n\t),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.CHECKSUM]]: i18n.t('i18n.checksum'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.CREATION_DATE]]: i18n.t(\n\t\t'i18n.creationDate',\n\t),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.DIMENSIONS]]: i18n.t('i18n.dimensions'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.EXPIRE_DATE]]: i18n.t('i18n.expires'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE]]: i18n.t('i18n.file'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE_FORMAT_FAMILY]]: i18n.t(\n\t\t'i18n.fileFormatFamily',\n\t),\n\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE_SIZE_2]]: i18n.t('i18n.fileSize'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.FILE_TYPE_LABEL]]: i18n.t(\n\t\t'i18n.fileType',\n\t),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.HEIGHT]]: i18n.t('i18n.height'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.IMPORT_DATE]]: i18n.t(\n\t\t'i18n.importDate',\n\t),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.MOD_DATE]]: i18n.t('i18n.modDate'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.MOD_USER]]: i18n.t('i18n.modUser'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.NAME]]: i18n.t('i18n.name'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.PATH]]: i18n.t('i18n.path'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.SMART_LABELS]]: i18n.t(\n\t\t'i18n.smartLabels',\n\t),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.THUMB_PATH]]: i18n.t('i18n.thumbPath'),\n\t[ATTRIBUTE_SYSTEM_ID[ATTRIBUTE_SYSTEM.WIDTH]]: i18n.t('i18n.width'),\n};\n","export { urlAlphabet } from './url-alphabet/index.js'\nexport let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))\nexport let customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1\n let step = -~((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let j = step\n while (j--) {\n id += alphabet[bytes[j] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nexport let customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nexport let nanoid = (size = 21) =>\n crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {\n byte &= 63\n if (byte < 36) {\n id += byte.toString(36)\n } else if (byte < 62) {\n id += (byte - 26).toString(36).toUpperCase()\n } else if (byte > 62) {\n id += '-'\n } else {\n id += '_'\n }\n return id\n }, '')\n","import { generateUtilityClass, generateUtilityClasses } from '@mui/base';\nexport function getTabUtilityClass(slot) {\n return generateUtilityClass('MuiTab', slot);\n}\nconst tabClasses = generateUtilityClasses('MuiTab', ['root', 'labelIcon', 'textColorInherit', 'textColorPrimary', 'textColorSecondary', 'selected', 'disabled', 'fullWidth', 'wrapped', 'iconWrapper']);\nexport default tabClasses;","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"className\", \"disabled\", \"disableFocusRipple\", \"fullWidth\", \"icon\", \"iconPosition\", \"indicator\", \"label\", \"onChange\", \"onClick\", \"onFocus\", \"selected\", \"selectionFollowsFocus\", \"textColor\", \"value\", \"wrapped\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport { unstable_composeClasses as composeClasses } from '@mui/base';\nimport ButtonBase from '../ButtonBase';\nimport capitalize from '../utils/capitalize';\nimport useThemeProps from '../styles/useThemeProps';\nimport styled from '../styles/styled';\nimport unsupportedProp from '../utils/unsupportedProp';\nimport tabClasses, { getTabUtilityClass } from './tabClasses';\nimport { jsxs as _jsxs } from \"react/jsx-runtime\";\n\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n textColor,\n fullWidth,\n wrapped,\n icon,\n label,\n selected,\n disabled\n } = ownerState;\n const slots = {\n root: ['root', icon && label && 'labelIcon', `textColor${capitalize(textColor)}`, fullWidth && 'fullWidth', wrapped && 'wrapped', selected && 'selected', disabled && 'disabled'],\n iconWrapper: ['iconWrapper']\n };\n return composeClasses(slots, getTabUtilityClass, classes);\n};\n\nconst TabRoot = styled(ButtonBase, {\n name: 'MuiTab',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.label && ownerState.icon && styles.labelIcon, styles[`textColor${capitalize(ownerState.textColor)}`], ownerState.fullWidth && styles.fullWidth, ownerState.wrapped && styles.wrapped];\n }\n})(({\n theme,\n ownerState\n}) => _extends({}, theme.typography.button, {\n maxWidth: 360,\n minWidth: 90,\n position: 'relative',\n minHeight: 48,\n flexShrink: 0,\n padding: '12px 16px',\n overflow: 'hidden',\n whiteSpace: 'normal',\n textAlign: 'center'\n}, ownerState.label && {\n flexDirection: ownerState.iconPosition === 'top' || ownerState.iconPosition === 'bottom' ? 'column' : 'row'\n}, {\n lineHeight: 1.25\n}, ownerState.icon && ownerState.label && {\n minHeight: 72,\n paddingTop: 9,\n paddingBottom: 9,\n [`& > .${tabClasses.iconWrapper}`]: _extends({}, ownerState.iconPosition === 'top' && {\n marginBottom: 6\n }, ownerState.iconPosition === 'bottom' && {\n marginTop: 6\n }, ownerState.iconPosition === 'start' && {\n marginRight: theme.spacing(1)\n }, ownerState.iconPosition === 'end' && {\n marginLeft: theme.spacing(1)\n })\n}, ownerState.textColor === 'inherit' && {\n color: 'inherit',\n opacity: 0.6,\n // same opacity as theme.palette.text.secondary\n [`&.${tabClasses.selected}`]: {\n opacity: 1\n },\n [`&.${tabClasses.disabled}`]: {\n opacity: (theme.vars || theme).palette.action.disabledOpacity\n }\n}, ownerState.textColor === 'primary' && {\n color: (theme.vars || theme).palette.text.secondary,\n [`&.${tabClasses.selected}`]: {\n color: (theme.vars || theme).palette.primary.main\n },\n [`&.${tabClasses.disabled}`]: {\n color: (theme.vars || theme).palette.text.disabled\n }\n}, ownerState.textColor === 'secondary' && {\n color: (theme.vars || theme).palette.text.secondary,\n [`&.${tabClasses.selected}`]: {\n color: (theme.vars || theme).palette.secondary.main\n },\n [`&.${tabClasses.disabled}`]: {\n color: (theme.vars || theme).palette.text.disabled\n }\n}, ownerState.fullWidth && {\n flexShrink: 1,\n flexGrow: 1,\n flexBasis: 0,\n maxWidth: 'none'\n}, ownerState.wrapped && {\n fontSize: theme.typography.pxToRem(12)\n}));\nconst Tab = /*#__PURE__*/React.forwardRef(function Tab(inProps, ref) {\n const props = useThemeProps({\n props: inProps,\n name: 'MuiTab'\n });\n\n const {\n className,\n disabled = false,\n disableFocusRipple = false,\n // eslint-disable-next-line react/prop-types\n fullWidth,\n icon: iconProp,\n iconPosition = 'top',\n // eslint-disable-next-line react/prop-types\n indicator,\n label,\n onChange,\n onClick,\n onFocus,\n // eslint-disable-next-line react/prop-types\n selected,\n // eslint-disable-next-line react/prop-types\n selectionFollowsFocus,\n // eslint-disable-next-line react/prop-types\n textColor = 'inherit',\n value,\n wrapped = false\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n\n const ownerState = _extends({}, props, {\n disabled,\n disableFocusRipple,\n selected,\n icon: !!iconProp,\n iconPosition,\n label: !!label,\n fullWidth,\n textColor,\n wrapped\n });\n\n const classes = useUtilityClasses(ownerState);\n const icon = iconProp && label && /*#__PURE__*/React.isValidElement(iconProp) ? /*#__PURE__*/React.cloneElement(iconProp, {\n className: clsx(classes.iconWrapper, iconProp.props.className)\n }) : iconProp;\n\n const handleClick = event => {\n if (!selected && onChange) {\n onChange(event, value);\n }\n\n if (onClick) {\n onClick(event);\n }\n };\n\n const handleFocus = event => {\n if (selectionFollowsFocus && !selected && onChange) {\n onChange(event, value);\n }\n\n if (onFocus) {\n onFocus(event);\n }\n };\n\n return /*#__PURE__*/_jsxs(TabRoot, _extends({\n focusRipple: !disableFocusRipple,\n className: clsx(classes.root, className),\n ref: ref,\n role: \"tab\",\n \"aria-selected\": selected,\n disabled: disabled,\n onClick: handleClick,\n onFocus: handleFocus,\n ownerState: ownerState,\n tabIndex: selected ? 0 : -1\n }, other, {\n children: [iconPosition === 'top' || iconPosition === 'start' ? /*#__PURE__*/_jsxs(React.Fragment, {\n children: [icon, label]\n }) : /*#__PURE__*/_jsxs(React.Fragment, {\n children: [label, icon]\n }), indicator]\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? Tab.propTypes\n/* remove-proptypes */\n= {\n // ----------------------------- Warning --------------------------------\n // | These PropTypes are generated from the TypeScript type definitions |\n // | To update them edit the d.ts file and run \"yarn proptypes\" |\n // ----------------------------------------------------------------------\n\n /**\n * This prop isn't supported.\n * Use the `component` prop if you need to change the children structure.\n */\n children: unsupportedProp,\n\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * If `true`, the component is disabled.\n * @default false\n */\n disabled: PropTypes.bool,\n\n /**\n * If `true`, the keyboard focus ripple is disabled.\n * @default false\n */\n disableFocusRipple: PropTypes.bool,\n\n /**\n * If `true`, the ripple effect is disabled.\n *\n * ⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure\n * to highlight the element by applying separate styles with the `.Mui-focusVisible` class.\n * @default false\n */\n disableRipple: PropTypes.bool,\n\n /**\n * The icon to display.\n */\n icon: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),\n\n /**\n * The position of the icon relative to the label.\n * @default 'top'\n */\n iconPosition: PropTypes.oneOf(['bottom', 'end', 'start', 'top']),\n\n /**\n * The label element.\n */\n label: PropTypes.node,\n\n /**\n * @ignore\n */\n onChange: PropTypes.func,\n\n /**\n * @ignore\n */\n onClick: PropTypes.func,\n\n /**\n * @ignore\n */\n onFocus: PropTypes.func,\n\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),\n\n /**\n * You can provide your own value. Otherwise, we fallback to the child position index.\n */\n value: PropTypes.any,\n\n /**\n * Tab labels appear in a single row.\n * They can use a second line if needed.\n * @default false\n */\n wrapped: PropTypes.bool\n} : void 0;\nexport default Tab;","import React from 'react';\n\nimport {Tab as MuiTab, TabProps as MuiTabProps} from '@mui/material';\nimport type {WithMuiPropOverrides} from '@netx/core-components/Theme';\n\nexport interface TabProps extends WithMuiPropOverrides {}\n\n/**\n * Wrapper for `@material-ui/Tab`\\\n * Provides some common overrides, and accepts all the same props as the component it wraps\n */\nexport const Tab = (props: TabProps) => {\n\treturn ;\n};\n\nexport default Tab;\n","export const ACTIONS = {\n\tUPDATE: 'UPDATE',\n\tSET_LOADING: 'SET_LOADING',\n};\n","import type {AttributeTemplate, Lookups} from '../../types';\nimport {ACTIONS} from './constants';\nimport type {Action} from './actions';\n\nexport type State = {\n\tdata: AttributeTemplate[];\n\thasMandatoryUserDefinedTemplates: boolean;\n\tloading: boolean;\n\tlookups: Lookups;\n};\n\nexport const initialState: State = {\n\tdata: [],\n\thasMandatoryUserDefinedTemplates: false,\n\tloading: false,\n\tlookups: {\n\t\tkeys: [],\n\t\ttargets: [],\n\t},\n};\n\nconst reducer = (state: State, action: Action): State => {\n\tswitch (action.type) {\n\t\tcase ACTIONS.SET_LOADING:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tloading: action.loading,\n\t\t\t};\n\t\tcase ACTIONS.UPDATE: {\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tdata: action.data,\n\t\t\t\thasMandatoryUserDefinedTemplates: action.data.some(\n\t\t\t\t\t(d) => !d.system && d.mandatory === 1,\n\t\t\t\t),\n\t\t\t\t// Get lookup keys/targets from data\n\t\t\t\tlookups: action.data.reduce(\n\t\t\t\t\t(lookups, attr) => {\n\t\t\t\t\t\tif (attr.keyDatasets.length) lookups.keys.push(attr.attributeid);\n\t\t\t\t\t\tif (attr.targetDatasets.length)\n\t\t\t\t\t\t\tlookups.targets.push(attr.attributeid);\n\t\t\t\t\t\treturn lookups;\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tkeys: [],\n\t\t\t\t\t\ttargets: [],\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\t}\n};\n\nexport default reducer;\n","import {\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseCallback,\n\tuseRef,\n} from 'react';\n\nimport attributesSingleton from '@netx/core-asset/collections/singleton/attributes';\nimport useBackboneCollection from '@netx/core-components/hooks/useBackboneCollection';\nimport useUpdateEffect from '@netx/core-components/hooks/useUpdateEffect';\nimport {metadataDatasetLookup} from '../../api/metadataDatasetLookup';\nimport {SYSTEM_ATTRIBUTE_LABELS} from '../../locales';\nimport type {\n\tAttributeId,\n\tAttributeDefaultValues,\n\tAttributeFormValues,\n\tAttributeObjectType,\n\tAttributeTemplate,\n\tAttributeType,\n} from '../../types';\nimport parseValue from '../../utils/parseValue';\nimport {ACTIONS} from './constants';\nimport reducer, {initialState} from './reducer';\n\nexport type UseAttributesParams = {\n\twritableOnly?: boolean;\n\tuserDefinedOnly?: boolean;\n};\n\nexport const useAttributes = ({\n\twritableOnly = false,\n\tuserDefinedOnly = false,\n}: UseAttributesParams = {}) => {\n\t// TODO: until we can wrap the entire app in we just need to utilize the singleton\n\t// and provide some bridging between that and the context\n\tconst attributes = useBackboneCollection(attributesSingleton, false);\n\n\tconst [state, dispatch] = useReducer(reducer, {\n\t\t...initialState,\n\t\tdata: attributes.filter(\n\t\t\t(attr) =>\n\t\t\t\t(!userDefinedOnly || attr.attributeid > -1) &&\n\t\t\t\t(!writableOnly || attr.permission !== 'r'),\n\t\t),\n\t});\n\n\tconst dataRef = useRef(state.data);\n\tdataRef.current = state.data;\n\n\tuseUpdateEffect(() => {\n\t\tconst _attributes = attributes.filter(\n\t\t\t(attr) =>\n\t\t\t\t(!userDefinedOnly || attr.attributeid > -1) &&\n\t\t\t\t(!writableOnly || attr.permission !== 'r'),\n\t\t);\n\n\t\tdispatch({type: ACTIONS.UPDATE, data: _attributes});\n\t}, [attributes, writableOnly, userDefinedOnly]);\n\n\t// Some basic getters\n\n\t/**\n\t * Get all attribute templates\n\t * @param omitReadOnly Omit read only attribute templates\n\t * @return Array of attribute templates\n\t */\n\tconst getAll = useCallback(\n\t\t(\n\t\t\tomitSystem?: boolean,\n\t\t\tomitReadOnly?: boolean,\n\t\t\tobjectType?: AttributeObjectType,\n\t\t) =>\n\t\t\tdataRef.current.filter(\n\t\t\t\t(attr) =>\n\t\t\t\t\t(!omitReadOnly || attr.permission !== 'r') &&\n\t\t\t\t\t(!omitSystem || !attr.system) &&\n\t\t\t\t\t(!objectType || attr.objectTypes.includes(objectType)),\n\t\t\t),\n\t\t[],\n\t);\n\n\t/**\n\t * get attribute template by id\n\t * @param id Attribute template id\n\t * @return Attribute template, if found\n\t */\n\tconst getById = useCallback(\n\t\t(id: AttributeId) =>\n\t\t\tdataRef.current.find((attr) => attr.attributeid === id),\n\t\t[],\n\t);\n\n\t/**\n\t * get attribute templates by ids\n\t * @param ids Attribute template ids\n\t * @return Array of attribute templates found\n\t */\n\tconst getByIds = useCallback(\n\t\t(\n\t\t\tids: AttributeId[],\n\t\t\tomitSystem?: boolean,\n\t\t\tobjectType?: AttributeObjectType,\n\t\t\tomitReadOnly?: boolean,\n\t\t) =>\n\t\t\tids\n\t\t\t\t.map((id) => getById(id))\n\t\t\t\t.filter(\n\t\t\t\t\t(attr) =>\n\t\t\t\t\t\tattr != null &&\n\t\t\t\t\t\t(attr.attributeid > -1 || !omitSystem) &&\n\t\t\t\t\t\t(attr.permission != 'r' || !omitReadOnly) &&\n\t\t\t\t\t\t(!objectType || attr.objectTypes.includes(objectType)),\n\t\t\t\t) as AttributeTemplate[],\n\t\t[],\n\t);\n\n\t/**\n\t * get attribute template by name\\\n\t * _frowned upon but still neccessary in some cases_\n\t * @param name Attribute template name\n\t * @return Attribute template, if found\n\t */\n\tconst getByName = useCallback(\n\t\t(name: string) => dataRef.current.find((attr) => attr.name === name),\n\t\t[],\n\t);\n\n\t/**\n\t * get attribute templates by names\\\n\t * _frowned upon but still neccessary in some cases_\n\t * @param names Attribute template names\n\t * @return Array of attribute templates found\n\t */\n\tconst getByNames = useCallback(\n\t\t(names: string[]) =>\n\t\t\tnames\n\t\t\t\t.map((name) => getByName(name))\n\t\t\t\t.filter((attr) => attr != null) as AttributeTemplate[],\n\t\t[],\n\t);\n\n\tconst getByType = useCallback(\n\t\t(type: AttributeType, omitSystem?: boolean) =>\n\t\t\tdataRef.current.filter(\n\t\t\t\t(attr) => attr.type === type && (attr.attributeid > -1 || !omitSystem),\n\t\t\t),\n\t\t[],\n\t);\n\n\t/**\n\t * get attribute template label by id\n\t * @param id Attribute template id\n\t * @return Attribute template label, if found\n\t */\n\tconst getLabelById = useCallback((id: AttributeId) => {\n\t\tconst attr = getById(id);\n\t\tif (!attr) return `!${id} unknown!`;\n\t\tif (!attr.system) return attr.name;\n\t\treturn SYSTEM_ATTRIBUTE_LABELS[id] || i18n.t(`i18n.${attr.name}`);\n\t}, []);\n\n\t/**\n\t * get default attribute template values\n\t * @param limitToIds Limit the returned values to the provided attribute template ids\n\t * @return Attribute values indexed by id\n\t */\n\tconst getDefaultValues = useCallback((limitToIds?: AttributeId[]) => {\n\t\tconst defaults = dataRef.current.reduce(\n\t\t\t(defaultValues, d) => {\n\t\t\t\tif (\n\t\t\t\t\t(limitToIds && !limitToIds.includes(d.attributeid)) ||\n\t\t\t\t\td.value == null ||\n\t\t\t\t\td.value === ''\n\t\t\t\t)\n\t\t\t\t\treturn defaultValues;\n\t\t\t\treturn {\n\t\t\t\t\t...defaultValues,\n\t\t\t\t\t[d.attributeid]: parseValue(d.type, d.value) as string[], // TODO: get the attribute values wrangled\n\t\t\t\t};\n\t\t\t},\n\t\t\t{},\n\t\t);\n\t\treturn defaults;\n\t}, []);\n\n\t// Some utils\n\n\t/**\n\t * perform attribute metadata lookup\n\t * @param attribute Attribute template to perform lookup from\n\t * @param lookupValue Value to perform lookup with\n\t * @param limitToIds Attribute template id\n\t * @return Attribute values indexed by id\n\t */\n\tconst lookup = useCallback(\n\t\tasync (\n\t\t\tattribute: AttributeTemplate,\n\t\t\tlookupValue: string,\n\t\t\tlimitToIds?: AttributeId[],\n\t\t) => {\n\t\t\tconst lookupResults = await metadataDatasetLookup({\n\t\t\t\tname: attribute.name,\n\t\t\t\tvalue: lookupValue,\n\t\t\t});\n\n\t\t\t// For each result, update the attribute values if possible\n\t\t\treturn lookupResults.reduce