diff --git a/package-lock.json b/package-lock.json index 649fd5198..295a9eccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11460,6 +11460,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, "node_modules/fastq": { "version": "1.17.1", "dev": true, @@ -23548,6 +23554,7 @@ "@googlemaps/js-api-loader": "^1.16.6", "@monaco-editor/loader": "^1.3.3", "@tato30/vue-pdf": "^1.9.6", + "ajv": "^8.17.1", "arquero": "^5.2.0", "chroma-js": "^2.4.2", "fuse.js": "7.0.0", @@ -23622,6 +23629,28 @@ } } }, + "src/ui/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "src/ui/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "tests/e2e": { "name": "writer-e2e", "version": "1.0.0", diff --git a/src/ui/package.json b/src/ui/package.json index 9787cafb2..c74f4e2fe 100644 --- a/src/ui/package.json +++ b/src/ui/package.json @@ -25,6 +25,7 @@ "@googlemaps/js-api-loader": "^1.16.6", "@monaco-editor/loader": "^1.3.3", "@tato30/vue-pdf": "^1.9.6", + "ajv": "^8.17.1", "arquero": "^5.2.0", "chroma-js": "^2.4.2", "fuse.js": "7.0.0", diff --git a/src/ui/src/builder/settings/BuilderFieldsAlign.vue b/src/ui/src/builder/settings/BuilderFieldsAlign.vue index 71da71685..4cce84c8b 100644 --- a/src/ui/src/builder/settings/BuilderFieldsAlign.vue +++ b/src/ui/src/builder/settings/BuilderFieldsAlign.vue @@ -24,6 +24,7 @@ v-if="mode == 'css'" ref="freehandInputEl" :value="component.content[fieldKey]" + :error="error" @input="handleInputCss" /> @@ -38,6 +39,7 @@ import { nextTick, onBeforeUnmount, onMounted, + PropType, Ref, ref, toRefs, @@ -135,11 +137,15 @@ const focusEls: Record> = { default: null, }; -const props = defineProps<{ - componentId: Component["id"]; - fieldKey: string; - direction: "horizontal" | "vertical"; -}>(); +const props = defineProps({ + componentId: { type: String as PropType, required: true }, + fieldKey: { type: String, required: true }, + direction: { + type: String as PropType<"horizontal" | "vertical">, + required: true, + }, + error: { type: String, required: false, default: undefined }, +}); const { componentId, fieldKey, direction } = toRefs(props); const component = computed(() => wf.getComponentById(componentId.value)); diff --git a/src/ui/src/builder/settings/BuilderFieldsColor.vue b/src/ui/src/builder/settings/BuilderFieldsColor.vue index 87114caa0..01d9d64e1 100644 --- a/src/ui/src/builder/settings/BuilderFieldsColor.vue +++ b/src/ui/src/builder/settings/BuilderFieldsColor.vue @@ -24,6 +24,7 @@ v-if="mode == 'css'" ref="freehandInputEl" :value="component.content[fieldKey]" + :error="error" @input="handleInput" /> @@ -40,6 +41,7 @@ import { Ref, ref, toRefs, + PropType, } from "vue"; import { Component } from "@/writerTypes"; import { useComponentActions } from "../useComponentActions"; @@ -65,10 +67,12 @@ const focusEls: Record> = { default: null, }; -const props = defineProps<{ - componentId: Component["id"]; - fieldKey: string; -}>(); +const props = defineProps({ + componentId: { type: String as PropType, required: true }, + fieldKey: { type: String, required: true }, + error: { type: String, required: false, default: undefined }, +}); + const { componentId, fieldKey } = toRefs(props); const component = computed(() => wf.getComponentById(componentId.value)); diff --git a/src/ui/src/builder/settings/BuilderFieldsKeyValue.vue b/src/ui/src/builder/settings/BuilderFieldsKeyValue.vue index 506a3fe56..97c2e1625 100644 --- a/src/ui/src/builder/settings/BuilderFieldsKeyValue.vue +++ b/src/ui/src/builder/settings/BuilderFieldsKeyValue.vue @@ -13,7 +13,10 @@ /> @@ -87,6 +91,7 @@ const props = defineProps({ componentId: { type: String, required: true }, fieldKey: { type: String, required: true }, instancePath: { type: Array as PropType, required: true }, + error: { type: String, required: false, default: undefined }, }); const { componentId, fieldKey } = toRefs(props); @@ -192,6 +197,9 @@ onMounted(async () => { border: 1px solid var(--builderSeparatorColor); border-radius: 8px; } +.staticList--invalid { + border-color: var(--wdsColorOrange5); +} .staticList:empty::before { content: "No entries yet."; diff --git a/src/ui/src/builder/settings/BuilderFieldsObject.vue b/src/ui/src/builder/settings/BuilderFieldsObject.vue index 8dba465c6..dbe6f01fe 100644 --- a/src/ui/src/builder/settings/BuilderFieldsObject.vue +++ b/src/ui/src/builder/settings/BuilderFieldsObject.vue @@ -6,6 +6,7 @@ variant="code" :value="component.content[fieldKey]" :placeholder="templateField?.default" + :error="error" @input=" (ev: Event) => formatAndSetContentValue((ev.target as HTMLInputElement).value) @@ -14,20 +15,21 @@