{"version":3,"file":"index.js","sources":["../../../../src/packages/core/validation/events/validation.event.ts","../../../../src/packages/core/validation/events/validation-valid.event.ts","../../../../src/packages/core/validation/events/validation-invalid.event.ts","../../../../src/packages/core/validation/components/form-validation-message.element.ts","../../../../src/packages/core/validation/const.ts","../../../../src/packages/core/validation/utils/json-path.function.ts","../../../../src/packages/core/validation/context/validation.context-token.ts","../../../../src/packages/core/validation/context/validation-messages.manager.ts","../../../../src/packages/core/validation/controllers/validation.controller.ts","../../../../src/packages/core/validation/context/validation.context.ts","../../../../src/packages/core/validation/context/server-model-validator.context-token.ts","../../../../src/packages/core/validation/utils/data-path-property-value-query.function.ts","../../../../src/packages/core/validation/utils/data-path-variant-query.function.ts","../../../../src/packages/core/validation/utils/extract-json-query-properties.function.ts","../../../../src/packages/core/validation/context/server-model-validator.context.ts","../../../../src/packages/core/validation/controllers/bind-server-validation-to-form-control.controller.ts","../../../../src/packages/core/validation/controllers/form-control-validator.controller.ts","../../../../src/packages/core/validation/controllers/observe-validation-state.controller.ts","../../../../src/packages/core/validation/directives/bind-to-validation.lit-directive.ts","../../../../src/packages/core/validation/mixins/form-control.mixin.ts","../../../../src/packages/core/validation/translators/validation-path-translator-base.controller.ts","../../../../src/packages/core/validation/translators/abstract-array-path-translator.controller.ts","../../../../src/packages/core/validation/translators/variant-values-validation-path-translator.controller.ts","../../../../src/packages/core/validation/translators/variants-validation-path-translator.controller.ts"],"sourcesContent":["export class UmbValidationEvent extends Event {\r\n\tpublic constructor(type: string) {\r\n\t\tsuper(type, { bubbles: true, composed: false, cancelable: false });\r\n\t}\r\n}\r\n","import { UmbValidationEvent } from './validation.event.js';\r\n\r\nexport class UmbValidationValidEvent extends UmbValidationEvent {\r\n\tstatic readonly TYPE = 'valid';\r\n\r\n\tconstructor() {\r\n\t\tsuper(UmbValidationValidEvent.TYPE);\r\n\t}\r\n}\r\n","import { UmbValidationEvent } from './validation.event.js';\r\n\r\nexport class UmbValidationInvalidEvent extends UmbValidationEvent {\r\n\tstatic readonly TYPE = 'invalid';\r\n\r\n\tpublic constructor() {\r\n\t\tsuper(UmbValidationInvalidEvent.TYPE);\r\n\t}\r\n}\r\n","import { UmbValidationInvalidEvent, UmbValidationValidEvent } from '../events/index.js';\r\nimport type { UmbFormControlMixinInterface } from '../mixins/index.js';\r\nimport { css, customElement, html, property, repeat, unsafeHTML } from '@umbraco-cms/backoffice/external/lit';\r\nimport { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';\r\n\r\n/**\r\n * @description - Component for displaying one or more validation messages from UMB/UUI Form Control within the given scope.\r\n * Notice: Only supports components that is build on the UMB / UUI FormControlMixing.\r\n * @slot - for button contents\r\n * @slot message - for extras in the messages container\r\n * @see FormControlMixin\r\n */\r\n@customElement('umb-form-validation-message')\r\nexport class UmbFormValidationMessageElement extends UmbLitElement {\r\n\t/**\r\n\t * Set the element containing Form Controls of interest.\r\n\t * @type {string}\r\n\t * @default\r\n\t */\r\n\t@property({ reflect: false, attribute: true })\r\n\tpublic get for(): HTMLElement | string | null {\r\n\t\treturn this._for;\r\n\t}\r\n\tpublic set for(value: HTMLElement | string | null) {\r\n\t\tlet element = null;\r\n\t\tif (typeof value === 'string') {\r\n\t\t\tconst scope = this.getRootNode();\r\n\t\t\telement = (scope as DocumentFragment)?.getElementById(value);\r\n\t\t} else if (value instanceof HTMLElement) {\r\n\t\t\telement = value;\r\n\t\t}\r\n\t\tconst newScope = element ?? this;\r\n\t\tconst oldScope = this._for;\r\n\r\n\t\tif (oldScope === newScope) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (oldScope !== null) {\r\n\t\t\toldScope.removeEventListener(UmbValidationInvalidEvent.TYPE, this.#onControlInvalid as EventListener);\r\n\t\t\toldScope.removeEventListener(UmbValidationValidEvent.TYPE, this.#onControlValid as EventListener);\r\n\t\t}\r\n\t\tthis._for = newScope;\r\n\t\tthis._for.addEventListener(UmbValidationInvalidEvent.TYPE, this.#onControlInvalid as EventListener);\r\n\t\tthis._for.addEventListener(UmbValidationValidEvent.TYPE, this.#onControlValid as EventListener);\r\n\t}\r\n\tprivate _for: HTMLElement | null = null;\r\n\r\n\tconstructor() {\r\n\t\tsuper();\r\n\t\tif (this.for === null) {\r\n\t\t\tthis.for = this;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate _messages = new Map, string>();\r\n\r\n\t#onControlInvalid = async (e: UmbValidationInvalidEvent) => {\r\n\t\tconst ctrl = (e as any).composedPath()[0];\r\n\t\tif (ctrl.pristine === false) {\r\n\t\t\t// Currently we only show message from components who does have the pristine property. (we only want to show messages from fields that are NOT pristine aka. that are dirty or in a from that has been submitted)\r\n\t\t\t// Notice we use the localization controller here, this is different frm the UUI component which uses the same name.\r\n\t\t\tthis._messages.set(ctrl, this.localize.string(ctrl.validationMessage));\r\n\t\t} else {\r\n\t\t\tthis._messages.delete(ctrl);\r\n\t\t}\r\n\t\tthis.requestUpdate();\r\n\t};\r\n\r\n\t#onControlValid = (e: UmbValidationValidEvent) => {\r\n\t\tconst ctrl = (e as any).composedPath()[0];\r\n\t\tthis._messages.delete(ctrl);\r\n\t\tthis.requestUpdate();\r\n\t};\r\n\r\n\toverride render() {\r\n\t\treturn html`\r\n\t\t\t\r\n\t\t\t
\r\n\t\t\t\t${repeat(this._messages, (item) => html`
${unsafeHTML(item[1])}
`)}\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t`;\r\n\t}\r\n\r\n\tstatic override styles = [\r\n\t\tcss`\r\n\t\t\t#messages {\r\n\t\t\t\tcolor: var(--uui-color-danger-standalone);\r\n\t\t\t}\r\n\t\t`,\r\n\t];\r\n}\r\ndeclare global {\r\n\tinterface HTMLElementTagNameMap {\r\n\t\t'umb-form-validation-message': UmbFormValidationMessageElement;\r\n\t}\r\n}\r\n","export const UMB_VALIDATION_EMPTY_LOCALIZATION_KEY = '#validation_invalidEmpty';\r\n","/**\r\n *\r\n * @param {object} data - object to traverse for the value.\r\n * @param {string} path - the JSON path to the value that should be found\r\n * @returns {unknown} - the found value.\r\n */\r\nexport function GetValueByJsonPath(data: unknown, path: string): unknown {\r\n\t// strip $ from the path:\r\n\tconst strippedPath = path.startsWith('$.') ? path.slice(2) : path;\r\n\t// get value from the path:\r\n\treturn GetNextPropertyValueFromPath(data, strippedPath);\r\n}\r\n\r\n/**\r\n *\r\n * @param {object} data - object to traverse for the value.\r\n * @param {string} path - the JSON path to the value that should be found\r\n * @returns {unknown} - the found value.\r\n */\r\nfunction GetNextPropertyValueFromPath(data: any, path: string): any {\r\n\tif (!data) return undefined;\r\n\t// find next '.' or '[' in the path, using regex:\r\n\tconst match = path.match(/\\.|\\[/);\r\n\t// If no match is found, we assume its a single key so lets return the value of the key:\r\n\tif (match === null || match.index === undefined) return data[path];\r\n\r\n\t// split the path at the first match:\r\n\tconst key = path.slice(0, match.index);\r\n\tconst rest = path.slice(match.index + 1);\r\n\r\n\tif (!key) return undefined;\r\n\t// get the value of the key from the data:\r\n\tconst value = data[key];\r\n\t// if there is no rest of the path, return the value:\r\n\tif (rest === undefined) return value;\r\n\t// if the value is an array, get the value at the index:\r\n\tif (Array.isArray(value)) {\r\n\t\t// get the value until the next ']', the value can be anything in between the brackets:\r\n\t\tconst lookupEnd = rest.match(/\\]/);\r\n\t\tif (!lookupEnd) return undefined;\r\n\t\t// get everything before the match:\r\n\t\tconst entryPointer = rest.slice(0, lookupEnd.index);\r\n\r\n\t\t// check if the entryPointer is a JSON Path Filter ( starting with ?( and ending with ) ):\r\n\t\tif (entryPointer.startsWith('?(') && entryPointer.endsWith(')')) {\r\n\t\t\t// get the filter from the entryPointer:\r\n\t\t\t// get the filter as a function:\r\n\t\t\tconst jsFilter = JsFilterFromJsonPathFilter(entryPointer);\r\n\t\t\t// find the index of the value that matches the filter:\r\n\t\t\tconst index = value.findIndex(jsFilter[0]);\r\n\t\t\t// if the index is -1, return undefined:\r\n\t\t\tif (index === -1) return undefined;\r\n\t\t\t// get the value at the index:\r\n\t\t\tconst data = value[index];\r\n\t\t\t// Check for safety:\r\n\t\t\tif (lookupEnd.index === undefined || lookupEnd.index + 1 >= rest.length) {\r\n\t\t\t\treturn data;\r\n\t\t\t}\r\n\t\t\t// continue with the rest of the path:\r\n\t\t\treturn GetNextPropertyValueFromPath(data, rest.slice(lookupEnd.index + 2)) ?? data;\r\n\t\t} else {\r\n\t\t\t// get the value at the index:\r\n\t\t\tconst indexAsNumber = parseInt(entryPointer);\r\n\t\t\tif (isNaN(indexAsNumber)) return undefined;\r\n\t\t\tconst data = value[indexAsNumber];\r\n\t\t\t// Check for safety:\r\n\t\t\tif (lookupEnd.index === undefined || lookupEnd.index + 1 >= rest.length) {\r\n\t\t\t\treturn data;\r\n\t\t\t}\r\n\t\t\t// continue with the rest of the path:\r\n\t\t\treturn GetNextPropertyValueFromPath(data, rest.slice(lookupEnd.index + 2)) ?? data;\r\n\t\t}\r\n\t} else {\r\n\t\t// continue with the rest of the path:\r\n\t\treturn GetNextPropertyValueFromPath(value, rest);\r\n\t}\r\n}\r\n\r\n/**\r\n * @param {string} filter - A JSON Query, limited to filtering features. Do not support other JSON PATH Query features.\r\n * @returns {Array<(queryFilter: any) => boolean>} - An array of methods that returns true if the given items property value matches the value of the query.\r\n */\r\nfunction JsFilterFromJsonPathFilter(filter: string): Array<(item: any) => boolean> {\r\n\t// strip ?( and ) from the filter\r\n\tconst jsFilter = filter.slice(2, -1);\r\n\t// split the filter into parts by splitting at ' && '\r\n\tconst parts = jsFilter.split(' && ');\r\n\t// map each part to a function that returns true if the part is true\r\n\treturn parts.map((part) => {\r\n\t\t// split the part into key and value\r\n\t\tconst [path, equal] = part.split(' == ');\r\n\t\t// remove @.\r\n\t\tconst key = path.slice(2);\r\n\t\t// remove quotes:\r\n\t\tconst value = equal.slice(1, -1);\r\n\t\t// return a function that returns true if the key is equal to the value\r\n\t\treturn (item: any) => item[key] === value;\r\n\t});\r\n}\r\n","import type { UmbValidationController } from '../controllers/validation.controller.js';\r\nimport { UmbContextToken } from '@umbraco-cms/backoffice/context-api';\r\n\r\nexport const UMB_VALIDATION_CONTEXT = new UmbContextToken('UmbValidationContext');\r\n","import type { UmbValidationMessageTranslator } from '../translators/validation-message-path-translator.interface.js';\r\nimport type { Observable } from '@umbraco-cms/backoffice/external/rxjs';\r\nimport { UmbId } from '@umbraco-cms/backoffice/id';\r\nimport { UmbArrayState } from '@umbraco-cms/backoffice/observable-api';\r\n\r\nexport type UmbValidationMessageType = 'client' | 'server';\r\nexport interface UmbValidationMessage {\r\n\ttype: UmbValidationMessageType;\r\n\tkey: string;\r\n\tpath: string;\r\n\tbody: string;\r\n}\r\n\r\n/**\r\n * Matches a path or a descendant path.\r\n * @param {string} source The path to check.\r\n * @param {string} match The path to match against, the source must forfill all of the match, but the source can be further specific.\r\n * @returns {boolean} True if the path matches or is a descendant path.\r\n */\r\nfunction MatchPathOrDescendantPath(source: string, match: string): boolean {\r\n\t// Find messages that starts with the given path, if the path is longer then require a dot or [ as the next character. using a more performant way than Regex:\r\n\treturn (\r\n\t\tsource.indexOf(match) === 0 &&\r\n\t\t(source.length === match.length || source[match.length] === '.' || source[match.length] === '[')\r\n\t);\r\n}\r\n\r\nexport class UmbValidationMessagesManager {\r\n\t#messages = new UmbArrayState([], (x) => x.key);\r\n\tmessages = this.#messages.asObservable();\r\n\r\n\tdebug(logName: string) {\r\n\t\tthis.messages.subscribe((x) => console.log(logName, x));\r\n\t}\r\n\r\n\tgetHasAnyMessages(): boolean {\r\n\t\treturn this.#messages.getValue().length !== 0;\r\n\t}\r\n\r\n\tgetMessagesOfPathAndDescendant(path: string): Array {\r\n\t\t//path = path.toLowerCase();\r\n\t\treturn this.#messages.getValue().filter((x) => MatchPathOrDescendantPath(x.path, path));\r\n\t}\r\n\r\n\tmessagesOfPathAndDescendant(path: string): Observable> {\r\n\t\t//path = path.toLowerCase();\r\n\t\treturn this.#messages.asObservablePart((msgs) => msgs.filter((x) => MatchPathOrDescendantPath(x.path, path)));\r\n\t}\r\n\r\n\tmessagesOfTypeAndPath(type: UmbValidationMessageType, path: string): Observable> {\r\n\t\t//path = path.toLowerCase();\r\n\t\t// Find messages that matches the given type and path.\r\n\t\treturn this.#messages.asObservablePart((msgs) => msgs.filter((x) => x.type === type && x.path === path));\r\n\t}\r\n\r\n\thasMessagesOfPathAndDescendant(path: string): Observable {\r\n\t\t//path = path.toLowerCase();\r\n\t\treturn this.#messages.asObservablePart((msgs) => msgs.some((x) => MatchPathOrDescendantPath(x.path, path)));\r\n\t}\r\n\tgetHasMessagesOfPathAndDescendant(path: string): boolean {\r\n\t\t//path = path.toLowerCase();\r\n\t\treturn this.#messages\r\n\t\t\t.getValue()\r\n\t\t\t.some(\r\n\t\t\t\t(x) =>\r\n\t\t\t\t\tx.path.indexOf(path) === 0 &&\r\n\t\t\t\t\t(x.path.length === path.length || x.path[path.length] === '.' || x.path[path.length] === '['),\r\n\t\t\t);\r\n\t}\r\n\r\n\taddMessage(type: UmbValidationMessageType, path: string, body: string, key: string = UmbId.new()): void {\r\n\t\t//path = this.#translatePath(path.toLowerCase()) ?? path.toLowerCase();\r\n\t\tpath = this.#translatePath(path) ?? path;\r\n\t\t// check if there is an existing message with the same path and type, and append the new messages: [NL]\r\n\t\tif (this.#messages.getValue().find((x) => x.type === type && x.path === path && x.body === body)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.#messages.appendOne({ type, key, path, body: body });\r\n\t}\r\n\r\n\taddMessages(type: UmbValidationMessageType, path: string, bodies: Array): void {\r\n\t\t//path = this.#translatePath(path.toLowerCase()) ?? path.toLowerCase();\r\n\t\tpath = this.#translatePath(path) ?? path;\r\n\t\t// filter out existing messages with the same path and type, and append the new messages: [NL]\r\n\t\tconst existingMessages = this.#messages.getValue();\r\n\t\tconst newBodies = bodies.filter(\r\n\t\t\t(message) => existingMessages.find((x) => x.type === type && x.path === path && x.body === message) === undefined,\r\n\t\t);\r\n\t\tthis.#messages.append(newBodies.map((body) => ({ type, key: UmbId.new(), path, body })));\r\n\t}\r\n\r\n\tremoveMessageByKey(key: string): void {\r\n\t\tthis.#messages.removeOne(key);\r\n\t}\r\n\tremoveMessageByKeys(keys: Array): void {\r\n\t\tthis.#messages.filter((x) => keys.indexOf(x.key) === -1);\r\n\t}\r\n\tremoveMessagesByType(type: UmbValidationMessageType): void {\r\n\t\tthis.#messages.filter((x) => x.type !== type);\r\n\t}\r\n\tremoveMessagesByPath(path: string): void {\r\n\t\tthis.#messages.filter((x) => x.path !== path);\r\n\t}\r\n\tremoveMessagesAndDescendantsByPath(path: string): void {\r\n\t\tthis.#messages.filter((x) => MatchPathOrDescendantPath(x.path, path));\r\n\t}\r\n\tremoveMessagesByTypeAndPath(type: UmbValidationMessageType, path: string): void {\r\n\t\t//path = path.toLowerCase();\r\n\t\tthis.#messages.filter((x) => !(x.type === type && x.path === path));\r\n\t}\r\n\r\n\t#translatePath(path: string): string | undefined {\r\n\t\t//path = path.toLowerCase();\r\n\t\tfor (const translator of this.#translators) {\r\n\t\t\tconst newPath = translator.translate(path);\r\n\t\t\t// If not undefined or false, then it was a valid translation: [NL]\r\n\t\t\tif (newPath) {\r\n\t\t\t\t// Lets try to translate it again, this will recursively translate the path until no more translations are possible (and then fallback to '?? newpath') [NL]\r\n\t\t\t\treturn this.#translatePath(newPath) ?? newPath;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\t#translators: Array = [];\r\n\taddTranslator(translator: UmbValidationMessageTranslator): void {\r\n\t\tif (this.#translators.indexOf(translator) === -1) {\r\n\t\t\tthis.#translators.push(translator);\r\n\t\t}\r\n\t\t// execute translators on all messages:\r\n\t\t// Notice we are calling getValue() in each iteration to avoid the need to re-translate the same messages over and over again. [NL]\r\n\t\tfor (const msg of this.#messages.getValue()) {\r\n\t\t\tconst newPath = this.#translatePath(msg.path);\r\n\t\t\t// If newPath is not false or undefined, a translation of it has occurred, meaning we ant to update it: [NL]\r\n\t\t\tif (newPath) {\r\n\t\t\t\t// update the specific message, with its new path: [NL]\r\n\t\t\t\tthis.#messages.updateOne(msg.key, { path: newPath });\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tremoveTranslator(translator: UmbValidationMessageTranslator): void {\r\n\t\tconst index = this.#translators.indexOf(translator);\r\n\t\tif (index !== -1) {\r\n\t\t\tthis.#translators.splice(index, 1);\r\n\t\t}\r\n\t}\r\n\r\n\tclear(): void {\r\n\t\tthis.#messages.setValue([]);\r\n\t}\r\n\r\n\tdestroy(): void {\r\n\t\tthis.#translators = [];\r\n\t\tthis.#messages.destroy();\r\n\t}\r\n}\r\n","import type { UmbValidator } from '../interfaces/validator.interface.js';\r\nimport type { UmbValidationMessageTranslator } from '../translators/index.js';\r\nimport { GetValueByJsonPath } from '../utils/json-path.function.js';\r\nimport { UMB_VALIDATION_CONTEXT } from '../context/validation.context-token.js';\r\nimport { type UmbValidationMessage, UmbValidationMessagesManager } from '../context/validation-messages.manager.js';\r\nimport type { UmbContextProviderController } from '@umbraco-cms/backoffice/context-api';\r\nimport { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';\r\n\r\n/**\r\n * Helper method to replace the start of a string with another string.\r\n * @param path {string}\r\n * @param startFrom {string}\r\n * @param startTo {string}\r\n * @returns {string}\r\n */\r\nfunction ReplaceStartOfString(path: string, startFrom: string, startTo: string): string {\r\n\tif (path.startsWith(startFrom + '.')) {\r\n\t\treturn startTo + path.slice(startFrom.length);\r\n\t}\r\n\treturn path;\r\n}\r\n\r\n/**\r\n * Validation Context is the core of Validation.\r\n * It hosts Validators that has to validate for the context to be valid.\r\n * It can also be used as a Validator as part of a parent Validation Context.\r\n */\r\nexport class UmbValidationController extends UmbControllerBase implements UmbValidator {\r\n\t// The current provider controller, that is providing this context:\r\n\t#providerCtrl?: UmbContextProviderController<\r\n\t\tUmbValidationController,\r\n\t\tUmbValidationController,\r\n\t\tUmbValidationController\r\n\t>;\r\n\r\n\t// Local version of the data send to the server, only use-case is for translation.\r\n\t#translationData = new UmbObjectState(undefined);\r\n\ttranslationDataOf(path: string): any {\r\n\t\treturn this.#translationData.asObservablePart((data) => GetValueByJsonPath(data, path));\r\n\t}\r\n\tsetTranslationData(data: any): void {\r\n\t\tthis.#translationData.setValue(data);\r\n\t}\r\n\tgetTranslationData(): any {\r\n\t\treturn this.#translationData.getValue();\r\n\t}\r\n\r\n\t#validators: Array = [];\r\n\t#validationMode: boolean = false;\r\n\t#isValid: boolean = false;\r\n\r\n\t#parent?: UmbValidationController;\r\n\t#parentMessages?: Array;\r\n\t#localMessages?: Array;\r\n\t#baseDataPath?: string;\r\n\r\n\tpublic readonly messages = new UmbValidationMessagesManager();\r\n\r\n\tconstructor(host: UmbControllerHost) {\r\n\t\t// This is overridden to avoid setting a controllerAlias, this might make sense, but currently i want to leave it out. [NL]\r\n\t\tsuper(host);\r\n\t}\r\n\r\n\t/**\r\n\t * Add a path translator to this validation context.\r\n\t * @param translator\r\n\t */\r\n\tasync addTranslator(translator: UmbValidationMessageTranslator) {\r\n\t\tthis.messages.addTranslator(translator);\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a path translator from this validation context.\r\n\t * @param translator\r\n\t */\r\n\tasync removeTranslator(translator: UmbValidationMessageTranslator) {\r\n\t\t// Because this may have been destroyed at this point. and because we do not know if a context has been destroyed, then we allow this call, but let it soft-fail if messages does not exists. [NL]\r\n\t\tthis.messages?.removeTranslator(translator);\r\n\t}\r\n\r\n\t#currentProvideHost?: UmbClassInterface;\r\n\t/**\r\n\t * Provide this validation context to a specific controller host.\r\n\t * This can be used to Host a validation context in a Workspace, but provide it on a certain scope, like a specific Workspace View.\r\n\t * @param controllerHost {UmbClassInterface}\r\n\t */\r\n\tprovideAt(controllerHost: UmbClassInterface): void {\r\n\t\tif (this.#currentProvideHost === controllerHost) return;\r\n\t\tthis.#providerCtrl?.destroy();\r\n\t\tthis.#currentProvideHost = controllerHost;\r\n\t\tthis.#providerCtrl = controllerHost.provideContext(UMB_VALIDATION_CONTEXT, this);\r\n\t}\r\n\r\n\t/**\r\n\t * Define a specific data path for this validation context.\r\n\t * This will turn this validation context into a sub-context of the parent validation context.\r\n\t * This means that a two-way binding for messages will be established between the parent and the sub-context.\r\n\t * And it will inherit the Translation Data from its parent.\r\n\t *\r\n\t * messages and data will be localizes accordingly to the given data path.\r\n\t * @param dataPath {string} - The data path to bind this validation context to.\r\n\t * @example\r\n\t * ```ts\r\n\t * const validationContext = new UmbValidationContext(this);\r\n\t * validationContext.setDataPath(\"$.values[?(@.alias == 'my-property')].value\");\r\n\t * ```\r\n\t *\r\n\t * A message with the path: '$.values[?(@.alias == 'my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context.\r\n\t */\r\n\tsetDataPath(dataPath: string): void {\r\n\t\tif (this.#baseDataPath) {\r\n\t\t\tif (this.#baseDataPath === dataPath) return;\r\n\t\t\t// Just fire an error, as I haven't made the right clean up jet. Or haven't thought about what should happen if it changes while already setup.\r\n\t\t\t// cause maybe all the messages should be removed as we are not interested in the old once any more. But then on the other side, some might be relevant as this is the same entity that changed its paths?\r\n\t\t\tthrow new Error('Data path is already set, we do not support changing the context data-path as of now.');\r\n\t\t}\r\n\t\tif (!dataPath) return;\r\n\t\tthis.#baseDataPath = dataPath;\r\n\r\n\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (parent) => {\r\n\t\t\tif (this.#parent) {\r\n\t\t\t\tthis.#parent.removeValidator(this);\r\n\t\t\t}\r\n\t\t\tthis.#parent = parent;\r\n\t\t\tparent.addValidator(this);\r\n\r\n\t\t\tthis.messages.clear();\r\n\r\n\t\t\tthis.observe(parent.translationDataOf(dataPath), (data) => {\r\n\t\t\t\tthis.setTranslationData(data);\r\n\t\t\t});\r\n\r\n\t\t\tthis.observe(\r\n\t\t\t\tparent.messages.messagesOfPathAndDescendant(dataPath),\r\n\t\t\t\t(msgs) => {\r\n\t\t\t\t\t//this.messages.appendMessages(msgs);\r\n\t\t\t\t\tif (this.#parentMessages) {\r\n\t\t\t\t\t\t// Remove the local messages that does not exist in the parent anymore:\r\n\t\t\t\t\t\tconst toRemove = this.#parentMessages.filter((msg) => !msgs.find((m) => m.key === msg.key));\r\n\t\t\t\t\t\tthis.#parent!.messages.removeMessageByKeys(toRemove.map((msg) => msg.key));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.#parentMessages = msgs;\r\n\t\t\t\t\tmsgs.forEach((msg) => {\r\n\t\t\t\t\t\tconst path = ReplaceStartOfString(msg.path, this.#baseDataPath!, '$');\r\n\t\t\t\t\t\t// Notice, the local message uses the same key. [NL]\r\n\t\t\t\t\t\tthis.messages.addMessage(msg.type, path, msg.body, msg.key);\r\n\t\t\t\t\t});\r\n\t\t\t\t},\r\n\t\t\t\t'observeParentMessages',\r\n\t\t\t);\r\n\r\n\t\t\tthis.observe(\r\n\t\t\t\tthis.messages.messages,\r\n\t\t\t\t(msgs) => {\r\n\t\t\t\t\tif (!this.#parent) return;\r\n\t\t\t\t\t//this.messages.appendMessages(msgs);\r\n\t\t\t\t\tif (this.#localMessages) {\r\n\t\t\t\t\t\t// Remove the parent messages that does not exist locally anymore:\r\n\t\t\t\t\t\tconst toRemove = this.#localMessages.filter((msg) => !msgs.find((m) => m.key === msg.key));\r\n\t\t\t\t\t\tthis.#parent!.messages.removeMessageByKeys(toRemove.map((msg) => msg.key));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.#localMessages = msgs;\r\n\t\t\t\t\tmsgs.forEach((msg) => {\r\n\t\t\t\t\t\t// replace this.#baseDataPath (if it starts with it) with $ in the path, so it becomes relative to the parent context\r\n\t\t\t\t\t\tconst path = ReplaceStartOfString(msg.path, '$', this.#baseDataPath!);\r\n\t\t\t\t\t\t// Notice, the parent message uses the same key. [NL]\r\n\t\t\t\t\t\tthis.#parent!.messages.addMessage(msg.type, path, msg.body, msg.key);\r\n\t\t\t\t\t});\r\n\t\t\t\t},\r\n\t\t\t\t'observeLocalMessages',\r\n\t\t\t);\r\n\t\t}).skipHost();\r\n\t\t// Notice skipHost ^^, this is because we do not want it to consume it self, as this would be a match for this consumption, instead we will look at the parent and above. [NL]\r\n\t}\r\n\r\n\t/**\r\n\t * Get if this context is valid.\r\n\t * Notice this does not verify the validity.\r\n\t * @returns {boolean}\r\n\t */\r\n\tget isValid(): boolean {\r\n\t\treturn this.#isValid;\r\n\t}\r\n\r\n\t/**\r\n\t * Add a validator to this context.\r\n\t * This validator will have to be valid for the context to be valid.\r\n\t * If the context is in validation mode, the validator will be validated immediately.\r\n\t * @param validator { UmbValidator } - The validator to add to this context.\r\n\t */\r\n\taddValidator(validator: UmbValidator): void {\r\n\t\tif (this.#validators.includes(validator)) return;\r\n\t\tthis.#validators.push(validator);\r\n\t\t//validator.addEventListener('change', this.#onValidatorChange);\r\n\t\tif (this.#validationMode) {\r\n\t\t\tthis.validate();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Remove a validator from this context.\r\n\t * @param validator {UmbValidator} - The validator to remove from this context.\r\n\t */\r\n\tremoveValidator(validator: UmbValidator): void {\r\n\t\tconst index = this.#validators.indexOf(validator);\r\n\t\tif (index !== -1) {\r\n\t\t\t// Remove the validator:\r\n\t\t\tthis.#validators.splice(index, 1);\r\n\t\t\t// If we are in validation mode then we should re-validate to focus next invalid element:\r\n\t\t\tif (this.#validationMode) {\r\n\t\t\t\tthis.validate();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Validate this context, all the validators of this context will be validated.\r\n\t * Notice its a recursive check meaning sub validation contexts also validates their validators.\r\n\t * @returns succeed {Promise} - Returns a promise that resolves to true if the validation succeeded.\r\n\t */\r\n\tasync validate(): Promise {\r\n\t\t// TODO: clear server messages here?, well maybe only if we know we will get new server messages? Do the server messages hook into the system like another validator?\r\n\t\tthis.#validationMode = true;\r\n\r\n\t\tconst resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then(\r\n\t\t\t() => true,\r\n\t\t\t() => false,\r\n\t\t);\r\n\r\n\t\tif (!this.messages) {\r\n\t\t\t// This Context has been destroyed while is was validating, so we should not continue.\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// If we have any messages then we are not valid, otherwise lets check the validation results: [NL]\r\n\t\t// This enables us to keep client validations though UI is not present anymore — because the client validations got defined as messages. [NL]\r\n\t\tconst isValid = this.messages.getHasAnyMessages() ? false : resultsStatus;\r\n\r\n\t\tthis.#isValid = isValid;\r\n\r\n\t\tif (isValid === false) {\r\n\t\t\t// Focus first invalid element:\r\n\t\t\tthis.focusFirstInvalidElement();\r\n\t\t\treturn Promise.reject();\r\n\t\t}\r\n\r\n\t\treturn Promise.resolve();\r\n\t}\r\n\r\n\t/**\r\n\t * Focus the first invalid element that this context can find.\r\n\t */\r\n\tfocusFirstInvalidElement(): void {\r\n\t\tconst firstInvalid = this.#validators.find((v) => !v.isValid);\r\n\t\tif (firstInvalid) {\r\n\t\t\tfirstInvalid.focusFirstInvalidElement();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Reset the validation state of this context.\r\n\t */\r\n\treset(): void {\r\n\t\tthis.#validationMode = false;\r\n\t\tthis.#validators.forEach((v) => v.reset());\r\n\t}\r\n\r\n\t#destroyValidators(): void {\r\n\t\tif (this.#validators === undefined || this.#validators.length === 0) return;\r\n\t\tthis.#validators.forEach((validator) => {\r\n\t\t\tvalidator.destroy();\r\n\t\t\t//validator.removeEventListener('change', this.#runValidate);\r\n\t\t});\r\n\t\tthis.#validators = [];\r\n\t}\r\n\r\n\toverride destroy(): void {\r\n\t\tthis.#providerCtrl = undefined;\r\n\t\tif (this.#parent) {\r\n\t\t\tthis.#parent.removeValidator(this);\r\n\t\t}\r\n\t\tthis.#parent = undefined;\r\n\t\tthis.#destroyValidators();\r\n\t\tthis.messages?.destroy();\r\n\t\t(this.messages as unknown) = undefined;\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n","import { UmbValidationController } from '../controllers/validation.controller.js';\r\nimport { UMB_VALIDATION_CONTEXT } from './validation.context-token.js';\r\nimport type { UmbClassInterface } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n/**\r\n * Validation Context is the core of Validation.\r\n * It hosts Validators that has to validate for the context to be valid.\r\n * It can also be used as a Validator as part of a parent Validation Context.\r\n */\r\nexport class UmbValidationContext extends UmbValidationController {\r\n\tconstructor(host: UmbControllerHost) {\r\n\t\t// This is overridden to avoid setting a controllerAlias, this might make sense, but currently i want to leave it out. [NL]\r\n\t\tsuper(host);\r\n\t\tthis.provideContext(UMB_VALIDATION_CONTEXT, this);\r\n\t}\r\n\r\n\t/**\r\n\t * Provides the validation context to the current host, if not already provided to a different host.\r\n\t * @deprecated No need to provide, this happens automatically. (Do notice this was necessary in 14.3.-rc, but removed in 14.3 release)\r\n\t * @returns instance {UmbValidationController} - Returns it self.\r\n\t */\r\n\tprovide(): UmbValidationController {\r\n\t\treturn this;\r\n\t}\r\n\r\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n\toverride provideAt(controllerHost: UmbClassInterface): void {\r\n\t\tthrow new Error(\r\n\t\t\t'UmbValidationContext cannot be used to provide at a different host. Use the UmbValidationController instead.',\r\n\t\t);\r\n\t}\r\n}\r\n","import type { UmbServerModelValidatorContext } from './server-model-validator.context.js';\r\nimport { UmbContextToken } from '@umbraco-cms/backoffice/context-api';\r\n\r\nexport const UMB_SERVER_MODEL_VALIDATOR_CONTEXT = new UmbContextToken(\r\n\t'UmbServerModelValidationContext',\r\n);\r\n","import type { UmbPartialSome } from '@umbraco-cms/backoffice/utils';\r\nimport type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/variant';\r\n\r\n/**\r\n * Validation Data Path Query generator for Property Value.\r\n * write a JSON-Path filter similar to `?(@.alias == 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')`\r\n * where culture and segment are optional\r\n * @param {UmbVariantPropertyValueModel} value - the object holding value and alias.\r\n * @returns {string} - a JSON-path query\r\n */\r\nexport function UmbDataPathPropertyValueQuery(\r\n\tvalue: UmbPartialSome, 'culture' | 'segment'>,\r\n): string {\r\n\t// write a array of strings for each property, where alias must be present and culture and segment are optional\r\n\tconst filters: Array = [`@.alias == '${value.alias}'`];\r\n\tif (value.culture !== undefined) {\r\n\t\tfilters.push(`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`);\r\n\t}\r\n\tif (value.segment !== undefined) {\r\n\t\tfilters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`);\r\n\t}\r\n\treturn `?(${filters.join(' && ')})`;\r\n}\r\n","import type { UmbPartialSome } from '@umbraco-cms/backoffice/utils';\r\nimport type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/variant';\r\n\r\n/**\r\n * Validation Data Path query generator for Variant.\r\n * write a JSON-Path filter similar to `?(@.culture == 'en-us' && @.segment == 'mySegment')`\r\n * where segment are optional.\r\n * @param value\r\n * @returns\r\n */\r\nexport function UmbDataPathVariantQuery(\r\n\tvalue: UmbPartialSome, 'segment'>,\r\n): string {\r\n\t// write a array of strings for each property, where culture must be present and segment is optional\r\n\tconst filters: Array = [`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`];\r\n\tif (value.segment !== undefined) {\r\n\t\tfilters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`);\r\n\t}\r\n\treturn `?(${filters.join(' && ')})`;\r\n}\r\n","const propValueRegex = /@\\.([a-zA-Z_$][\\w$]*)\\s*==\\s*['\"]([^'\"]*)['\"]/g;\r\n\r\n/**\r\n * Extracts properties and their values from a JSON path query.\r\n * @param {string} query - The JSON path query.\r\n * @returns {Record} An object containing the properties and their values.\r\n * @example\r\n * ```ts\r\n * const query = `?(@.culture == 'en-us' && @.segment == 'mySegment')`;\r\n * const props = ExtractJsonQueryProps(query);\r\n * console.log(props); // { culture: 'en-us', segment: 'mySegment' }\r\n * ```\r\n */\r\nexport function ExtractJsonQueryProps(query: string): Record {\r\n\t// Object to hold property-value pairs\r\n\tconst propsMap: Record = {};\r\n\tlet match;\r\n\r\n\t// Iterate over all matches\r\n\twhile ((match = propValueRegex.exec(query)) !== null) {\r\n\t\tpropsMap[match[1]] = match[2];\r\n\t}\r\n\r\n\treturn propsMap;\r\n}\r\n","import type { UmbValidator } from '../interfaces/validator.interface.js';\r\nimport { UmbDataPathPropertyValueQuery } from '../utils/index.js';\r\nimport { UMB_VALIDATION_EMPTY_LOCALIZATION_KEY } from '../const.js';\r\nimport { UMB_VALIDATION_CONTEXT } from './validation.context-token.js';\r\nimport { UMB_SERVER_MODEL_VALIDATOR_CONTEXT } from './server-model-validator.context-token.js';\r\nimport { UmbContextBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';\r\n\r\n/** This should ideally be generated by the server, but we currently don't generate error-model-types. */\r\ninterface ValidateErrorResponseBodyModel {\r\n\tdetail: string;\r\n\terrors: Record>;\r\n\tmissingProperties: Array;\r\n\toperationStatus: string;\r\n\tstatus: number;\r\n\ttitle: string;\r\n\ttype: string;\r\n}\r\n\r\nexport class UmbServerModelValidatorContext\r\n\textends UmbContextBase\r\n\timplements UmbValidator\r\n{\r\n\t#validatePromise?: Promise;\r\n\t#validatePromiseResolve?: () => void;\r\n\r\n\t#context?: typeof UMB_VALIDATION_CONTEXT.TYPE;\r\n\t#isValid = true;\r\n\r\n\t#data: any;\r\n\tgetData(): any {\r\n\t\treturn this.#data;\r\n\t}\r\n\r\n\tconstructor(host: UmbControllerHost) {\r\n\t\tsuper(host, UMB_SERVER_MODEL_VALIDATOR_CONTEXT);\r\n\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (context) => {\r\n\t\t\tif (this.#context) {\r\n\t\t\t\tthis.#context.removeValidator(this);\r\n\t\t\t}\r\n\t\t\tthis.#context = context;\r\n\t\t\tcontext.addValidator(this);\r\n\r\n\t\t\t// Run translators?\r\n\t\t}).asPromise();\r\n\t}\r\n\r\n\tasync askServerForValidation(data: unknown, requestPromise: Promise>): Promise {\r\n\t\tthis.#context?.messages.removeMessagesByType('server');\r\n\r\n\t\tthis.#isValid = false;\r\n\t\t//this.#validatePromiseReject?.();\r\n\t\tthis.#validatePromise = new Promise((resolve) => {\r\n\t\t\tthis.#validatePromiseResolve = resolve;\r\n\t\t});\r\n\r\n\t\t// Store this state of the data for translator look ups:\r\n\t\tthis.#data = data;\r\n\t\t// Ask the server for validation...\r\n\t\tconst { error } = await requestPromise;\r\n\r\n\t\tthis.#isValid = error ? false : true;\r\n\t\tif (this.#isValid) {\r\n\t\t\t// Send data to context for translation:\r\n\t\t\tthis.#context?.setTranslationData(undefined);\r\n\t\t} else {\r\n\t\t\tif (!this.#context) {\r\n\t\t\t\tthrow new Error('No context available for translation.');\r\n\t\t\t}\r\n\t\t\t// Send data to context for translation:\r\n\t\t\tthis.#context.setTranslationData(data);\r\n\r\n\t\t\t// We are missing some typing here, but we will just go wild with 'as any': [NL]\r\n\t\t\tconst errorBody = (error as any).body as ValidateErrorResponseBodyModel;\r\n\t\t\t// Check if there are validation errors, since the error might be a generic ApiError\r\n\t\t\tif (errorBody?.errors) {\r\n\t\t\t\tObject.keys(errorBody.errors).forEach((path) => {\r\n\t\t\t\t\t//serverFeedback.push({ path, messages: errorBody.errors[path] });\r\n\t\t\t\t\tthis.#context!.messages.addMessages('server', path, errorBody.errors[path]);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\t// Check if there are missing properties:\r\n\t\t\tif (errorBody?.missingProperties) {\r\n\t\t\t\t// Retrieve the variants of he send data, as those are the once we will declare as missing properties:\r\n\t\t\t\t// Temporary fix for missing properties, as we currently get one for each variant, but we do not know which variant it is for: [NL]\r\n\t\t\t\tconst uniqueMissingProperties = [...new Set(errorBody.missingProperties)];\r\n\t\t\t\tuniqueMissingProperties.forEach((alias) => {\r\n\t\t\t\t\tthis.#data.variants.forEach((variant: any) => {\r\n\t\t\t\t\t\tconst path = `$.values[${UmbDataPathPropertyValueQuery({\r\n\t\t\t\t\t\t\talias: alias,\r\n\t\t\t\t\t\t\tculture: variant.culture,\r\n\t\t\t\t\t\t\tsegment: variant.segment,\r\n\t\t\t\t\t\t})}].value`;\r\n\t\t\t\t\t\tthis.#context!.messages.addMessages('server', path, [UMB_VALIDATION_EMPTY_LOCALIZATION_KEY]);\r\n\t\t\t\t\t});\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.#validatePromiseResolve?.();\r\n\t\tthis.#validatePromiseResolve = undefined;\r\n\t}\r\n\r\n\tget isValid(): boolean {\r\n\t\treturn this.#isValid;\r\n\t}\r\n\tasync validate(): Promise {\r\n\t\tif (this.#validatePromise) {\r\n\t\t\tawait this.#validatePromise;\r\n\t\t}\r\n\t\treturn this.#isValid ? Promise.resolve() : Promise.reject();\r\n\t}\r\n\r\n\treset(): void {}\r\n\r\n\tfocusFirstInvalidElement(): void {}\r\n\r\n\toverride hostConnected(): void {\r\n\t\tsuper.hostConnected();\r\n\t\tif (this.#context) {\r\n\t\t\tthis.#context.addValidator(this);\r\n\t\t}\r\n\t}\r\n\toverride hostDisconnected(): void {\r\n\t\tsuper.hostDisconnected();\r\n\t\tif (this.#context) {\r\n\t\t\tthis.#context.removeValidator(this);\r\n\t\t\tthis.#context = undefined;\r\n\t\t}\r\n\t}\r\n\r\n\toverride destroy(): void {\r\n\t\t// TODO: make sure we destroy things properly:\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n","import type { UmbValidationMessage } from '../context/validation-messages.manager.js';\r\nimport { UMB_VALIDATION_CONTEXT } from '../context/validation.context-token.js';\r\nimport type { UmbFormControlMixinInterface } from '../mixins/form-control.mixin.js';\r\nimport { defaultMemoization, simpleHashCode } from '@umbraco-cms/backoffice/observable-api';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nconst observeSymbol = Symbol();\r\n\r\n/**\r\n * Binds server validation to a form control.\r\n * This controller will add a custom error to the form control if the validation context has any messages for the specified data path.\r\n */\r\nexport class UmbBindServerValidationToFormControl extends UmbControllerBase {\r\n\t#context?: typeof UMB_VALIDATION_CONTEXT.TYPE;\r\n\r\n\t#control: UmbFormControlMixinInterface;\r\n\r\n\t#controlValidator?: ReturnType['addValidator']>;\r\n\t#messages: Array = [];\r\n\t#isValid = false;\r\n\r\n\t#value?: unknown;\r\n\tset value(value: unknown) {\r\n\t\tif (this.#isValid) {\r\n\t\t\t// If valid lets just parse it on [NL]\r\n\t\t\tthis.#value = value;\r\n\t\t} else {\r\n\t\t\t// If not valid lets see if we should remove server validation [NL]\r\n\t\t\tif (!defaultMemoization(this.#value, value)) {\r\n\t\t\t\tthis.#value = value;\r\n\t\t\t\t// Only remove server validations from validation context [NL]\r\n\t\t\t\tconst toRemove = this.#messages.filter((x) => x.type === 'server').map((msg) => msg.key);\r\n\t\t\t\tthis.#context?.messages.removeMessageByKeys(toRemove);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconstructor(host: UmbControllerHost, formControl: UmbFormControlMixinInterface, dataPath: string) {\r\n\t\tsuper(host, 'umbFormControlValidation_' + simpleHashCode(dataPath));\r\n\t\tthis.#control = formControl;\r\n\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (context) => {\r\n\t\t\tthis.#context = context;\r\n\r\n\t\t\tthis.observe(\r\n\t\t\t\tcontext.messages.messagesOfTypeAndPath('server', dataPath),\r\n\t\t\t\t(messages) => {\r\n\t\t\t\t\tthis.#messages = messages;\r\n\t\t\t\t\tthis.#isValid = messages.length === 0;\r\n\t\t\t\t\tif (!this.#isValid) {\r\n\t\t\t\t\t\tthis.#setup();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.#demolish();\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tobserveSymbol,\r\n\t\t\t);\r\n\t\t});\r\n\t}\r\n\r\n\t#setup() {\r\n\t\tif (!this.#controlValidator) {\r\n\t\t\tthis.#controlValidator = this.#control.addValidator(\r\n\t\t\t\t'customError',\r\n\t\t\t\t() => this.#messages.map((x) => x.body).join(', '),\r\n\t\t\t\t() => !this.#isValid,\r\n\t\t\t);\r\n\t\t\t//this.#control.addEventListener('change', this.#onControlChange);\r\n\t\t\t// Legacy event, used by some controls:\r\n\t\t\t//this.#control.addEventListener('property-value-change', this.#onControlChange);\r\n\t\t}\r\n\t\tthis.#control.checkValidity();\r\n\t}\r\n\r\n\t#demolish() {\r\n\t\tif (!this.#control || !this.#controlValidator) return;\r\n\r\n\t\tthis.#control.removeValidator(this.#controlValidator);\r\n\t\t//this.#control.removeEventListener('change', this.#onControlChange);\r\n\t\t// Legacy event, used by some controls:\r\n\t\t//this.#control.removeEventListener('property-value-change', this.#onControlChange);\r\n\t\tthis.#controlValidator = undefined;\r\n\t\tthis.#control.checkValidity();\r\n\t}\r\n\r\n\tvalidate(): Promise {\r\n\t\t//this.#isValid = this.#control.checkValidity();\r\n\t\treturn this.#isValid ? Promise.resolve() : Promise.reject();\r\n\t}\r\n\r\n\t/**\r\n\t * Resets the validation state of this validator.\r\n\t */\r\n\treset(): void {\r\n\t\tthis.#isValid = false;\r\n\t\tthis.#control.pristine = true; // Make sure the control goes back into not-validation-mode/'untouched'/pristine state.\r\n\t}\r\n\r\n\t/*getMessages(): string[] {\r\n\t\treturn [this.#control.validationMessage];\r\n\t}*/\r\n\r\n\tfocusFirstInvalidElement(): void {\r\n\t\tthis.#control.focusFirstInvalidElement();\r\n\t}\r\n\r\n\toverride destroy(): void {\r\n\t\tthis.#context = undefined;\r\n\t\t// Reset control setup.\r\n\t\tthis.#demolish();\r\n\t\tthis.#control = undefined as any;\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n","import type { UmbValidator } from '../interfaces/index.js';\r\nimport { UMB_VALIDATION_CONTEXT } from '../context/validation.context-token.js';\r\nimport type { UmbFormControlMixinInterface } from '../mixins/form-control.mixin.js';\r\nimport { UmbValidationInvalidEvent } from '../events/validation-invalid.event.js';\r\nimport { UmbValidationValidEvent } from '../events/validation-valid.event.js';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\n/**\r\n * Bind a Form Controls validation state to the validation context.\r\n * This validator will validate the form control and add messages to the validation context if the form control is invalid.\r\n */\r\nexport class UmbFormControlValidator extends UmbControllerBase implements UmbValidator {\r\n\t// The path to the data that this validator is validating.\r\n\treadonly #dataPath?: string;\r\n\r\n\t#context?: typeof UMB_VALIDATION_CONTEXT.TYPE;\r\n\r\n\t#control: UmbFormControlMixinInterface;\r\n\r\n\t#isValid = true;\r\n\r\n\tconstructor(host: UmbControllerHost, formControl: UmbFormControlMixinInterface, dataPath?: string) {\r\n\t\tsuper(host);\r\n\t\tthis.#dataPath = dataPath;\r\n\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (context) => {\r\n\t\t\tif (this.#context) {\r\n\t\t\t\tthis.#context.removeValidator(this);\r\n\t\t\t}\r\n\t\t\tthis.#context = context;\r\n\t\t\tcontext.addValidator(this);\r\n\t\t\t// If we have a message already, then un-pristine the control:\r\n\t\t\tif (dataPath && context.messages.getHasMessagesOfPathAndDescendant(dataPath)) {\r\n\t\t\t\tformControl.pristine = false;\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis.#control = formControl;\r\n\t\tthis.#control.addEventListener(UmbValidationInvalidEvent.TYPE, this.#setInvalid);\r\n\t\tthis.#control.addEventListener(UmbValidationValidEvent.TYPE, this.#setValid);\r\n\t}\r\n\r\n\tget isValid(): boolean {\r\n\t\treturn this.#isValid;\r\n\t}\r\n\t#setIsValid(newVal: boolean) {\r\n\t\tif (this.#isValid === newVal) return;\r\n\t\tthis.#isValid = newVal;\r\n\r\n\t\tif (this.#dataPath) {\r\n\t\t\tif (newVal) {\r\n\t\t\t\tthis.#context?.messages.removeMessagesByTypeAndPath('client', this.#dataPath);\r\n\t\t\t} else {\r\n\t\t\t\tthis.#context?.messages.addMessages('client', this.#dataPath, [this.#control.validationMessage]);\r\n\t\t\t}\r\n\t\t}\r\n\t\t//this.dispatchEvent(new CustomEvent('change')); // To let the ValidationContext know that the validation state has changed.\r\n\t}\r\n\r\n\t#setInvalid = this.#setIsValid.bind(this, false);\r\n\t#setValid = this.#setIsValid.bind(this, true);\r\n\r\n\tvalidate(): Promise {\r\n\t\tthis.#isValid = this.#control.checkValidity();\r\n\t\treturn this.#isValid ? Promise.resolve() : Promise.reject();\r\n\t}\r\n\r\n\t/**\r\n\t * Resets the validation state of this validator.\r\n\t */\r\n\treset(): void {\r\n\t\tthis.#isValid = false;\r\n\t\tthis.#control.pristine = true; // Make sure the control goes back into not-validation-mode/'untouched'/pristine state.\r\n\t}\r\n\r\n\t/*getMessages(): string[] {\r\n\t\treturn [this.#control.validationMessage];\r\n\t}*/\r\n\r\n\tfocusFirstInvalidElement(): void {\r\n\t\tthis.#control.focusFirstInvalidElement();\r\n\t}\r\n\r\n\toverride hostConnected(): void {\r\n\t\tsuper.hostConnected();\r\n\t\tif (this.#context) {\r\n\t\t\tthis.#context.addValidator(this);\r\n\t\t}\r\n\t}\r\n\toverride hostDisconnected(): void {\r\n\t\tsuper.hostDisconnected();\r\n\t\tif (this.#context) {\r\n\t\t\tthis.#context.removeValidator(this);\r\n\t\t\t// Remove any messages that this validator has added:\r\n\t\t\tif (this.#dataPath) {\r\n\t\t\t\t//this.#context.messages.removeMessagesByTypeAndPath('client', this.#dataPath);\r\n\t\t\t}\r\n\t\t\tthis.#context = undefined;\r\n\t\t}\r\n\t}\r\n\r\n\toverride destroy(): void {\r\n\t\tif (this.#control) {\r\n\t\t\tthis.#control.removeEventListener(UmbValidationInvalidEvent.TYPE, this.#setInvalid);\r\n\t\t\tthis.#control.removeEventListener(UmbValidationValidEvent.TYPE, this.#setValid);\r\n\t\t\tthis.#control = undefined as any;\r\n\t\t}\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n","import { UMB_VALIDATION_CONTEXT } from '../context/validation.context-token.js';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nconst ObserveSymbol = Symbol();\r\n\r\nexport class UmbObserveValidationStateController extends UmbControllerBase {\r\n\tconstructor(\r\n\t\thost: UmbControllerHost,\r\n\t\tdataPath: string | undefined,\r\n\t\tcallback: (messages: boolean) => void,\r\n\t\tcontrollerAlias?: string,\r\n\t) {\r\n\t\tsuper(host, controllerAlias ?? 'observeValidationState_' + dataPath);\r\n\t\tif (dataPath) {\r\n\t\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (context) => {\r\n\t\t\t\tthis.observe(context.messages.hasMessagesOfPathAndDescendant(dataPath), callback, ObserveSymbol);\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n}\r\n","import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport { AsyncDirective, directive, nothing, type ElementPart } from '@umbraco-cms/backoffice/external/lit';\r\nimport type { UmbFormControlMixinInterface } from '@umbraco-cms/backoffice/validation';\r\nimport { UmbBindServerValidationToFormControl, UmbFormControlValidator } from '@umbraco-cms/backoffice/validation';\r\n\r\n/**\r\n * The `bind to validation` directive connects the Form Control Element to closets Validation Context.\r\n */\r\nclass UmbBindToValidationDirective extends AsyncDirective {\r\n\t#host?: UmbControllerHost;\r\n\t#dataPath?: string;\r\n\t#el?: UmbFormControlMixinInterface;\r\n\t#validator?: UmbFormControlValidator;\r\n\t#msgBinder?: UmbBindServerValidationToFormControl;\r\n\r\n\t// For Directives their arguments have to be defined on the Render method, despite them, not being used by the render method. In this case they are used by the update method.\r\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n\toverride render(host: UmbControllerHost, dataPath?: string, value?: unknown) {\r\n\t\treturn nothing;\r\n\t}\r\n\r\n\toverride update(part: ElementPart, args: Parameters) {\r\n\t\tif (!part.element) return nothing;\r\n\t\tif (this.#el !== part.element || this.#host !== args[0] || this.#dataPath !== args[1]) {\r\n\t\t\tthis.#host = args[0];\r\n\t\t\tthis.#dataPath = args[1];\r\n\t\t\tthis.#el = part.element as UmbFormControlMixinInterface;\r\n\r\n\t\t\tif (!this.#msgBinder && this.#dataPath) {\r\n\t\t\t\tthis.#msgBinder = new UmbBindServerValidationToFormControl(this.#host, this.#el as any, this.#dataPath);\r\n\t\t\t}\r\n\r\n\t\t\tthis.#validator = new UmbFormControlValidator(this.#host, this.#el, this.#dataPath);\r\n\t\t}\r\n\r\n\t\t// If we have a msgBinder, then lets update the value no matter the other conditions.\r\n\t\tif (this.#msgBinder) {\r\n\t\t\tthis.#msgBinder.value = args[2];\r\n\t\t}\r\n\r\n\t\treturn nothing;\r\n\t}\r\n\r\n\toverride disconnected() {\r\n\t\tif (this.#validator) {\r\n\t\t\tthis.#validator?.destroy();\r\n\t\t\tthis.#validator = undefined;\r\n\t\t}\r\n\t\tif (this.#msgBinder) {\r\n\t\t\tthis.#msgBinder.destroy();\r\n\t\t\tthis.#msgBinder = undefined;\r\n\t\t}\r\n\t\tthis.#el = undefined;\r\n\t}\r\n\r\n\t/*override reconnected() {\r\n\t}*/\r\n}\r\n\r\n/**\r\n * @description\r\n * A Lit directive, which binds the validation state of the element to the Validation Context.\r\n *\r\n * The minimal binding can be established by just providing a host element:\r\n * @example:\r\n * ```js\r\n * html``;\r\n * ```\r\n * But can be extended with a dataPath, which is the path to the data holding the value. (if no server validation in this context, then this can be fictive and is then just used internal for remembering the validation state despite the element begin removed from the DOM.)\r\n * @example:\r\n * ```js\r\n * html``;\r\n * ```\r\n *\r\n * Additional the value can be provided, which is then used to remove a server validation state, if the value is changed.\r\n * @example:\r\n * ```js\r\n * html``;\r\n * ```\r\n */\r\nexport const umbBindToValidation = directive(UmbBindToValidationDirective);\r\n\r\n//export type { UmbFocusDirective };\r\n","import { UmbValidationInvalidEvent } from '../events/validation-invalid.event.js';\r\nimport { UmbValidationValidEvent } from '../events/validation-valid.event.js';\r\nimport { property, type LitElement } from '@umbraco-cms/backoffice/external/lit';\r\nimport type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-api';\r\n\r\ntype UmbNativeFormControlElement = Pick<\r\n\tHTMLObjectElement,\r\n\t'validity' | 'checkValidity' | 'validationMessage' | 'setCustomValidity'\r\n> &\r\n\tHTMLElement; // Eventually use a specific interface or list multiple options like appending these types: ... | HTMLTextAreaElement | HTMLSelectElement\r\n\r\n/* FlagTypes type options originate from:\r\n * https://developer.mozilla.org/en-US/docs/Web/API/ValidityState\r\n * */\r\ntype FlagTypes =\r\n\t| 'customError'\r\n\t| 'badInput'\r\n\t| 'patternMismatch'\r\n\t| 'rangeOverflow'\r\n\t| 'rangeUnderflow'\r\n\t| 'stepMismatch'\r\n\t| 'tooLong'\r\n\t| 'tooShort'\r\n\t| 'typeMismatch'\r\n\t| 'valueMissing'\r\n\t| 'valid';\r\n\r\nconst WeightedErrorFlagTypes = [\r\n\t'customError',\r\n\t'valueMissing',\r\n\t'badInput',\r\n\t'typeMismatch',\r\n\t'patternMismatch',\r\n\t'rangeOverflow',\r\n\t'rangeUnderflow',\r\n\t'stepMismatch',\r\n\t'tooLong',\r\n\t'tooShort',\r\n];\r\n\r\n// Acceptable as an internal interface/type, BUT if exposed externally this should be turned into a public interface in a separate file.\r\nexport interface UmbFormControlValidatorConfig {\r\n\tflagKey: FlagTypes;\r\n\tgetMessageMethod: () => string;\r\n\tcheckMethod: () => boolean;\r\n\tweight: number;\r\n}\r\n\r\nexport interface UmbFormControlMixinInterface extends HTMLElement {\r\n\taddValidator: (\r\n\t\tflagKey: FlagTypes,\r\n\t\tgetMessageMethod: () => string,\r\n\t\tcheckMethod: () => boolean,\r\n\t) => UmbFormControlValidatorConfig;\r\n\tremoveValidator: (obj: UmbFormControlValidatorConfig) => void;\r\n\t//static formAssociated: boolean;\r\n\t//protected getFormElement(): HTMLElement | undefined | null; // allows for null as it makes it simpler to just implement a querySelector as that might return null. [NL]\r\n\tfocusFirstInvalidElement(): void;\r\n\tget value(): ValueType;\r\n\tset value(newValue: ValueType);\r\n\tformResetCallback(): void;\r\n\tcheckValidity(): boolean;\r\n\tget validationMessage(): string;\r\n\tget validity(): ValidityState;\r\n\tsetCustomValidity(error?: string): void;\r\n\tsubmit(): void;\r\n\tpristine: boolean;\r\n}\r\n\r\nexport declare abstract class UmbFormControlMixinElement\r\n\textends LitElement\r\n\timplements UmbFormControlMixinInterface\r\n{\r\n\tprotected _internals: ElementInternals;\r\n\tprotected _runValidators(): void;\r\n\taddValidator: (\r\n\t\tflagKey: FlagTypes,\r\n\t\tgetMessageMethod: () => string,\r\n\t\tcheckMethod: () => boolean,\r\n\t) => UmbFormControlValidatorConfig;\r\n\tremoveValidator: (obj: UmbFormControlValidatorConfig) => void;\r\n\tprotected addFormControlElement(element: UmbNativeFormControlElement): void;\r\n\tprotected removeFormControlElement(element: UmbNativeFormControlElement): void;\r\n\r\n\t//static formAssociated: boolean;\r\n\tprotected getFormElement(): HTMLElement | undefined | null;\r\n\tfocusFirstInvalidElement(): void;\r\n\tget value(): ValueType;\r\n\tset value(newValue: ValueType);\r\n\tformResetCallback(): void;\r\n\tcheckValidity(): boolean;\r\n\tget validationMessage(): string;\r\n\tget validity(): ValidityState;\r\n\tsetCustomValidity(error?: string): void;\r\n\tsubmit(): void;\r\n\tpristine: boolean;\r\n}\r\n\r\n/**\r\n * @mixin\r\n * The mixin allows a custom element to participate in HTML forms.\r\n * @param {object} superClass - superclass to be extended.\r\n * @param {object} defaultValue - Default value for the form control.\r\n * @returns {Function} - The mixin class.\r\n */\r\nexport function UmbFormControlMixin<\r\n\tValueType = FormData | FormDataEntryValue,\r\n\tT extends HTMLElementConstructor = HTMLElementConstructor,\r\n\tDefaultValueType = undefined,\r\n>(superClass: T, defaultValue?: DefaultValueType) {\r\n\tabstract class UmbFormControlMixinClass extends superClass {\r\n\t\t/**\r\n\t\t * This is a static class field indicating that the element is can be used inside a native form and participate in its events.\r\n\t\t * It may require a polyfill, check support here https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals.\r\n\t\t * Read more about form controls here https://web.dev/more-capable-form-controls/\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tstatic readonly formAssociated = true;\r\n\r\n\t\t/**\r\n\t\t * Value of this form control.\r\n\t\t * @type {string}\r\n\t\t * @attr value\r\n\t\t * @default\r\n\t\t */\r\n\t\t@property({ reflect: false }) // Do not 'reflect' as the attribute value is used as fallback. [NL]\r\n\t\tget value(): ValueType | DefaultValueType {\r\n\t\t\treturn this.#value;\r\n\t\t}\r\n\t\tset value(newValue: ValueType | DefaultValueType) {\r\n\t\t\tthis.#value = newValue;\r\n\t\t\tthis._runValidators();\r\n\t\t}\r\n\r\n\t\t// Validation\r\n\t\t//private _validityState = new UmbValidityState();\r\n\t\t#validity: any = {};\r\n\r\n\t\t/**\r\n\t\t * Determines wether the form control has been touched or interacted with, this determines wether the validation-status of this form control should be made visible.\r\n\t\t * @type {boolean}\r\n\t\t * @attr\r\n\t\t * @default\r\n\t\t */\r\n\t\t@property({ type: Boolean, reflect: true })\r\n\t\tpublic set pristine(value: boolean) {\r\n\t\t\tif (this._pristine !== value) {\r\n\t\t\t\tthis._pristine = value;\r\n\t\t\t\tthis._runValidators();\r\n\t\t\t}\r\n\t\t}\r\n\t\tpublic get pristine(): boolean {\r\n\t\t\treturn this._pristine;\r\n\t\t}\r\n\t\tprivate _pristine: boolean = true;\r\n\r\n\t\t#value: ValueType | DefaultValueType = defaultValue as unknown as DefaultValueType;\r\n\t\tprotected _internals: ElementInternals;\r\n\t\t#form: HTMLFormElement | null = null;\r\n\t\t#validators: UmbFormControlValidatorConfig[] = [];\r\n\t\t#formCtrlElements: UmbNativeFormControlElement[] = [];\r\n\r\n\t\tconstructor(...args: any[]) {\r\n\t\t\tsuper(...args);\r\n\t\t\tthis._internals = this.attachInternals();\r\n\r\n\t\t\tthis.addEventListener('blur', () => {\r\n\t\t\t\t/*if (e.composedPath().some((x) => x === this)) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}*/\r\n\t\t\t\tthis.pristine = false;\r\n\t\t\t\tthis.checkValidity();\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Get internal form element.\r\n\t\t * This has to be implemented to provide a FormControl Element of choice for the given context. The element is used as anchor for validation-messages.\r\n\t\t * @function getFormElement\r\n\t\t * @returns {HTMLElement | undefined | null} - Returns the form element or undefined if not found.\r\n\t\t */\r\n\t\tprotected getFormElement(): HTMLElement | undefined | null {\r\n\t\t\treturn this.#formCtrlElements.find((el) => el.validity.valid === false);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Focus first element that is invalid.\r\n\t\t * @function focusFirstInvalidElement\r\n\t\t * @returns {HTMLElement | undefined} - Returns the first invalid element or undefined if no invalid elements are found.\r\n\t\t */\r\n\t\tfocusFirstInvalidElement() {\r\n\t\t\tconst firstInvalid = this.#formCtrlElements.find((el) => el.validity.valid === false);\r\n\t\t\tif (firstInvalid) {\r\n\t\t\t\tif ('focusFirstInvalidElement' in firstInvalid) {\r\n\t\t\t\t\t(firstInvalid as any).focusFirstInvalidElement();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tfirstInvalid.focus();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthis.focus();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toverride disconnectedCallback(): void {\r\n\t\t\tsuper.disconnectedCallback();\r\n\t\t\tthis.#removeFormListeners();\r\n\t\t}\r\n\t\t#removeFormListeners() {\r\n\t\t\tif (this.#form) {\r\n\t\t\t\tthis.#form.removeEventListener('submit', this.#onFormSubmit);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Add validation, to validate this Form Control.\r\n\t\t * See https://developer.mozilla.org/en-US/docs/Web/API/ValidityState for available Validator FlagTypes.\r\n\t\t * @example\r\n\t\t * this.addValidator(\r\n\t\t * 'tooLong',\r\n\t\t * () => 'This input contains too many characters',\r\n\t\t * () => this._value.length > 10\r\n\t\t * );\r\n\t\t * @function addValidator\r\n\t\t * @param {FlagTypes} flagKey the type of validation.\r\n\t\t * @param {method} getMessageMethod method to retrieve relevant message. Is executed every time the validator is re-executed.\r\n\t\t * @param {method} checkMethod method to determine if this validator should invalidate this form control. Return true if this should prevent submission.\r\n\t\t * @returns {UmbFormControlValidatorConfig} - The added validator configuration.\r\n\t\t */\r\n\t\taddValidator(\r\n\t\t\tflagKey: FlagTypes,\r\n\t\t\tgetMessageMethod: () => string,\r\n\t\t\tcheckMethod: () => boolean,\r\n\t\t): UmbFormControlValidatorConfig {\r\n\t\t\tconst validator = {\r\n\t\t\t\tflagKey: flagKey,\r\n\t\t\t\tgetMessageMethod: getMessageMethod,\r\n\t\t\t\tcheckMethod: checkMethod,\r\n\t\t\t\tweight: WeightedErrorFlagTypes.indexOf(flagKey),\r\n\t\t\t} satisfies UmbFormControlValidatorConfig;\r\n\t\t\tthis.#validators.push(validator);\r\n\t\t\t// Sort validators based on the WeightedErrorFlagTypes order. [NL]\r\n\t\t\tthis.#validators.sort((a, b) => (a.weight > b.weight ? 1 : b.weight > a.weight ? -1 : 0));\r\n\t\t\treturn validator;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Remove validation from this form control.\r\n\t\t * @function removeValidator\r\n\t\t * @param {UmbFormControlValidatorConfig} validator - The specific validation configuration to remove.\r\n\t\t */\r\n\t\tremoveValidator(validator: UmbFormControlValidatorConfig) {\r\n\t\t\tconst index = this.#validators.indexOf(validator);\r\n\t\t\tif (index !== -1) {\r\n\t\t\t\tthis.#validators.splice(index, 1);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t#runValidatorsCallback = () => this._runValidators;\r\n\r\n\t\t/**\r\n\t\t * @function addFormControlElement\r\n\t\t * @description Important notice if adding a native form control then ensure that its value and thereby validity is updated when value is changed from the outside.\r\n\t\t * @param {UmbNativeFormControlElement} element - element to validate and include as part of this form control association.\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tprotected addFormControlElement(element: UmbNativeFormControlElement) {\r\n\t\t\tthis.#formCtrlElements.push(element);\r\n\t\t\telement.addEventListener(UmbValidationInvalidEvent.TYPE, this.#runValidatorsCallback);\r\n\t\t\telement.addEventListener(UmbValidationValidEvent.TYPE, this.#runValidatorsCallback);\r\n\t\t\t// If we are in validationMode/'touched'/not-pristine then we need to validate this newly added control. [NL]\r\n\t\t\tif (this._pristine === false) {\r\n\t\t\t\telement.checkValidity();\r\n\t\t\t\t// I think we could just execute validators for the new control, but now lets just run al of it again. [NL]\r\n\t\t\t\tthis._runValidators();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * @function removeFormControlElement\r\n\t\t * @param {UmbNativeFormControlElement} element - element to remove as part of this form controls associated controls.\r\n\t\t * @returns {void}\r\n\t\t */\r\n\t\tprotected removeFormControlElement(element: UmbNativeFormControlElement) {\r\n\t\t\tconst index = this.#formCtrlElements.indexOf(element);\r\n\t\t\tif (index !== -1) {\r\n\t\t\t\tthis.#formCtrlElements.splice(index, 1);\r\n\t\t\t\telement.removeEventListener(UmbValidationInvalidEvent.TYPE, this.#runValidatorsCallback);\r\n\t\t\t\telement.removeEventListener(UmbValidationValidEvent.TYPE, this.#runValidatorsCallback);\r\n\t\t\t\tif (this._pristine === false) {\r\n\t\t\t\t\tthis._runValidators();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tprivate _customValidityObject?: UmbFormControlValidatorConfig;\r\n\r\n\t\t/**\r\n\t\t * @function setCustomValidity\r\n\t\t * @description Set custom validity state, set to empty string to remove the custom message.\r\n\t\t * @param {string} message - The message to be shown\r\n\t\t * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity|HTMLObjectElement:setCustomValidity}\r\n\t\t */\r\n\t\tprotected setCustomValidity(message: string | null) {\r\n\t\t\tif (this._customValidityObject) {\r\n\t\t\t\tthis.removeValidator(this._customValidityObject);\r\n\t\t\t}\r\n\r\n\t\t\tif (message != null && message !== '') {\r\n\t\t\t\tthis._customValidityObject = this.addValidator(\r\n\t\t\t\t\t'customError',\r\n\t\t\t\t\t(): string => message,\r\n\t\t\t\t\t() => true,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tthis._runValidators();\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * @function _runValidators\r\n\t\t * @description Run all validators and set the validityState of this form control.\r\n\t\t * Run this method when you want to re-run all validators.\r\n\t\t * This can be relevant if you have a validators that is using values that is not triggering the Lit Updated Callback.\r\n\t\t * Such are mainly properties that are not declared as a Lit state and or Lit property.\r\n\t\t */\r\n\t\tprotected _runValidators() {\r\n\t\t\tthis.#validity = {};\r\n\t\t\t//const messages: Set = new Set();\r\n\t\t\tlet message: string | undefined = undefined;\r\n\t\t\tlet innerFormControlEl: UmbNativeFormControlElement | undefined = undefined;\r\n\r\n\t\t\t// Loop through custom validators, currently its intentional to have them overwritten native validity. but might need to be reconsidered (This current way enables to overwrite with custom messages) [NL]\r\n\t\t\tthis.#validators.some((validator) => {\r\n\t\t\t\tif (validator.checkMethod()) {\r\n\t\t\t\t\tthis.#validity[validator.flagKey] = true;\r\n\t\t\t\t\t//messages.add(validator.getMessageMethod());\r\n\t\t\t\t\tmessage = validator.getMessageMethod();\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t\treturn false;\r\n\t\t\t});\r\n\r\n\t\t\tif (!message) {\r\n\t\t\t\t// Loop through inner native form controls to adapt their validityState. [NL]\r\n\t\t\t\tthis.#formCtrlElements.some((formCtrlEl) => {\r\n\t\t\t\t\tlet key: keyof ValidityState;\r\n\t\t\t\t\tfor (key in formCtrlEl.validity) {\r\n\t\t\t\t\t\tif (key !== 'valid' && formCtrlEl.validity[key]) {\r\n\t\t\t\t\t\t\tthis.#validity[key] = true;\r\n\t\t\t\t\t\t\t//messages.add(formCtrlEl.validationMessage);\r\n\t\t\t\t\t\t\tmessage = formCtrlEl.validationMessage;\r\n\t\t\t\t\t\t\tinnerFormControlEl ??= formCtrlEl;\r\n\t\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tconst hasError = Object.values(this.#validity).includes(true);\r\n\r\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState#valid\r\n\t\t\tthis.#validity.valid = !hasError;\r\n\r\n\t\t\t// Transfer the new validityState to the ElementInternals. [NL]\r\n\t\t\tthis._internals.setValidity(\r\n\t\t\t\tthis.#validity,\r\n\t\t\t\t// Turn messages into an array and join them with a comma. [NL]:\r\n\t\t\t\t//[...messages].join(', '),\r\n\t\t\t\tmessage,\r\n\t\t\t\tinnerFormControlEl ?? this.getFormElement() ?? undefined,\r\n\t\t\t);\r\n\r\n\t\t\tthis.#dispatchValidationState();\r\n\t\t}\r\n\r\n\t\t#dispatchValidationState() {\r\n\t\t\t// Do not fire validation events unless we are not pristine/'untouched'/not-in-validation-mode. [NL]\r\n\t\t\tif (this._pristine === true) return;\r\n\t\t\tif (this.#validity.valid) {\r\n\t\t\t\tthis.dispatchEvent(new UmbValidationValidEvent());\r\n\t\t\t} else {\r\n\t\t\t\tthis.dispatchEvent(new UmbValidationInvalidEvent());\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toverride updated(changedProperties: Map) {\r\n\t\t\tsuper.updated(changedProperties);\r\n\t\t\tthis._runValidators();\r\n\t\t}\r\n\r\n\t\t#onFormSubmit = () => {\r\n\t\t\tthis.pristine = false;\r\n\t\t};\r\n\r\n\t\tpublic formAssociatedCallback() {\r\n\t\t\tthis.#removeFormListeners();\r\n\t\t\tthis.#form = this._internals.form;\r\n\t\t\tif (this.#form) {\r\n\t\t\t\t// This relies on the form begin a 'uui-form': [NL]\r\n\t\t\t\tif (this.#form.hasAttribute('submit-invalid')) {\r\n\t\t\t\t\tthis.pristine = false;\r\n\t\t\t\t}\r\n\t\t\t\tthis.#form.addEventListener('submit', this.#onFormSubmit);\r\n\t\t\t}\r\n\t\t}\r\n\t\tpublic formResetCallback() {\r\n\t\t\tthis.pristine = true;\r\n\t\t\tthis.value = this.getInitialValue() ?? this.getDefaultValue();\r\n\t\t}\r\n\r\n\t\tprotected getDefaultValue(): DefaultValueType {\r\n\t\t\treturn defaultValue as DefaultValueType;\r\n\t\t}\r\n\t\tprotected getInitialValue(): ValueType | DefaultValueType {\r\n\t\t\treturn this.getAttribute('value') as ValueType | DefaultValueType;\r\n\t\t}\r\n\r\n\t\tpublic checkValidity() {\r\n\t\t\tthis.pristine = false;\r\n\t\t\tthis._runValidators();\r\n\r\n\t\t\tfor (const key in this.#formCtrlElements) {\r\n\t\t\t\tif (this.#formCtrlElements[key].checkValidity() === false) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn this._internals?.checkValidity();\r\n\t\t}\r\n\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity\r\n\t\tpublic get validity(): ValidityState {\r\n\t\t\treturn this.#validity;\r\n\t\t}\r\n\r\n\t\tget validationMessage() {\r\n\t\t\treturn this._internals?.validationMessage;\r\n\t\t}\r\n\t}\r\n\treturn UmbFormControlMixinClass as unknown as HTMLElementConstructor<\r\n\t\tUmbFormControlMixinElement\r\n\t> &\r\n\t\tT;\r\n}\r\n","import { UMB_VALIDATION_CONTEXT } from '../index.js';\r\nimport type { UmbValidationMessageTranslator } from './validation-message-path-translator.interface.js';\r\nimport type { UmbControllerAlias, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\n\r\nexport abstract class UmbValidationPathTranslatorBase\r\n\textends UmbControllerBase\r\n\timplements UmbValidationMessageTranslator\r\n{\r\n\t//\r\n\tprotected _context?: typeof UMB_VALIDATION_CONTEXT.TYPE;\r\n\r\n\tconstructor(host: UmbControllerHost, ctrlAlias?: UmbControllerAlias) {\r\n\t\tsuper(host, ctrlAlias);\r\n\r\n\t\tthis.consumeContext(UMB_VALIDATION_CONTEXT, (context) => {\r\n\t\t\tthis._context?.removeTranslator(this);\r\n\t\t\tthis._context = context;\r\n\t\t\tcontext.addTranslator(this);\r\n\t\t});\r\n\t}\r\n\r\n\toverride hostDisconnected(): void {\r\n\t\tthis._context?.removeTranslator(this);\r\n\t\tthis._context = undefined;\r\n\t\tsuper.hostDisconnected();\r\n\t}\r\n\r\n\tabstract translate(path: string): ReturnType;\r\n}\r\n","import { UmbValidationPathTranslatorBase } from './validation-path-translator-base.controller.js';\r\nimport type { UmbControllerAlias, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nexport abstract class UmbAbstractArrayValidationPathTranslator extends UmbValidationPathTranslatorBase {\r\n\t#initialPathToMatch: string;\r\n\t#queryMethod: (data: unknown) => string;\r\n\r\n\tconstructor(\r\n\t\thost: UmbControllerHost,\r\n\t\tinitialPathToMatch: string,\r\n\t\tqueryMethod: (data: any) => string,\r\n\t\tctrlAlias?: UmbControllerAlias,\r\n\t) {\r\n\t\tsuper(host, ctrlAlias);\r\n\r\n\t\tthis.#initialPathToMatch = initialPathToMatch;\r\n\t\tthis.#queryMethod = queryMethod;\r\n\t}\r\n\ttranslate(path: string) {\r\n\t\tif (!this._context) return;\r\n\t\tif (path.indexOf(this.#initialPathToMatch) !== 0) {\r\n\t\t\t// We do not handle this path.\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tconst pathEnd = path.indexOf(']');\r\n\t\tif (pathEnd === -1) {\r\n\t\t\t// We do not handle this path.\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// retrieve the number from the message values index: [NL]\r\n\t\tconst index = parseInt(path.substring(this.#initialPathToMatch.length, pathEnd));\r\n\r\n\t\tif (isNaN(index)) {\r\n\t\t\t// index is not a number, this means its not a path we want to translate. [NL]\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Get the data from the validation request, the context holds that for us: [NL]\r\n\t\tconst data = this.getDataFromIndex(index);\r\n\r\n\t\tif (!data) return false;\r\n\t\t// replace the values[ number ] with JSON-Path filter values[@.(...)], continues by the rest of the path:\r\n\t\treturn this.#initialPathToMatch + this.#queryMethod(data) + path.substring(path.indexOf(']'));\r\n\t}\r\n\r\n\tabstract getDataFromIndex(index: number): unknown | undefined;\r\n}\r\n","import { UmbDataPathPropertyValueQuery } from '../utils/data-path-property-value-query.function.js';\r\nimport { UmbAbstractArrayValidationPathTranslator } from './abstract-array-path-translator.controller.js';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nexport class UmbVariantValuesValidationPathTranslator extends UmbAbstractArrayValidationPathTranslator {\r\n\tconstructor(host: UmbControllerHost) {\r\n\t\tsuper(host, '$.values[', UmbDataPathPropertyValueQuery);\r\n\t}\r\n\r\n\tgetDataFromIndex(index: number) {\r\n\t\tif (!this._context) return;\r\n\t\tconst data = this._context.getTranslationData();\r\n\t\treturn data.values[index];\r\n\t}\r\n}\r\n","import { UmbDataPathVariantQuery } from '../utils/data-path-variant-query.function.js';\r\nimport { UmbAbstractArrayValidationPathTranslator } from './abstract-array-path-translator.controller.js';\r\nimport type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nexport class UmbVariantsValidationPathTranslator extends UmbAbstractArrayValidationPathTranslator {\r\n\tconstructor(host: UmbControllerHost) {\r\n\t\tsuper(host, '$.variants[', UmbDataPathVariantQuery);\r\n\t}\r\n\r\n\tgetDataFromIndex(index: number) {\r\n\t\tif (!this._context) return;\r\n\t\tconst data = this._context.getTranslationData();\r\n\t\treturn data.variants[index];\r\n\t}\r\n}\r\n"],"names":["UmbValidationEvent","type","UmbValidationValidEvent","UmbValidationInvalidEvent","_onControlInvalid","_onControlValid","UmbFormValidationMessageElement","UmbLitElement","__privateAdd","e","ctrl","value","element","newScope","oldScope","__privateGet","html","repeat","item","unsafeHTML","css","__decorateClass","property","customElement","UMB_VALIDATION_EMPTY_LOCALIZATION_KEY","GetValueByJsonPath","data","path","strippedPath","GetNextPropertyValueFromPath","match","key","rest","lookupEnd","entryPointer","jsFilter","JsFilterFromJsonPathFilter","index","indexAsNumber","filter","part","equal","UMB_VALIDATION_CONTEXT","UmbContextToken","MatchPathOrDescendantPath","source","UmbValidationMessagesManager","#messages","UmbArrayState","x","#translators","logName","msgs","body","UmbId","#translatePath","bodies","existingMessages","newBodies","message","keys","translator","newPath","msg","ReplaceStartOfString","startFrom","startTo","UmbValidationController","UmbControllerBase","host","#translationData","UmbObjectState","#validators","#validationMode","#isValid","#providerCtrl","#parent","#parentMessages","#localMessages","#baseDataPath","#currentProvideHost","controllerHost","dataPath","parent","toRemove","m","validator","resultsStatus","v","isValid","firstInvalid","#destroyValidators","UmbValidationContext","UMB_SERVER_MODEL_VALIDATOR_CONTEXT","UmbDataPathPropertyValueQuery","filters","UmbDataPathVariantQuery","propValueRegex","ExtractJsonQueryProps","query","propsMap","UmbServerModelValidatorContext","UmbContextBase","#validatePromise","#validatePromiseResolve","#context","#data","context","requestPromise","resolve","error","errorBody","alias","variant","observeSymbol","UmbBindServerValidationToFormControl","#control","#controlValidator","#value","defaultMemoization","formControl","simpleHashCode","messages","#demolish","#setup","UmbFormControlValidator","#dataPath","#setInvalid","#setValid","#setIsValid","newVal","ObserveSymbol","UmbObserveValidationStateController","callback","controllerAlias","UmbBindToValidationDirective","AsyncDirective","#host","#el","#validator","#msgBinder","nothing","args","umbBindToValidation","directive","WeightedErrorFlagTypes","UmbFormControlMixin","superClass","defaultValue","UmbFormControlMixinClass","#validity","#form","#formCtrlElements","#runValidatorsCallback","#onFormSubmit","newValue","el","#removeFormListeners","flagKey","getMessageMethod","checkMethod","a","b","innerFormControlEl","formCtrlEl","hasError","#dispatchValidationState","changedProperties","UmbValidationPathTranslatorBase","ctrlAlias","UmbAbstractArrayValidationPathTranslator","#initialPathToMatch","#queryMethod","initialPathToMatch","queryMethod","pathEnd","UmbVariantValuesValidationPathTranslator","UmbVariantsValidationPathTranslator"],"mappings":"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"}