From eceba7fcec08c3e4b54adcf789b61e08a6300f2c Mon Sep 17 00:00:00 2001 From: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:38:20 +0100 Subject: [PATCH 1/2] ui(eslint): update typescript-eslint and plugins to latest --- eslint.config.mjs | 11 +- package.json | 5 +- .../components/CodePreviewLegacy.vue | 2 +- .../components/CodePreviewNew.vue | 2 +- packages/documentation/components/NavBar.vue | 12 +- packages/documentation/pages/changelog.vue | 2 +- .../pages/foundations/icons/list.vue | 2 +- .../pages/usage/components/avatar.vue | 20 +- .../pages/usage/components/breadcrumb.vue | 20 +- .../pages/usage/components/comment.vue | 30 +- .../pages/usage/components/drawer.vue | 2 +- .../usage/components/field-inline-edit.vue | 4 +- .../pages/usage/components/form-fields.vue | 19 +- .../pages/usage/components/heading.vue | 2 +- .../pages/usage/components/loadings.vue | 2 +- .../pages/usage/components/modal.vue | 4 +- .../pages/usage/components/popover.vue | 2 +- .../pages/usage/components/table.vue | 5 +- packages/eslint-config/package.json | 24 +- packages/eslint-config/source/index.ts | 47 +- .../source/rules/vue-consistent-ref-names.ts | 1 - .../source/rules/vue-no-v-model-deep.ts | 1 - .../source/rules/vue-no-v-t-on-components.ts | 1 - .../rules/vue-no-v-t-without-translation.ts | 1 - .../kotti-ui/source/kotti-accordion/hooks.ts | 4 +- .../kotti-ui/source/kotti-avatar/KtAvatar.vue | 6 +- .../source/kotti-breadcrumb/KtBreadcrumb.vue | 6 +- .../source/kotti-button/KtSplitButton.vue | 1 + .../kotti-ui/source/kotti-comment/index.ts | 32 +- .../kotti-field-currency/KtFieldCurrency.vue | 10 +- .../source/kotti-field-currency/types.ts | 2 +- .../kotti-field-date/KtFieldDateTime.vue | 4 +- .../kotti-field-date/KtFieldDateTimeRange.vue | 4 +- .../kotti-ui/source/kotti-field-date/hooks.ts | 28 +- .../KtFieldInlineEdit.vue | 2 +- .../components/ConfirmButton.vue | 4 +- .../components/EditIcon.vue | 2 +- .../source/kotti-field-inline-edit/hooks.ts | 4 +- .../kotti-field-number/KtFieldNumber.vue | 2 +- .../kotti-field-password/KtFieldPassword.vue | 8 +- .../components/GenericSelectField.vue | 9 +- .../kotti-field-select/components/Options.vue | 12 +- .../kotti-ui/source/kotti-field/errors.ts | 24 +- packages/kotti-ui/source/kotti-field/hooks.ts | 2 +- .../source/kotti-file-upload/KtFileUpload.vue | 4 +- .../source/kotti-filters/KtFilters.vue | 8 +- .../kotti-filters/components/FilterRow.vue | 2 +- .../kotti-ui/source/kotti-filters/utils.ts | 7 +- .../KtFormControllerList.test.ts | 2 +- .../KtFormControllerObject.test.ts | 2 +- .../kotti-ui/source/kotti-form/KtForm.test.ts | 4 +- .../kotti-ui/source/kotti-form/KtForm.vue | 2 +- packages/kotti-ui/source/kotti-form/types.ts | 7 +- .../kotti-ui/source/kotti-form/utilities.ts | 6 +- packages/kotti-ui/source/kotti-i18n/types.ts | 2 +- .../kotti-ui/source/kotti-line/KtLine.vue | 2 +- .../source/kotti-pagination/KtPagination.vue | 20 +- .../components/PaginationFlexible.vue | 8 +- .../components/PaginationFractionated.vue | 4 +- .../kotti-table-legacy/KtTableLegacyColumn.ts | 2 +- .../components/TableBody.ts | 2 +- .../components/TableBodyExpandRow.ts | 4 +- .../components/TableHeader.vue | 34 +- .../source/kotti-table-legacy/logic/column.ts | 5 +- .../source/kotti-table-legacy/logic/expand.ts | 3 +- .../source/kotti-table-legacy/logic/sort.ts | 1 + .../source/kotti-table-legacy/logic/types.ts | 2 - .../kotti-ui/source/kotti-table/KtTable.vue | 6 +- .../components/filters/NumberRange.vue | 6 +- .../kotti-table/standard-table/simple-hash.ts | 2 + .../kotti-table/standard-table/storage.ts | 28 +- .../kotti-table/standard-table/types.ts | 27 +- .../standard-table/utilities/filters.ts | 1 + .../standard-table/utilities/translation.ts | 1 + .../source/kotti-table/table/hooks.ts | 4 +- .../kotti-table/table/tanstack-table/index.ts | 2 +- .../source/kotti-toaster/create-toaster.ts | 2 + packages/kotti-ui/source/make-props.test.ts | 2 + packages/kotti-ui/source/make-props.ts | 77 +- .../toggle-inner/ToggleInner.vue | 2 +- packages/kotti-ui/source/types/kotti.ts | 12 +- packages/kotti-ui/source/types/utilities.ts | 8 +- packages/kotti-ui/vite.config.ts | 4 +- packages/vue-use-tippy/source/index.ts | 2 +- yarn.lock | 2431 ++++++++++++++--- 85 files changed, 2431 insertions(+), 706 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index c01dcf96aa..e9bb9c86f2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -78,12 +78,10 @@ const config = tseslint.config( languageOptions: { ecmaVersion: 2022, parserOptions: { - project: [ - './tsconfig.json', - './internals/*/tsconfig.json', - './packages/*/tsconfig.json', - './packages/kotti-ui/tsconfig.node.json', - ], + projectService: { + allowDefaultProject: ['*.mjs'], + defaultProject: 'tsconfig.json', + }, tsconfigRootDir: root, }, sourceType: 'module', @@ -126,6 +124,7 @@ const config = tseslint.config( ], }, ], + '@typescript-eslint/prefer-namespace-keyword': 'off', }, }, { diff --git a/package.json b/package.json index a95423f6d3..1efd9687fe 100644 --- a/package.json +++ b/package.json @@ -46,11 +46,12 @@ "url": "https://github.com/carsoli" } ], + "dependencies": {}, "devDependencies": { "@3yourmind/eslint-config": "*", "@types/eslint__js": "^8.42.3", "@types/node": "20.11.16", - "eslint": "^9.2.0", + "eslint": "^9.17.0", "husky": "^7.0.1", "knip": "^5.13.0", "lerna": "^7.4.2", @@ -68,7 +69,7 @@ "stylelint-csstree-validator": "^3.0.0", "stylelint-prettier": "^4.0.2", "turbo": "^1.13.3", - "typescript": "^5.4.4", + "typescript": "5.4.4", "typescript-eslint": "^7.8.0" }, "engines": { diff --git a/packages/documentation/components/CodePreviewLegacy.vue b/packages/documentation/components/CodePreviewLegacy.vue index 687a0f3f39..08d9aa8fbd 100644 --- a/packages/documentation/components/CodePreviewLegacy.vue +++ b/packages/documentation/components/CodePreviewLegacy.vue @@ -16,8 +16,8 @@ import { computed, defineComponent, ref } from 'vue' export default defineComponent({ name: 'CodePreviewLegacy', props: { - vueSlotLabel: { default: 'Kotti-UI', type: String }, styleSlotLabel: { default: 'Kotti-Style', type: String }, + vueSlotLabel: { default: 'Kotti-UI', type: String }, }, setup(props) { const showCode = ref(true) diff --git a/packages/documentation/components/CodePreviewNew.vue b/packages/documentation/components/CodePreviewNew.vue index 3a50aa6e19..ab8fa7c18a 100644 --- a/packages/documentation/components/CodePreviewNew.vue +++ b/packages/documentation/components/CodePreviewNew.vue @@ -32,7 +32,7 @@ import { error, success } from '~/utilities/toaster' /** * Port of an equivalent component from 'vue3/upgrade'. Used to document the new kt-toaster - * TODO: remove in vue3 + * FIXME: remove in vue3 */ export default defineComponent({ name: 'CodePreviewNew', diff --git a/packages/documentation/components/NavBar.vue b/packages/documentation/components/NavBar.vue index 83ce7c2b83..4592385329 100644 --- a/packages/documentation/components/NavBar.vue +++ b/packages/documentation/components/NavBar.vue @@ -32,7 +32,7 @@ const saveSavedFieldsToLocalStorage = (isNarrow: boolean) => { LOCALSTORAGE_IS_NAVBAR_NARROW_KEY, JSON.stringify(isNarrow), ) - } catch (error) { + } catch { // eslint-disable-next-line no-console console.warn('could not save to localStorage') } @@ -55,7 +55,7 @@ export default defineComponent({ ) if (value) return JSON.parse(value) } - } catch (error) { + } catch { // eslint-disable-next-line no-console console.warn('could not read localStorage') } @@ -68,20 +68,20 @@ export default defineComponent({ navLogo, quickLinks: [ { - title: 'Create New Issue', link: 'https://github.com/3YOURMIND/kotti/issues/new/choose', + title: 'Create New Issue', }, { - title: 'NPM', link: 'https://www.npmjs.com/package/@3yourmind/kotti-ui', + title: 'NPM', }, { - title: 'Issues', link: 'https://github.com/3YOURMIND/kotti/issues', + title: 'Issues', }, { - title: 'Readme', link: 'https://github.com/3YOURMIND/kotti#readme', + title: 'Readme', }, ], sections: computed(() => diff --git a/packages/documentation/pages/changelog.vue b/packages/documentation/pages/changelog.vue index 5c9fb6bde5..781dd2cc53 100644 --- a/packages/documentation/pages/changelog.vue +++ b/packages/documentation/pages/changelog.vue @@ -142,9 +142,9 @@ export default defineComponent({ return { dayjs, isLoading, + releases, renderMarkdown: (markdown: string) => marked.parse(convertPoundToIssueLink(markdown)), - releases, sortedReleases: computed(() => cloneDeep(releases.value).sort((a, b) => naturalSort({ direction: 'desc' })(a.tag_name, b.tag_name), diff --git a/packages/documentation/pages/foundations/icons/list.vue b/packages/documentation/pages/foundations/icons/list.vue index 48648bb322..0e6ca0590d 100644 --- a/packages/documentation/pages/foundations/icons/list.vue +++ b/packages/documentation/pages/foundations/icons/list.vue @@ -34,7 +34,6 @@ export default defineComponent({ }, setup() { const component: { meta: Kotti.Meta; name: string } = { - name: 'Icons', meta: { addedVersion: null, deprecated: null, @@ -48,6 +47,7 @@ export default defineComponent({ schema: yocoIconSchema, }, }, + name: 'Icons', } return { diff --git a/packages/documentation/pages/usage/components/avatar.vue b/packages/documentation/pages/usage/components/avatar.vue index 07d0a415d3..165aa8c54b 100644 --- a/packages/documentation/pages/usage/components/avatar.vue +++ b/packages/documentation/pages/usage/components/avatar.vue @@ -110,13 +110,6 @@ export default defineComponent({ }, setup() { return { - avatarSettings: ref({ - isHoverable: false, - name: "Jony O'Five", - showContentSlot: false, - size: Kotti.Avatar.Size.MEDIUM, - src: 'https://picsum.photos/200/100', - }), avatarGroupSettings: ref< Kotti.AvatarGroup.Props & { showContentSlot: boolean } >({ @@ -133,13 +126,20 @@ export default defineComponent({ showContentSlot: false, size: Kotti.Avatar.Size.MEDIUM, }), + avatarSettings: ref({ + isHoverable: false, + name: "Jony O'Five", + showContentSlot: false, + size: Kotti.Avatar.Size.MEDIUM, + src: 'https://picsum.photos/200/100', + }), + Kotti, + KtAvatar, + KtAvatarGroup, sizeOptions: Object.entries(Kotti.Avatar.Size).map(([label, value]) => ({ label, value, })), - Kotti, - KtAvatar, - KtAvatarGroup, Yoco, } }, diff --git a/packages/documentation/pages/usage/components/breadcrumb.vue b/packages/documentation/pages/usage/components/breadcrumb.vue index 1731550226..695e9c2069 100644 --- a/packages/documentation/pages/usage/components/breadcrumb.vue +++ b/packages/documentation/pages/usage/components/breadcrumb.vue @@ -103,44 +103,44 @@ export default defineComponent({ component: KtBreadcrumb, links: [ { - title: 'Kotti', + isCompleted: true, onClick: () => { activeIndex.value = 0 void router.value.push('#') }, - isCompleted: true, + title: 'Kotti', }, { - title: 'Usage', + isCompleted: true, onClick: () => { activeIndex.value = 1 void router.value.push('#') }, - isCompleted: true, + title: 'Usage', }, { - title: 'Components', + isCompleted: true, onClick: () => { activeIndex.value = 2 void router.value.push('#') }, - isCompleted: true, + title: 'Components', }, { - title: 'Links', + isCompleted: false, onClick: () => { activeIndex.value = 3 void router.value.push('#') }, - isCompleted: false, + title: 'Links', }, { - title: 'Breadcrumbs', + isDisabled: true, onClick: () => { activeIndex.value = 4 void router.value.push('#') }, - isDisabled: true, + title: 'Breadcrumbs', }, ], textSeparator: { diff --git a/packages/documentation/pages/usage/components/comment.vue b/packages/documentation/pages/usage/components/comment.vue index 393239b8dd..2dd07499a6 100644 --- a/packages/documentation/pages/usage/components/comment.vue +++ b/packages/documentation/pages/usage/components/comment.vue @@ -394,8 +394,8 @@ export default defineComponent({ comment.id === payload.id ? { ...comment, - isModified: true, isInternal: payload.isInternal, + isModified: true, message: payload.message, } : comment @@ -432,12 +432,16 @@ export default defineComponent({ }), ) }, - handleEdit(payload: Kotti.Comment.Events.Edit) { + handleDelete(payload: Kotti.Comment.Events.Delete) { if (!payload.parentId) { if (!comments.value.some((comment) => comment.id === payload.id)) - throw new Error(`Comment not found, comment id: ${payload.id}`) + throw new Error( + `Comment not found, comment id: ${String(payload.id)}`, + ) - comments.value = comments.value.map(editComment(payload)) + comments.value = comments.value.filter( + (comment) => comment.id !== payload.id, + ) return } @@ -455,18 +459,16 @@ export default defineComponent({ `Comment not found, comment id: ${String(payload.id)}`, ) - parentComment.replies = parentComment.replies.map(editComment(payload)) + parentComment.replies = parentComment.replies.filter( + (reply) => reply.id !== payload.id, + ) }, - handleDelete(payload: Kotti.Comment.Events.Delete) { + handleEdit(payload: Kotti.Comment.Events.Edit) { if (!payload.parentId) { if (!comments.value.some((comment) => comment.id === payload.id)) - throw new Error( - `Comment not found, comment id: ${String(payload.id)}`, - ) + throw new Error(`Comment not found, comment id: ${payload.id}`) - comments.value = comments.value.filter( - (comment) => comment.id !== payload.id, - ) + comments.value = comments.value.map(editComment(payload)) return } @@ -484,9 +486,7 @@ export default defineComponent({ `Comment not found, comment id: ${String(payload.id)}`, ) - parentComment.replies = parentComment.replies.filter( - (reply) => reply.id !== payload.id, - ) + parentComment.replies = parentComment.replies.map(editComment(payload)) }, postEscapeParser: (msg: string) => msg.replaceAll('\n', '
'), settings, diff --git a/packages/documentation/pages/usage/components/drawer.vue b/packages/documentation/pages/usage/components/drawer.vue index d5d2f95259..063ceadc7b 100644 --- a/packages/documentation/pages/usage/components/drawer.vue +++ b/packages/documentation/pages/usage/components/drawer.vue @@ -149,8 +149,8 @@ import ComponentInfo from '~/components/ComponentInfo.vue' export default defineComponent({ name: 'DocumentationPageUsageComponentsDrawer', components: { - ComponentInfo, CodePreviewLegacy, + ComponentInfo, }, data() { return { diff --git a/packages/documentation/pages/usage/components/field-inline-edit.vue b/packages/documentation/pages/usage/components/field-inline-edit.vue index 79b7b2ce92..1148f2f657 100644 --- a/packages/documentation/pages/usage/components/field-inline-edit.vue +++ b/packages/documentation/pages/usage/components/field-inline-edit.vue @@ -174,8 +174,6 @@ export default defineComponent({ { label: '', value: 'token' }, ]), component: KtFieldInlineEdit, - formValue, - fieldValue: computed(() => formValue.value.fieldValue), fieldProps: computed(() => ({ autoComplete: settings.value.autoComplete === 'token' @@ -200,6 +198,8 @@ export default defineComponent({ type: settings.value.validation ?? 'empty', }), })), + fieldValue: computed(() => formValue.value.fieldValue), + formValue, onConfirm: (newVal: Kotti.FieldInlineEdit.Events.Confirm) => { success({ text: newVal ?? '' }) }, diff --git a/packages/documentation/pages/usage/components/form-fields.vue b/packages/documentation/pages/usage/components/form-fields.vue index 8e574bbc1b..d3ba685804 100644 --- a/packages/documentation/pages/usage/components/form-fields.vue +++ b/packages/documentation/pages/usage/components/form-fields.vue @@ -803,7 +803,7 @@ const saveSavedFieldsToLocalStorage = (savedFields: Array) => { LOCALSTORAGE_SAVED_COMPONENTS_KEY, JSON.stringify(savedFields), ) - } catch (error) { + } catch { // eslint-disable-next-line no-console console.warn('could not save to localStorage') } @@ -1337,6 +1337,7 @@ export default defineComponent({ settings.value.component.includes('Range'), ) + // eslint-disable-next-line sonarjs/cognitive-complexity const componentProps = computed(() => { const standardProps = { dataTest: settings.value.dataTest, @@ -1666,7 +1667,7 @@ export default defineComponent({ ) if (value) return JSON.parse(value) } - } catch (error) { + } catch { // eslint-disable-next-line no-console console.warn('could not read localStorage') } @@ -1814,6 +1815,13 @@ export default defineComponent({ reset: () => { values.value = INITIAL_VALUES }, + savedFieldsAdd: () => { + savedFields.value = [ + ...savedFields.value, + cloneDeep(componentValue.value), + ] + saveSavedFieldsToLocalStorage(savedFields.value) + }, savedFieldsMap: computed(() => savedFields.value.map( (component): ComponentRepresentation => ({ @@ -1823,13 +1831,6 @@ export default defineComponent({ }), ), ), - savedFieldsAdd: () => { - savedFields.value = [ - ...savedFields.value, - cloneDeep(componentValue.value), - ] - saveSavedFieldsToLocalStorage(savedFields.value) - }, savedFieldsRemove: (toRemove: number) => { savedFields.value = savedFields.value.filter( (_, index) => index !== toRemove, diff --git a/packages/documentation/pages/usage/components/heading.vue b/packages/documentation/pages/usage/components/heading.vue index 3be84fcff8..34677a82ee 100644 --- a/packages/documentation/pages/usage/components/heading.vue +++ b/packages/documentation/pages/usage/components/heading.vue @@ -100,10 +100,10 @@ export default defineComponent({ setup() { return { component: KtHeading, - toggle: ref(false), showAlert() { info({ text: 'H3 Action Clicked' }) }, + toggle: ref(false), } }, }) diff --git a/packages/documentation/pages/usage/components/loadings.vue b/packages/documentation/pages/usage/components/loadings.vue index 021444638f..0c691471a1 100644 --- a/packages/documentation/pages/usage/components/loadings.vue +++ b/packages/documentation/pages/usage/components/loadings.vue @@ -132,7 +132,6 @@ export default defineComponent({ }, setup() { const component: { meta: Kotti.Meta; name: string } = { - name: 'Loadings', meta: { addedVersion: null, deprecated: null, @@ -143,6 +142,7 @@ export default defineComponent({ slots: {}, typeScript: null, }, + name: 'Loadings', } return { diff --git a/packages/documentation/pages/usage/components/modal.vue b/packages/documentation/pages/usage/components/modal.vue index 963c8246f0..95a473f7ef 100644 --- a/packages/documentation/pages/usage/components/modal.vue +++ b/packages/documentation/pages/usage/components/modal.vue @@ -97,8 +97,6 @@ export default defineComponent({ setup() { return { component: KtModal, - showAnnouncement: ref(true), - showModal: ref(false), settings: ref<{ preventCloseOutside: boolean size: Kotti.Modal.Size @@ -116,6 +114,8 @@ export default defineComponent({ header: true, }, }), + showAnnouncement: ref(true), + showModal: ref(false), } }, }) diff --git a/packages/documentation/pages/usage/components/popover.vue b/packages/documentation/pages/usage/components/popover.vue index 5daa4e91d8..299ae8f1f0 100644 --- a/packages/documentation/pages/usage/components/popover.vue +++ b/packages/documentation/pages/usage/components/popover.vue @@ -289,6 +289,7 @@ export default defineComponent({ value, })), ), + UsageMode, usageOptions: computed(() => [ { label: 'Use Slot', value: UsageMode.SLOT }, { label: 'Use Options', value: UsageMode.OPTIONS }, @@ -297,7 +298,6 @@ export default defineComponent({ value: UsageMode.SELECTABLE_OPTIONS, }, ]), - UsageMode, values: ref< Pick & { usageMode: UsageMode diff --git a/packages/documentation/pages/usage/components/table.vue b/packages/documentation/pages/usage/components/table.vue index 4c4e04a129..dc51844368 100644 --- a/packages/documentation/pages/usage/components/table.vue +++ b/packages/documentation/pages/usage/components/table.vue @@ -438,8 +438,9 @@ export default defineComponent({ }, expandMode, reverseColumnOrder: () => { - tableHook.api.columnOrder.value = - tableHook.api.columnOrder.value.reverse() + const localColumns = [...tableHook.api.columnOrder.value] + localColumns.reverse() + tableHook.api.columnOrder.value = localColumns }, showAllColumns: () => { tableHook.api.hiddenColumns.value = new Set() diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index bcfb2786c2..fd4b87f1f8 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -4,21 +4,21 @@ "url": "https://github.com/3YOURMIND/kotti/issues" }, "dependencies": { - "@eslint/js": "^9.3.0", - "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0", - "@typescript-eslint/utils": "^7.11.0", + "@eslint/js": "^9.17.0", + "@eslint-community/eslint-plugin-eslint-comments": "^4.4.1", + "@typescript-eslint/utils": "^8.19.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jsonc": "^2.16.0", - "eslint-plugin-perfectionist": "^3.8.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-sonarjs": "^1.0.3", - "eslint-plugin-unicorn": "^53.0.0", + "eslint-plugin-jsonc": "^2.18.2", + "eslint-plugin-perfectionist": "^4.6.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-sonarjs": "^3.0.1", + "eslint-plugin-unicorn": "^56.0.1", "eslint-plugin-vitest": "^0.5.4", - "eslint-plugin-vue": "^9.26.0", - "globals": "^15.3.0", + "eslint-plugin-vue": "^9.32.0", + "globals": "^15.14.0", "jsonc-eslint-parser": "^2.4.0", - "typescript-eslint": "^7.11.0", - "vue-eslint-parser": "^9.4.2" + "typescript-eslint": "^8.19.1", + "vue-eslint-parser": "^9.4.3" }, "description": "ESLint config for 3YOURMIND", "exports": { diff --git a/packages/eslint-config/source/index.ts b/packages/eslint-config/source/index.ts index 2523634d25..da1e14ab58 100644 --- a/packages/eslint-config/source/index.ts +++ b/packages/eslint-config/source/index.ts @@ -1,5 +1,5 @@ -import eslint from '@eslint/js' import comments from '@eslint-community/eslint-plugin-eslint-comments/configs' +import eslint from '@eslint/js' import type { TSESLint } from '@typescript-eslint/utils' import type { SharedConfig } from '@typescript-eslint/utils/ts-eslint' import jsonc from 'eslint-plugin-jsonc' @@ -126,6 +126,12 @@ const baseConfig = tseslint.config({ { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }, ], '@typescript-eslint/no-use-before-define': 'error', + '@typescript-eslint/switch-exhaustiveness-check': [ + 'error', + { + considerDefaultExhaustiveForUnions: true, + }, + ], // Eslint 'dot-notation': 'warn', @@ -144,11 +150,20 @@ const baseConfig = tseslint.config({ 'prettier/prettier': 'warn', // SonarJS + 'sonarjs/deprecation': 'off', // deprecation is intentionally used for flagging outdated but not yet removed code + 'sonarjs/different-types-comparison': 'off', // conflicts with @typescript-eslint/no-unnecessary-condition + 'sonarjs/empty-string-repetition': 'off', + 'sonarjs/fixme-tag': 'off', + 'sonarjs/function-return-type': 'off', 'sonarjs/no-collapsible-if': 'off', // replaced by unicorn/no-lonely-if 'sonarjs/no-duplicate-string': 'off', + 'sonarjs/no-nested-conditional': 'off', 'sonarjs/no-redundant-jump': 'off', 'sonarjs/no-small-switch': 'off', 'sonarjs/no-use-of-empty-return-value': 'off', + 'sonarjs/pseudo-random': 'off', + 'sonarjs/redundant-type-aliases': 'off', + 'sonarjs/void-use': 'off', // Unicorn 'unicorn/catch-error-name': 'warn', @@ -284,14 +299,23 @@ const rulesRequiringTypes = { allowRegExp: false, }, ], - '@typescript-eslint/switch-exhaustiveness-check': 'error', } satisfies SharedConfig.RulesRecord const plugin = { rules, } satisfies TSESLint.FlatConfig.Plugin -export default { +const kottiEslintConfig: { + configs: { + default: TSESLint.FlatConfig.ConfigArray + global: TSESLint.FlatConfig.ConfigArray + json: TSESLint.FlatConfig.ConfigArray + tests: TSESLint.FlatConfig.ConfigArray + untyped: TSESLint.FlatConfig.ConfigArray + vue: TSESLint.FlatConfig.ConfigArray + } + plugin: TSESLint.FlatConfig.Plugin +} = { configs: { /** * Should be used on .ts and .tsx files. This enables rules that rely on type checking. @@ -406,6 +430,12 @@ export default { type: 'natural', }, ], + 'perfectionist/sort-jsx-props': [ + 'warn', + { + type: 'natural', + }, + ], 'perfectionist/sort-maps': [ 'warn', { @@ -413,6 +443,7 @@ export default { type: 'natural', }, ], + 'perfectionist/sort-modules': 'off', // conflicts with @typescript-eslint/no-use-before-define 'perfectionist/sort-named-exports': [ 'warn', { partitionByComment: true, type: 'natural' }, @@ -446,6 +477,12 @@ export default { type: 'natural', }, ], + 'perfectionist/sort-switch-case': [ + 'warn', + { + type: 'natural', + }, + ], 'perfectionist/sort-union-types': [ 'warn', { @@ -539,10 +576,12 @@ export default { '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-return': 'off', + '@typescript-eslint/no-unused-expressions': 'off', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/restrict-template-expressions': 'off', 'no-console': 'off', 'no-magic-numbers': 'off', + 'sonarjs/no-nested-functions': 'off', 'vitest/no-disabled-tests': 'error', 'vitest/no-identical-title': 'error', 'vue/one-component-per-file': 'off', @@ -644,3 +683,5 @@ export default { }, plugin, } + +export default kottiEslintConfig diff --git a/packages/eslint-config/source/rules/vue-consistent-ref-names.ts b/packages/eslint-config/source/rules/vue-consistent-ref-names.ts index 43a831fbba..0b1356abbf 100644 --- a/packages/eslint-config/source/rules/vue-consistent-ref-names.ts +++ b/packages/eslint-config/source/rules/vue-consistent-ref-names.ts @@ -28,7 +28,6 @@ export default createRule({ meta: { docs: { description, - requiresTypeChecking: false, }, messages: { avoidName: "Refs to elements or components should always end with 'Ref'", diff --git a/packages/eslint-config/source/rules/vue-no-v-model-deep.ts b/packages/eslint-config/source/rules/vue-no-v-model-deep.ts index 05af8072a1..de5c158167 100644 --- a/packages/eslint-config/source/rules/vue-no-v-model-deep.ts +++ b/packages/eslint-config/source/rules/vue-no-v-model-deep.ts @@ -26,7 +26,6 @@ export default createRule({ meta: { docs: { description, - requiresTypeChecking: false, }, messages: { avoidDeepAttributesInProps: diff --git a/packages/eslint-config/source/rules/vue-no-v-t-on-components.ts b/packages/eslint-config/source/rules/vue-no-v-t-on-components.ts index c2a7e3325c..66fc3306d8 100644 --- a/packages/eslint-config/source/rules/vue-no-v-t-on-components.ts +++ b/packages/eslint-config/source/rules/vue-no-v-t-on-components.ts @@ -28,7 +28,6 @@ export default createRule({ meta: { docs: { description, - requiresTypeChecking: false, }, messages: { avoidUnsupportedVT: diff --git a/packages/eslint-config/source/rules/vue-no-v-t-without-translation.ts b/packages/eslint-config/source/rules/vue-no-v-t-without-translation.ts index 4985dd5c68..8abdb3cb8e 100644 --- a/packages/eslint-config/source/rules/vue-no-v-t-without-translation.ts +++ b/packages/eslint-config/source/rules/vue-no-v-t-without-translation.ts @@ -43,7 +43,6 @@ export default createRule({ meta: { docs: { description, - requiresTypeChecking: false, }, messages: { missingTranslation: diff --git a/packages/kotti-ui/source/kotti-accordion/hooks.ts b/packages/kotti-ui/source/kotti-accordion/hooks.ts index 4f760089a5..aaa5ad4a4a 100644 --- a/packages/kotti-ui/source/kotti-accordion/hooks.ts +++ b/packages/kotti-ui/source/kotti-accordion/hooks.ts @@ -27,7 +27,9 @@ export const useSlideAnimation = ( const animation = animatedObject.animate(frames, finalOptions) animation.pause() - willOpen ? animation.play() : animation.reverse() + + if (willOpen) animation.play() + else animation.reverse() await animation.finished diff --git a/packages/kotti-ui/source/kotti-avatar/KtAvatar.vue b/packages/kotti-ui/source/kotti-avatar/KtAvatar.vue index f8634907cd..354eae3894 100644 --- a/packages/kotti-ui/source/kotti-avatar/KtAvatar.vue +++ b/packages/kotti-ui/source/kotti-avatar/KtAvatar.vue @@ -74,12 +74,12 @@ export default defineComponent({ })), avatarFallback, contentRef, - onImageFailedToLoad: () => { - avatarFallback.value = false - }, onAvatarContainerClick(event: MouseEvent) { emit('click', event) }, + onImageFailedToLoad: () => { + avatarFallback.value = false + }, triggerRef, Yoco, } diff --git a/packages/kotti-ui/source/kotti-breadcrumb/KtBreadcrumb.vue b/packages/kotti-ui/source/kotti-breadcrumb/KtBreadcrumb.vue index b6c4f457c9..f4d61c4f0c 100644 --- a/packages/kotti-ui/source/kotti-breadcrumb/KtBreadcrumb.vue +++ b/packages/kotti-ui/source/kotti-breadcrumb/KtBreadcrumb.vue @@ -44,11 +44,11 @@ export default defineComponent({ breadCrumbClasses: (item: KottiBreadcrumb.Breadcrumb, index: number) => { return { 'kt-breadcrumb__list-item': true, - 'kt-breadcrumb__list-item--is-disabled': item.isDisabled, - 'kt-breadcrumb__list-item--is-completed': - !item.isDisabled && item.isCompleted, 'kt-breadcrumb__list-item--is-active': !item.isDisabled && index === props.activeIndex, + 'kt-breadcrumb__list-item--is-completed': + !item.isDisabled && item.isCompleted, + 'kt-breadcrumb__list-item--is-disabled': item.isDisabled, } }, handleClick: (item: KottiBreadcrumb.Breadcrumb) => { diff --git a/packages/kotti-ui/source/kotti-button/KtSplitButton.vue b/packages/kotti-ui/source/kotti-button/KtSplitButton.vue index e64dc05ecd..80b3544687 100755 --- a/packages/kotti-ui/source/kotti-button/KtSplitButton.vue +++ b/packages/kotti-ui/source/kotti-button/KtSplitButton.vue @@ -138,6 +138,7 @@ export default defineComponent({ watch( () => isTippyOpen.value, (isOpen) => { + // eslint-disable-next-line sonarjs/no-selector-parameter if (!isOpen) currentActionIndexInFocus.value = UNSET_INDEX else if (hasAvailableActions.value) // Focus the 1st available action item diff --git a/packages/kotti-ui/source/kotti-comment/index.ts b/packages/kotti-ui/source/kotti-comment/index.ts index c99313e0b3..026bf81334 100644 --- a/packages/kotti-ui/source/kotti-comment/index.ts +++ b/packages/kotti-ui/source/kotti-comment/index.ts @@ -1,3 +1,5 @@ +import type { ComponentPublicInstanceConstructor } from 'vue/types/v3-component-public-instance' + import type { Kotti } from '../types' import { MetaDesignType } from '../types/kotti' import { attachMeta, makeInstallable } from '../utilities' @@ -16,17 +18,23 @@ const META: Omit = { slots: {}, } -export const KtComment = attachMeta(makeInstallable(KtCommentVue), { - ...META, - typeScript: { - namespace: 'Kotti.Comment', - schema: KottiComment.propsSchema, +export const KtComment = attachMeta( + makeInstallable(KtCommentVue as ComponentPublicInstanceConstructor), + { + ...META, + typeScript: { + namespace: 'Kotti.Comment', + schema: KottiComment.propsSchema, + }, }, -}) -export const KtCommentInput = attachMeta(makeInstallable(KtCommentInputVue), { - ...META, - typeScript: { - namespace: 'Kotti.CommentInput', - schema: KottiCommentInput.propsSchema, +) +export const KtCommentInput = attachMeta( + makeInstallable(KtCommentInputVue as ComponentPublicInstanceConstructor), + { + ...META, + typeScript: { + namespace: 'Kotti.CommentInput', + schema: KottiCommentInput.propsSchema, + }, }, -}) +) diff --git a/packages/kotti-ui/source/kotti-field-currency/KtFieldCurrency.vue b/packages/kotti-ui/source/kotti-field-currency/KtFieldCurrency.vue index 54ff1ebe56..db531c4930 100644 --- a/packages/kotti-ui/source/kotti-field-currency/KtFieldCurrency.vue +++ b/packages/kotti-ui/source/kotti-field-currency/KtFieldCurrency.vue @@ -156,11 +156,6 @@ export default defineComponent({ ) return { - modifiedField: computed(() => ({ - ...field, - prefix: currencyFormat.value.symbol, - })), - inputRef, inputProps: computed( (): InputHTMLAttributes & { class: Record @@ -179,6 +174,11 @@ export default defineComponent({ value: internalStringValue.value, }), ), + inputRef, + modifiedField: computed(() => ({ + ...field, + prefix: currencyFormat.value.symbol, + })), onInput: (event: Event) => { const value = (event.target as HTMLInputElement).value diff --git a/packages/kotti-ui/source/kotti-field-currency/types.ts b/packages/kotti-ui/source/kotti-field-currency/types.ts index 31464a850a..f39bf24070 100644 --- a/packages/kotti-ui/source/kotti-field-currency/types.ts +++ b/packages/kotti-ui/source/kotti-field-currency/types.ts @@ -3,7 +3,7 @@ import { z } from 'zod' import { KottiField } from '../kotti-field/types' export module KottiFieldCurrency { - const VALUE_PROP_REGEX = /^-?(0?|([1-9][0-9]*))?(\.[0-9]+)?$/ + const VALUE_PROP_REGEX = /^-?(0?|([1-9]\d*))?(\.\d+)?$/ export const valueSchema = z.string().regex(VALUE_PROP_REGEX).nullable() export type Value = z.output diff --git a/packages/kotti-ui/source/kotti-field-date/KtFieldDateTime.vue b/packages/kotti-ui/source/kotti-field-date/KtFieldDateTime.vue index 8881bd69e5..00e2c67200 100644 --- a/packages/kotti-ui/source/kotti-field-date/KtFieldDateTime.vue +++ b/packages/kotti-ui/source/kotti-field-date/KtFieldDateTime.vue @@ -83,6 +83,8 @@ export default defineComponent({ const isInPopover = inject(KT_IS_IN_POPOVER, false) return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + elDateRef: elDateRef as any, elDateTimePickerProps: computed( (): Partial => ({ ...EL_DATE_TIME_PROPS, @@ -101,8 +103,6 @@ export default defineComponent({ value: field.currentValue ?? '', }), ), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - elDateRef: elDateRef as any, field, inputContainerRef, onInput: (value: KottiFieldDateTime.Value) => { diff --git a/packages/kotti-ui/source/kotti-field-date/KtFieldDateTimeRange.vue b/packages/kotti-ui/source/kotti-field-date/KtFieldDateTimeRange.vue index 8d17a4b370..2c1f2bb146 100644 --- a/packages/kotti-ui/source/kotti-field-date/KtFieldDateTimeRange.vue +++ b/packages/kotti-ui/source/kotti-field-date/KtFieldDateTimeRange.vue @@ -85,6 +85,8 @@ export default defineComponent({ const isInPopover = inject(KT_IS_IN_POPOVER, false) return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + elDateRef: elDateRef as any, elDateTimeRangePickerProps: computed( (): Partial => ({ ...EL_DATE_TIME_PROPS, @@ -108,8 +110,6 @@ export default defineComponent({ ], }), ), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - elDateRef: elDateRef as any, field, inputContainerRef, onInput: (value: KottiFieldDateTimeRange.Value | null) => { diff --git a/packages/kotti-ui/source/kotti-field-date/hooks.ts b/packages/kotti-ui/source/kotti-field-date/hooks.ts index bcd3f2f472..d488ff9177 100644 --- a/packages/kotti-ui/source/kotti-field-date/hooks.ts +++ b/packages/kotti-ui/source/kotti-field-date/hooks.ts @@ -14,20 +14,6 @@ import type { KottiFieldDateTimeRange, } from './types' -type Values = - | KottiFieldDate.Value - | KottiFieldDateRange.Value - | KottiFieldDateTime.Value - | KottiFieldDateTimeRange.Value - -type HookParameters = { - elDateRef: Ref - field: KottiField.Hook.Returns - inputContainerRef: Ref - popperHeight: string - popperWidth: string -} - export type ElDateWithInternalAPI = ElDate & { blur(): void haveTrigger: boolean @@ -43,6 +29,20 @@ export type ElDateWithInternalAPI = ElDate & { showClose: boolean } +type HookParameters = { + elDateRef: Ref + field: KottiField.Hook.Returns + inputContainerRef: Ref + popperHeight: string + popperWidth: string +} + +type Values = + | KottiFieldDate.Value + | KottiFieldDateRange.Value + | KottiFieldDateTime.Value + | KottiFieldDateTimeRange.Value + const getDateComponent = ({ elDateRef, }: Pick, 'elDateRef'>) => { diff --git a/packages/kotti-ui/source/kotti-field-inline-edit/KtFieldInlineEdit.vue b/packages/kotti-ui/source/kotti-field-inline-edit/KtFieldInlineEdit.vue index b530050d86..f9188dc094 100644 --- a/packages/kotti-ui/source/kotti-field-inline-edit/KtFieldInlineEdit.vue +++ b/packages/kotti-ui/source/kotti-field-inline-edit/KtFieldInlineEdit.vue @@ -295,7 +295,6 @@ export default defineComponent({ onConfirm() } }, - sharedProps, rootClasses: computed(() => ({ 'kt-field-inline-edit': true, 'kt-field-inline-edit--is-editable': !props.isReadonly, @@ -303,6 +302,7 @@ export default defineComponent({ isEditing.value && !props.isDisabled, 'kt-field-inline-edit--is-readonly': props.isReadonly, })), + sharedProps, textareaProps: computed( (): TextareaHTMLAttributes & { class: Record diff --git a/packages/kotti-ui/source/kotti-field-inline-edit/components/ConfirmButton.vue b/packages/kotti-ui/source/kotti-field-inline-edit/components/ConfirmButton.vue index b05bca879a..88ab561e15 100644 --- a/packages/kotti-ui/source/kotti-field-inline-edit/components/ConfirmButton.vue +++ b/packages/kotti-ui/source/kotti-field-inline-edit/components/ConfirmButton.vue @@ -15,8 +15,8 @@ import { Yoco } from '@3yourmind/yoco' export default defineComponent({ name: 'ConfirmButton', props: { - tabIndex: { type: Number, default: 0 }, - dataTest: { type: String, default: null }, + dataTest: { default: null, type: String }, + tabIndex: { default: 0, type: Number }, }, emits: ['confirm'], setup(props, { emit }) { diff --git a/packages/kotti-ui/source/kotti-field-inline-edit/components/EditIcon.vue b/packages/kotti-ui/source/kotti-field-inline-edit/components/EditIcon.vue index 0bbe9dc209..9f031cc40a 100644 --- a/packages/kotti-ui/source/kotti-field-inline-edit/components/EditIcon.vue +++ b/packages/kotti-ui/source/kotti-field-inline-edit/components/EditIcon.vue @@ -10,7 +10,7 @@ import { Yoco } from '@3yourmind/yoco' export default defineComponent({ name: 'EditIcon', props: { - isDisabled: { type: Boolean, default: false }, + isDisabled: { default: false, type: Boolean }, }, setup(props) { return { diff --git a/packages/kotti-ui/source/kotti-field-inline-edit/hooks.ts b/packages/kotti-ui/source/kotti-field-inline-edit/hooks.ts index 6927dd4c96..e44db3377b 100644 --- a/packages/kotti-ui/source/kotti-field-inline-edit/hooks.ts +++ b/packages/kotti-ui/source/kotti-field-inline-edit/hooks.ts @@ -54,10 +54,10 @@ export const usePreventConfirm = ({ switch (props.preventConfirmationOn) { case KottiFieldInlineEdit.ConfirmationValidation.ERROR: return fieldValidation.value === 'error' - case KottiFieldInlineEdit.ConfirmationValidation.WARNING: - return ['error', 'warning'].includes(fieldValidation.value) case KottiFieldInlineEdit.ConfirmationValidation.NEVER: return false + case KottiFieldInlineEdit.ConfirmationValidation.WARNING: + return ['error', 'warning'].includes(fieldValidation.value) default: throw new Error( `KtFieldInlineEdit: Unexpected type for 'preventConfirmationOn': ${props.preventConfirmationOn}`, diff --git a/packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue b/packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue index f82ddfd18e..3313fcb0ae 100644 --- a/packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue +++ b/packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue @@ -305,7 +305,6 @@ export default defineComponent({ })), incrementButtonRef, incrementValue, - inputRef, inputProps: computed( (): InputHTMLAttributes & KottiField.Hook.Returns['inputProps'] & { @@ -326,6 +325,7 @@ export default defineComponent({ value: internalStringValue.value, }), ), + inputRef, onBlur: () => { forceUpdateDisplayedValue(field.currentValue) }, diff --git a/packages/kotti-ui/source/kotti-field-password/KtFieldPassword.vue b/packages/kotti-ui/source/kotti-field-password/KtFieldPassword.vue index 0086ef89ef..f49efbcb8d 100644 --- a/packages/kotti-ui/source/kotti-field-password/KtFieldPassword.vue +++ b/packages/kotti-ui/source/kotti-field-password/KtFieldPassword.vue @@ -36,6 +36,10 @@ export default defineComponent({ const { forceUpdate, forceUpdateKey } = useForceUpdate() return { field, + handleVisibilityChange: () => { + const isValueHidden = fieldType.value === 'password' + fieldType.value = isValueHidden ? 'text' : 'password' + }, inputProps: computed( (): InputHTMLAttributes & { class: string[] @@ -57,10 +61,6 @@ export default defineComponent({ forceUpdate() }, - handleVisibilityChange: () => { - const isValueHidden = fieldType.value === 'password' - fieldType.value = isValueHidden ? 'text' : 'password' - }, } }, }) diff --git a/packages/kotti-ui/source/kotti-field-select/components/GenericSelectField.vue b/packages/kotti-ui/source/kotti-field-select/components/GenericSelectField.vue index 19c997563a..7f8d239797 100644 --- a/packages/kotti-ui/source/kotti-field-select/components/GenericSelectField.vue +++ b/packages/kotti-ui/source/kotti-field-select/components/GenericSelectField.vue @@ -116,14 +116,14 @@ const propsSchema = Shared.propsSchema ]), }) -type SingleValue = - | KottiFieldSingleSelect.Value - | KottiFieldSingleSelectRemote.Value - type MultiValue = | KottiFieldMultiSelect.Value | KottiFieldMultiSelectRemote.Value +type SingleValue = + | KottiFieldSingleSelect.Value + | KottiFieldSingleSelectRemote.Value + export default defineComponent({ name: 'GenericSelectField', components: { @@ -286,7 +286,6 @@ export default defineComponent({ if (!props.isMultiple) selectTippy.setIsDropdownOpen(false) }, onPressDelete: () => { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Not sure if '??' is the right choice to handle empty strings if (queryValue.value || !props.isMultiple) return // only delete value if query is already empty const value = field.currentValue as MultiValue diff --git a/packages/kotti-ui/source/kotti-field-select/components/Options.vue b/packages/kotti-ui/source/kotti-field-select/components/Options.vue index 62eef730cd..f0ca02e24f 100644 --- a/packages/kotti-ui/source/kotti-field-select/components/Options.vue +++ b/packages/kotti-ui/source/kotti-field-select/components/Options.vue @@ -77,18 +77,18 @@ const propsSchema = z.object({ value: z.array(Shared.valueSchema), }) -type ModifiedOption = z.output< - (typeof propsSchema)['shape']['options'] ->[number] & { - isSelected: boolean -} - type ModifiedAction = z.output< (typeof propsSchema)['shape']['actions'] >[number] & { dataTest: string } +type ModifiedOption = z.output< + (typeof propsSchema)['shape']['options'] +>[number] & { + isSelected: boolean +} + const mod = (number: number, divisor: number) => ((number % divisor) + divisor) % divisor diff --git a/packages/kotti-ui/source/kotti-field/errors.ts b/packages/kotti-ui/source/kotti-field/errors.ts index 034cde1c0a..cde0a64b5d 100644 --- a/packages/kotti-ui/source/kotti-field/errors.ts +++ b/packages/kotti-ui/source/kotti-field/errors.ts @@ -5,6 +5,18 @@ const createErrorMessage = ( messages: string[], ) => `useField(${String(props.formKey ?? props.label)}): ${messages.join('\n')}` +class DisabledSetValueCalledError extends Error { + constructor(props: KottiField.PropsInternal) { + super( + createErrorMessage(props, [ + 'Attempted to setValue on a disabled field.', + 'Disabled fields should never call setValue as it causes unexpected behavior.', + ]), + ) + this.name = 'DisabledSetValueCalledError' + } +} + class ImplicitFormKeyNoneError extends Error { constructor(props: KottiField.PropsInternal) { super( @@ -33,18 +45,6 @@ class InvalidPropOutsideOfContextError extends Error { } } -class DisabledSetValueCalledError extends Error { - constructor(props: KottiField.PropsInternal) { - super( - createErrorMessage(props, [ - 'Attempted to setValue on a disabled field.', - 'Disabled fields should never call setValue as it causes unexpected behavior.', - ]), - ) - this.name = 'DisabledSetValueCalledError' - } -} - export const ktFieldErrors = { DisabledSetValueCalledError, ImplicitFormKeyNoneError, diff --git a/packages/kotti-ui/source/kotti-field/hooks.ts b/packages/kotti-ui/source/kotti-field/hooks.ts index 057ddd57ea..ced0be6238 100644 --- a/packages/kotti-ui/source/kotti-field/hooks.ts +++ b/packages/kotti-ui/source/kotti-field/hooks.ts @@ -165,7 +165,7 @@ const useValidation = ({ return { hideValidation, - // TODO: Write unit test to figure out if props.isDisabled affects this function or if a computed() is necessary + // FIXME: Write unit test to figure out if props.isDisabled affects this function or if a computed() is necessary validation: computed((): KottiField.Validation.Result => { const customValidation = (() => { if (!context && props.formKey) diff --git a/packages/kotti-ui/source/kotti-file-upload/KtFileUpload.vue b/packages/kotti-ui/source/kotti-file-upload/KtFileUpload.vue index 4dea0ffe1d..2bec34662e 100644 --- a/packages/kotti-ui/source/kotti-file-upload/KtFileUpload.vue +++ b/packages/kotti-ui/source/kotti-file-upload/KtFileUpload.vue @@ -75,11 +75,11 @@