From 13f97dca7f7a38a9fd46ffa9cd7352aaa92f615e Mon Sep 17 00:00:00 2001 From: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:31:17 +0100 Subject: [PATCH 1/7] documentation(CodePreviewNew): backport CodePreview from 'vue3/upgrade' Co-Authored-By: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> --- .../components/CodePreviewNew.vue | 167 ++++++++++++++++++ packages/documentation/package.json | 1 + yarn.lock | 5 + 3 files changed, 173 insertions(+) create mode 100644 packages/documentation/components/CodePreviewNew.vue diff --git a/packages/documentation/components/CodePreviewNew.vue b/packages/documentation/components/CodePreviewNew.vue new file mode 100644 index 0000000000..3a50aa6e19 --- /dev/null +++ b/packages/documentation/components/CodePreviewNew.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/packages/documentation/package.json b/packages/documentation/package.json index 546b8a9a88..2186cbea6d 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -10,6 +10,7 @@ "lodash": "4.x", "marked": "^12.0.0", "natural-sort": "^1.0.0", + "ts-dedent": "^2.2.0", "vue-router": "3.x" }, "description": "Kotti-ui Doc Pages", diff --git a/yarn.lock b/yarn.lock index 77677aed5b..3faefce673 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14654,6 +14654,11 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + ts-loader@8.x, ts-loader@^8.0.17: version "8.4.0" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f" From 850d732d2b8d415fde1d83292060fdd8cb934018 Mon Sep 17 00:00:00 2001 From: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:57:00 +0100 Subject: [PATCH 2/7] chore(vue3): Remove vue-project Co-Authored-By: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> --- packages/vue-project/src/App.vue | 218 ------------------------------- 1 file changed, 218 deletions(-) delete mode 100644 packages/vue-project/src/App.vue diff --git a/packages/vue-project/src/App.vue b/packages/vue-project/src/App.vue deleted file mode 100644 index f1656570e9..0000000000 --- a/packages/vue-project/src/App.vue +++ /dev/null @@ -1,218 +0,0 @@ - - - - - From 52ee6864f799030d2c5770dc53b9b3a1e9fc4d9c Mon Sep 17 00:00:00 2001 From: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:57:27 +0100 Subject: [PATCH 3/7] dx(editorconfig): Remove Max Line Length Was likely never actually used Co-Authored-By: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> --- .editorconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 81274ea2f6..8b09ff3c1f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,7 +5,6 @@ charset = utf-8 end_of_line = lf indent_style = tab insert_final_newline = true -max_line_length = 80 trim_trailing_whitespace = true [*.md] From c3ba4bd69c9a75aa183327466f09fe2a6a1bacfa Mon Sep 17 00:00:00 2001 From: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:59:30 +0100 Subject: [PATCH 4/7] dx(eslint): Allow non-null-assertion, no-unnecessary-condition in Tests, Allow globalThis Co-Authored-By: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> --- packages/eslint-config/source/index.ts | 2 ++ packages/eslint-config/source/utils/no-restricted-globals.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/eslint-config/source/index.ts b/packages/eslint-config/source/index.ts index 320f994c17..853b238a84 100644 --- a/packages/eslint-config/source/index.ts +++ b/packages/eslint-config/source/index.ts @@ -528,6 +528,8 @@ export default { '@typescript-eslint/no-empty-function': 'off', '@typescript-eslint/no-empty-interface': 'off', '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unnecessary-condition': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', diff --git a/packages/eslint-config/source/utils/no-restricted-globals.ts b/packages/eslint-config/source/utils/no-restricted-globals.ts index 97e54bb02e..21fd96a300 100644 --- a/packages/eslint-config/source/utils/no-restricted-globals.ts +++ b/packages/eslint-config/source/utils/no-restricted-globals.ts @@ -27,6 +27,7 @@ const GLOBALS_WHITELIST = new Set([ 'FileReader', // complicated due to typescript types 'FormData', 'Function', + 'globalThis', 'Intl', 'JSON', 'Map', From ee91977e964f093234140d2a83aa40d63c5f5283 Mon Sep 17 00:00:00 2001 From: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> Date: Mon, 18 Nov 2024 23:56:05 +0100 Subject: [PATCH 5/7] chore(documentation): Move Slots Below Props and Emits Co-Authored-By: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> --- packages/documentation/components/ComponentInfo.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/documentation/components/ComponentInfo.vue b/packages/documentation/components/ComponentInfo.vue index 594202344f..221357e7c6 100644 --- a/packages/documentation/components/ComponentInfo.vue +++ b/packages/documentation/components/ComponentInfo.vue @@ -62,7 +62,6 @@ - + + From 88a5e54b4722aee4ec804baa74538165aba17811 Mon Sep 17 00:00:00 2001 From: Florian Wendelborn <1133858+FlorianWendelborn@users.noreply.github.com> Date: Wed, 6 Nov 2024 23:10:56 +0100 Subject: [PATCH 6/7] feature(KtToaster): Re-implement KtToaster and KtBanner with Support for TypeScript, and A New Design, and API Co-Authored-By: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> --- eslint.config.mjs | 1 + internals/fake-root/package.json | 2 +- .../documentation/assets/img/banner_alert.png | Bin 41999 -> 0 bytes .../assets/img/banner_expand.png | Bin 108494 -> 0 bytes .../documentation/components/ColorPalette.vue | 23 +- .../documentation/components/MyToaster.vue | 37 ++ .../documentation/components/YocoPreview.vue | 25 +- packages/documentation/layouts/default.vue | 3 + packages/documentation/layouts/empty.vue | 6 + packages/documentation/layouts/fullpage.vue | 3 + .../documentation/pages/examples/layouts.vue | 4 +- .../pages/usage/components/banner.vue | 246 +++++---- .../pages/usage/components/button.vue | 66 ++- .../usage/components/field-inline-edit.vue | 4 +- .../pages/usage/components/form-fields.vue | 16 +- .../pages/usage/components/form.vue | 4 +- .../pages/usage/components/heading.vue | 4 +- .../pages/usage/components/line.vue | 10 +- .../pages/usage/components/popover.vue | 4 +- .../pages/usage/components/table-legacy.vue | 11 +- .../pages/usage/components/toaster.vue | 453 ++++++++++++++-- packages/documentation/styles/main.scss | 10 - packages/documentation/utilities/pages.ts | 8 +- packages/documentation/utilities/toaster.ts | 53 ++ packages/kotti-ui/package.json | 2 +- packages/kotti-ui/source/index.ts | 22 +- .../kotti-ui/source/kotti-banner/KtBanner.vue | 215 ++++++-- .../kotti-ui/source/kotti-banner/index.ts | 20 +- .../kotti-ui/source/kotti-banner/types.ts | 31 +- .../source/kotti-i18n/locales/de-DE.ts | 4 - .../source/kotti-i18n/locales/en-US.ts | 4 - .../source/kotti-i18n/locales/es-ES.ts | 4 - .../source/kotti-i18n/locales/fr-FR.ts | 4 - .../source/kotti-i18n/locales/ja-JP.ts | 4 - packages/kotti-ui/source/kotti-i18n/types.ts | 2 - .../kotti-ui/source/kotti-style/tokens.css | 53 +- .../kotti-ui/source/kotti-toaster/KtToast.vue | 71 +++ .../source/kotti-toaster/KtToastProvider.vue | 27 + .../source/kotti-toaster/KtToaster.vue | 247 ++++----- .../kotti-ui/source/kotti-toaster/context.ts | 10 + .../source/kotti-toaster/create-deferred.ts | 30 ++ .../kotti-toaster/create-toaster.test.ts | 509 ++++++++++++++++++ .../source/kotti-toaster/create-toaster.ts | 504 +++++++++++++++++ .../kotti-ui/source/kotti-toaster/index.ts | 61 ++- .../kotti-ui/source/kotti-toaster/types.ts | 34 ++ .../source/kotti-toaster/utilities.js | 28 - packages/kotti-ui/source/locales/input.json | 4 - packages/kotti-ui/source/types/kotti.ts | 6 +- packages/kotti-ui/source/utilities.ts | 4 - packages/kotti-ui/tokens/colors.js | 69 ++- packages/kotti-ui/tokens/generate.js | 6 +- packages/kotti-ui/tokens/utilities.js | 2 +- yarn.lock | 10 +- 53 files changed, 2385 insertions(+), 595 deletions(-) delete mode 100644 packages/documentation/assets/img/banner_alert.png delete mode 100644 packages/documentation/assets/img/banner_expand.png create mode 100644 packages/documentation/components/MyToaster.vue create mode 100644 packages/documentation/utilities/toaster.ts create mode 100644 packages/kotti-ui/source/kotti-toaster/KtToast.vue create mode 100644 packages/kotti-ui/source/kotti-toaster/KtToastProvider.vue create mode 100644 packages/kotti-ui/source/kotti-toaster/context.ts create mode 100644 packages/kotti-ui/source/kotti-toaster/create-deferred.ts create mode 100644 packages/kotti-ui/source/kotti-toaster/create-toaster.test.ts create mode 100644 packages/kotti-ui/source/kotti-toaster/create-toaster.ts create mode 100644 packages/kotti-ui/source/kotti-toaster/types.ts delete mode 100644 packages/kotti-ui/source/kotti-toaster/utilities.js diff --git a/eslint.config.mjs b/eslint.config.mjs index 3dc58c8f99..3361c50f18 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -15,6 +15,7 @@ const trustedDependencies = new Set([ '@metatypes/typography', '@metatypes/units', 'filesize', + 'nanoid', 'zod', ]) diff --git a/internals/fake-root/package.json b/internals/fake-root/package.json index 995d6f93a5..35539ab84b 100644 --- a/internals/fake-root/package.json +++ b/internals/fake-root/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "check:eslint": "yarn --cwd ../.. run eslint --max-warnings=0 --ignore-pattern=internals --ignore-pattern=packages .", - "check:knip": "yarn --cwd ../.. run knip", + "check:knip": "yarn --cwd ../.. run knip --tags=-knipignore", "check:prettier": "yarn --cwd ../.. run prettier --check --ignore-path=.fake-prettierignore --ignore-path=.prettierignore .", "fix:eslint": "yarn run check:eslint --fix", "fix:prettier": "yarn run check:prettier --write" diff --git a/packages/documentation/assets/img/banner_alert.png b/packages/documentation/assets/img/banner_alert.png deleted file mode 100644 index c0318daad68a9c4c26b752b90264955a3373aa80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41999 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 diff --git a/packages/documentation/assets/img/banner_expand.png b/packages/documentation/assets/img/banner_expand.png deleted file mode 100644 index 8b30ff8ffde88b27598811aa0bc42602b01690ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108494 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 rbAVht=(nN%e$oHcgWqzy7j~PYM4J
- -
Copy successful
-
diff --git a/packages/documentation/components/YocoPreview.vue b/packages/documentation/components/YocoPreview.vue index 44211b3c38..1f5fa59951 100644 --- a/packages/documentation/components/YocoPreview.vue +++ b/packages/documentation/components/YocoPreview.vue @@ -18,22 +18,18 @@
Click to Copy
-
diff --git a/packages/documentation/layouts/fullpage.vue b/packages/documentation/layouts/fullpage.vue index 2f2d83405a..fe83529008 100644 --- a/packages/documentation/layouts/fullpage.vue +++ b/packages/documentation/layouts/fullpage.vue @@ -5,6 +5,7 @@
+ @@ -12,6 +13,7 @@ + + + + diff --git a/packages/kotti-ui/source/kotti-banner/index.ts b/packages/kotti-ui/source/kotti-banner/index.ts index 4c7118cbc8..3d87ec5335 100755 --- a/packages/kotti-ui/source/kotti-banner/index.ts +++ b/packages/kotti-ui/source/kotti-banner/index.ts @@ -9,11 +9,25 @@ export const KtBanner = attachMeta(makeInstallable(KtBannerVue), { deprecated: null, designs: { type: MetaDesignType.FIGMA, - url: 'https://www.figma.com/file/0yFVivSWXgFf2ddEF92zkf/Kotti-Design-System?node-id=1439%3A5', + url: 'https://www.figma.com/design/0yFVivSWXgFf2ddEF92zkf/Kotti-Design-System?node-id=7096-5539', }, slots: { - default: { - description: 'Content when Banner is expanded', + action: { + description: + 'Use this only if you need to implement a custom action button', + scope: null, + }, + footer: { + description: + 'Used to put e.g. buttons or other interactive elements at the bottom of the banner', + scope: null, + }, + header: { + description: 'Used to replace the optional header text', + scope: null, + }, + text: { + description: 'Used to replace the main text', scope: null, }, }, diff --git a/packages/kotti-ui/source/kotti-banner/types.ts b/packages/kotti-ui/source/kotti-banner/types.ts index 9ac31877d9..38c62a2b48 100644 --- a/packages/kotti-ui/source/kotti-banner/types.ts +++ b/packages/kotti-ui/source/kotti-banner/types.ts @@ -1,22 +1,29 @@ import { z } from 'zod' -import { Yoco, yocoIconSchema } from '@3yourmind/yoco' +import { yocoIconSchema } from '@3yourmind/yoco' export module KottiBanner { + export const styleSchema = z + .object({ + backgroundColor: z.string(), + darkColor: z.string(), + icon: yocoIconSchema.nullable(), + lightColor: z.string(), + }) + .strict() + + export type Style = z.infer + export const propsSchema = z.object({ - actionText: z.string().nullable().default(null), - expandCloseLabel: z.string().nullable().default(null), - expandLabel: z.string().nullable().default(null), - icon: yocoIconSchema.default(Yoco.Icon.ANNOUNCE), - isGray: z.boolean().default(false), - message: z.string(), + action: z.string().nullable().default(null), + header: z.string().nullable().default(null), + isCloseable: z.boolean().default(false), + text: z.string().nullable().default(null), + type: z + .union([styleSchema, z.enum(['error', 'info', 'success', 'warning'])]) + .default('info'), }) export type Props = z.input export type PropsInternal = z.output - - export type Translations = { - expandCloseLabel: string - expandLabel: string - } } diff --git a/packages/kotti-ui/source/kotti-i18n/locales/de-DE.ts b/packages/kotti-ui/source/kotti-i18n/locales/de-DE.ts index b81b6c7767..f80ebb5d57 100644 --- a/packages/kotti-ui/source/kotti-i18n/locales/de-DE.ts +++ b/packages/kotti-ui/source/kotti-i18n/locales/de-DE.ts @@ -18,10 +18,6 @@ module Common { } export const deDE: KottiI18n.Messages = { - KtBanner: { - expandCloseLabel: 'Schließen', - expandLabel: 'Öffnen', - }, KtComment: { cancelMessage: 'Drücken Sie die Esc-Taste oder', clickToCancelLabel: 'klicken Sie zum Abbrechen', diff --git a/packages/kotti-ui/source/kotti-i18n/locales/en-US.ts b/packages/kotti-ui/source/kotti-i18n/locales/en-US.ts index ff4a75aece..49f3d388ec 100644 --- a/packages/kotti-ui/source/kotti-i18n/locales/en-US.ts +++ b/packages/kotti-ui/source/kotti-i18n/locales/en-US.ts @@ -18,10 +18,6 @@ module Common { } export const enUS: KottiI18n.Messages = { - KtBanner: { - expandCloseLabel: 'Close', - expandLabel: 'View', - }, KtComment: { cancelMessage: 'Press Esc key or', clickToCancelLabel: 'click to cancel', diff --git a/packages/kotti-ui/source/kotti-i18n/locales/es-ES.ts b/packages/kotti-ui/source/kotti-i18n/locales/es-ES.ts index 753b3e78d7..f6d19381f6 100644 --- a/packages/kotti-ui/source/kotti-i18n/locales/es-ES.ts +++ b/packages/kotti-ui/source/kotti-i18n/locales/es-ES.ts @@ -18,10 +18,6 @@ module Common { } export const esES: KottiI18n.Messages = { - KtBanner: { - expandCloseLabel: 'Cerrar', - expandLabel: 'Ver', - }, KtComment: { cancelMessage: 'Pulse la tecla Esc o', clickToCancelLabel: 'haga clic para cancelar', diff --git a/packages/kotti-ui/source/kotti-i18n/locales/fr-FR.ts b/packages/kotti-ui/source/kotti-i18n/locales/fr-FR.ts index 63ce56d7d6..603d6d627c 100644 --- a/packages/kotti-ui/source/kotti-i18n/locales/fr-FR.ts +++ b/packages/kotti-ui/source/kotti-i18n/locales/fr-FR.ts @@ -18,10 +18,6 @@ module Common { } export const frFR: KottiI18n.Messages = { - KtBanner: { - expandCloseLabel: 'Fermer', - expandLabel: 'Voir', - }, KtComment: { cancelMessage: 'Appuyez sur la touche Esc ou', clickToCancelLabel: 'cliquez pour annuler', diff --git a/packages/kotti-ui/source/kotti-i18n/locales/ja-JP.ts b/packages/kotti-ui/source/kotti-i18n/locales/ja-JP.ts index 8233d708a9..9f2d47486e 100644 --- a/packages/kotti-ui/source/kotti-i18n/locales/ja-JP.ts +++ b/packages/kotti-ui/source/kotti-i18n/locales/ja-JP.ts @@ -18,10 +18,6 @@ module Common { } export const jaJP: KottiI18n.Messages = { - KtBanner: { - expandCloseLabel: '閉じる', - expandLabel: '表示', - }, KtComment: { cancelMessage: 'Escキーを押すか', clickToCancelLabel: 'クリックしてキャンセルします', diff --git a/packages/kotti-ui/source/kotti-i18n/types.ts b/packages/kotti-ui/source/kotti-i18n/types.ts index 41a9dfea79..3668c3d9e4 100644 --- a/packages/kotti-ui/source/kotti-i18n/types.ts +++ b/packages/kotti-ui/source/kotti-i18n/types.ts @@ -1,6 +1,5 @@ import type { Ref } from 'vue' -import type { KottiBanner } from '../kotti-banner/types' import type { KottiComment } from '../kotti-comment/types' import type { KottiField } from '../kotti-field/types' import type { Shared as KottiFieldFileUploadShared } from '../kotti-field-file-upload/types' @@ -33,7 +32,6 @@ export module KottiI18n { } export type Messages = { - KtBanner: KottiBanner.Translations KtComment: KottiComment.Translations KtFieldFileUpload: KottiFieldFileUploadShared.Translations KtFieldInlineEdit: KottiFieldInlineEdit.Translations diff --git a/packages/kotti-ui/source/kotti-style/tokens.css b/packages/kotti-ui/source/kotti-style/tokens.css index 2263c27883..10d90363eb 100644 --- a/packages/kotti-ui/source/kotti-style/tokens.css +++ b/packages/kotti-ui/source/kotti-style/tokens.css @@ -5,9 +5,19 @@ */ :root { - --white: #fff; --black: #000; + --blue-10: #eaf0fa; + --blue-100: #0d244a; + --blue-20: #c1d7fb; + --blue-30: #afc5e8; + --blue-40: #6795e0; + --blue-50: #3173de; + --blue-60: #2c66c4; + --blue-70: #2659ab; + --blue-80: #1f55ad; + --blue-90: #153c7a; --gray-10: #f8f8f8; + --gray-100: #141414; --gray-20: #e0e0e0; --gray-30: #c6c6c6; --gray-40: #a8a8a8; @@ -16,8 +26,18 @@ --gray-70: #525252; --gray-80: #393939; --gray-90: #262626; - --gray-100: #141414; + --green-10: #e6f8d2; + --green-20: #c4e0a5; + --green-50: #71c716; + --green-60: #64ad13; + --green-70: #549410; + --orange-10: #fde2cb; + --orange-20: #fab980; + --orange-50: #ff9333; + --orange-60: #ff7800; + --orange-70: #ba6820; --primary-10: #eaf0fa; + --primary-100: #0d244a; --primary-20: #c1d7fb; --primary-30: #afc5e8; --primary-40: #6795e0; @@ -26,27 +46,20 @@ --primary-70: #2659ab; --primary-80: #1f55ad; --primary-90: #153c7a; - --primary-100: #0d244a; - --green-20: #c4e0a5; - --green-50: #71c716; - --green-60: #64ad13; - --green-70: #549410; - --red-20: #f0a8a8; - --red-50: #f21d1d; - --red-60: #d91919; - --red-70: #bf1717; --purple-20: #b995ca; --purple-50: #932dc2; --purple-60: #6c218f; --purple-70: #591b75; + --red-10: #fbe1e1; + --red-20: #f0a8a8; + --red-50: #f21d1d; + --red-60: #d91919; + --red-70: #bf1717; + --white: #fff; --yellow-20: #fff9c0; --yellow-50: #fff490; --yellow-60: #ffe60d; --yellow-70: #dfc903; - --orange-20: #fab980; - --orange-50: #ff9333; - --orange-60: #ff7800; - --orange-70: #ba6820; --ui-background: var(--white); --ui-01: var(--gray-10); --ui-02: var(--gray-20); @@ -76,15 +89,19 @@ --icon-02: var(--gray-50); --icon-03: var(--white); --support-error: var(--red-50); + --support-error-bg: var(--red-10); --support-error-dark: var(--red-70); --support-error-light: var(--red-20); --support-warning: var(--orange-50); + --support-warning-bg: var(--orange-10); --support-warning-dark: var(--orange-70); --support-warning-light: var(--orange-20); --support-success: var(--green-50); + --support-success-bg: var(--green-10); --support-success-dark: var(--green-70); --support-success-light: var(--green-20); - --support-info: var(--primary-50); - --support-info-dark: var(--primary-70); - --support-info-light: var(--primary-20); + --support-info: var(--blue-50); + --support-info-bg: var(--blue-10); + --support-info-dark: var(--blue-70); + --support-info-light: var(--blue-20); } diff --git a/packages/kotti-ui/source/kotti-toaster/KtToast.vue b/packages/kotti-ui/source/kotti-toaster/KtToast.vue new file mode 100644 index 0000000000..6227b902d0 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/KtToast.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/packages/kotti-ui/source/kotti-toaster/KtToastProvider.vue b/packages/kotti-ui/source/kotti-toaster/KtToastProvider.vue new file mode 100644 index 0000000000..48c02edb45 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/KtToastProvider.vue @@ -0,0 +1,27 @@ + + + diff --git a/packages/kotti-ui/source/kotti-toaster/KtToaster.vue b/packages/kotti-ui/source/kotti-toaster/KtToaster.vue index 8fb243dcaf..9ade381efa 100644 --- a/packages/kotti-ui/source/kotti-toaster/KtToaster.vue +++ b/packages/kotti-ui/source/kotti-toaster/KtToaster.vue @@ -1,167 +1,132 @@ - + + + diff --git a/packages/kotti-ui/source/kotti-toaster/context.ts b/packages/kotti-ui/source/kotti-toaster/context.ts new file mode 100644 index 0000000000..5d1ec3a273 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/context.ts @@ -0,0 +1,10 @@ +import type { ComputedRef } from 'vue' + +export type ToastContext = ComputedRef<{ + delete: () => void + header: string | null + progress: number | null + text: string +}> + +export const TOAST_CONTEXT = Symbol('TOAST_CONTEXT') diff --git a/packages/kotti-ui/source/kotti-toaster/create-deferred.ts b/packages/kotti-ui/source/kotti-toaster/create-deferred.ts new file mode 100644 index 0000000000..7a19b92169 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/create-deferred.ts @@ -0,0 +1,30 @@ +/** + * Creates a deferred promise, useful in scenarios where a promise needs to be created and + * resolved or rejected from an external context. This exposes `resolve` and `reject` functions, + * allowing external control over the promise's resolution state. + * + * @throws {Error} Throws an error if the promise's `resolve` or `reject` functions could not be initialized (which shouldn't occur under typical JavaScript execution). + */ +export const createDeferred = (): { + promise: Promise + reject: (arg: unknown) => void + resolve: (res: PROMISE_RESOLUTION_TYPE) => void +} => { + let resolve: ((res: PROMISE_RESOLUTION_TYPE) => void) | null = null + let reject: ((arg: unknown) => void) | null = null + + const promise = new Promise((res, rej) => { + resolve = res + reject = rej + }) + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (resolve === null || reject === null) + throw new Error('could not create deferred promise') + + return { + promise, + reject, + resolve, + } +} diff --git a/packages/kotti-ui/source/kotti-toaster/create-toaster.test.ts b/packages/kotti-ui/source/kotti-toaster/create-toaster.test.ts new file mode 100644 index 0000000000..f46e707872 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/create-toaster.test.ts @@ -0,0 +1,509 @@ +import { describe, expect, it, vitest } from 'vitest' + +import { createToaster } from './create-toaster' + +const DEBUG: boolean = false + +const createAnimationFrameMock = () => { + let interval: Timer | null = null + return { + getIsRunning: () => interval !== null, + start: (update: () => void) => { + if (interval) + throw new Error( + 'Could not start animation frame, already running. This is likely a bug.', + ) + + if (DEBUG) console.log('animation-frame-mock: start') + interval = globalThis.setInterval(() => { + if (DEBUG) console.log('animation-frame-mock: update') + update() + }, 5) + }, + stop: () => { + if (DEBUG) console.log('animation-frame-mock: stop') + if (interval) { + globalThis.clearInterval(interval) + interval = null + } + }, + } +} + +describe('createToaster', () => { + it('returns things', () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + + expect(toaster).toEqual({ + _internal_pls_dont_touch: expect.anything(), + abort: expect.anything(), + show: expect.anything(), + withOptions: expect.anything(), + }) + }) + + describe('.abort()', () => { + it('can abort a toast', async () => { + const toaster = createToaster() + + const toast = toaster.show({ duration: 1, text: 'test' }) + expect(() => { + toaster.abort(toast.metadata.id) + }).not.toThrow() + expect(toast.metadata.abortController.signal.aborted).toBe(true) + await expect(toast.done).rejects.toThrow('INTERNAL_ABORT') + }) + + it('cannot abort an aborted toast', async () => { + const toaster = createToaster() + + const toast = toaster.show({ duration: 1, text: 'test' }) + expect(() => { + toaster.abort(toast.metadata.id) + }).not.toThrow() + expect(toast.metadata.abortController.signal.aborted).toBe(true) + await expect(toast.done).rejects.toThrow('INTERNAL_ABORT') + expect(() => { + toaster.abort(toast.metadata.id) + }).toThrow() + }) + + it('cannot abort an already toasted toast', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + + const toast = toaster.show({ duration: 1, text: 'test' }) + await expect(toast.done).resolves.toBe('deleted') + expect(() => { + toaster.abort(toast.metadata.id) + }).toThrow() + }) + + it('throws for unknown toasts', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ duration: 1, text: 'test' }) + expect(() => { + toaster.abort('not-a-real-toast') + }).toThrow( + 'could not find toast in fifoToasterQueue with id “not-a-real-toast”', + ) + expect(toast.metadata.abortController.signal.aborted).toBe(false) + await expect(toast.done).resolves.toBe('deleted') + }) + }) + + describe('.withOptions()', () => { + it('can create a customized show function', () => { + const toaster = createToaster() + const show = toaster.withOptions({ + duration: 3000, + }) + expect(show).toBeInstanceOf(Function) + }) + + it('can call customized show function', () => { + const toaster = createToaster() + const show = toaster.withOptions({ + duration: 3000, + }) + expect(() => show({ duration: 1, text: 'some text' })).not.toThrowError() + }) + }) + + describe('.show()', () => { + it('can push', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ duration: 1, text: 'example toast' }) + + expect(toast.text).toBe('example toast') + await expect(toast.done).resolves.toBe('deleted') + }) + + it('correctly handles durations', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + + const wait = (ms: number) => + new Promise((_resolve, reject) => { + globalThis.setTimeout(() => { + reject(new Error(`timeout after ${ms}ms`)) + }, ms) + }) + + const fastToast = toaster.show({ duration: 1, text: 'fast toast' }) + await expect(Promise.race([fastToast.done, wait(10)])).resolves.toBe( + 'deleted', + ) + + const slowToast = toaster.show({ duration: 100, text: 'slow toast' }) + await expect(Promise.race([slowToast.done, wait(200)])).resolves.toBe( + 'deleted', + ) + + const superSlowToast = toaster.show({ + duration: 500, + text: 'super slow toast', + }) + await expect( + Promise.race([superSlowToast.done, wait(200)]), + ).rejects.toThrow('timeout') + }) + + it('can push custom data', async () => { + const custom = { testing: true } + + const toaster = createToaster<{ + default: Record + test: { testing: boolean } + }>({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ + custom, + duration: 1, + text: 'example toast', + type: 'test', + }) + + expect(toast.custom).toEqual(custom) + await expect(toast.done).resolves.toBe('deleted') + }) + + it('can push with metadata.id', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ + duration: 1, + metadata: { id: 'foo' }, + text: 'example toast', + }) + + expect(toast.metadata.id).toEqual('foo') + await expect(toast.done).resolves.toBe('deleted') + }) + + it('can push with metadata.abortController', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + const abortController = new globalThis.AbortController() + const toast = toaster.show({ + duration: 1, + metadata: { abortController }, + text: 'example toast', + }) + + expect(toast.metadata.abortController).toBe(abortController) + expect(() => { + toast.abort() + }).not.toThrow() + expect(abortController.signal.aborted).toBe(true) + await expect(toast.done).rejects.toThrow('INTERNAL_ABORT') + }) + + describe('returns', () => { + it('.abort()', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ duration: 1, text: '42' }) + + expect(toast.metadata.abortController.signal.aborted).toBe(false) + toast.abort() + expect(toast.metadata.abortController.signal.aborted).toBe(true) + await expect(toast.done).rejects.toThrow('INTERNAL_ABORT') + }) + + it('supports await toast.done', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + const toast = toaster.show({ duration: 10, text: '42' }) + + await expect(toast.done).resolves.toBe('deleted') + }) + }) + }) + + describe('._internal_pls_dont_touch', () => { + describe('.requestDelete()', () => { + it('deletes a toast', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + toaster._internal_pls_dont_touch.subscribe(() => {}) + + let testPromiseIsDone = false + + const toast = toaster.show({ text: 'test' }) + + void toast.done.then(() => { + testPromiseIsDone = true + }) + + expect(testPromiseIsDone).toBe(false) + toaster._internal_pls_dont_touch.requestDelete(toast.metadata.id) + await new Promise((res) => globalThis.setTimeout(res, 1)) + expect(testPromiseIsDone).toBe(true) + }) + }) + + describe('.subscribe()', () => { + it('can subscribe', () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + const handler = vitest.fn() + + toaster._internal_pls_dont_touch.subscribe(handler) + + expect(handler.mock.calls).toEqual([[[]]]) + toaster.show({ text: 'test' }) + expect(handler.mock.calls).toEqual([[[]], [[expect.anything()]]]) + }) + + it('correctly handles old toasts upon subscribing', () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + const handler = vitest.fn() + + toaster.show({ text: 'test' }) + + expect(handler.mock.calls).toEqual([]) + toaster._internal_pls_dont_touch.subscribe(handler) + expect(handler.mock.calls).toEqual([ + [ + [ + { + custom: {}, + duration: null, + header: null, + metadata: expect.anything(), + progress: null, + text: 'test', + type: 'default', + }, + ], + ], + ]) + }) + + it('prevents multiple simultaneous subscriptions', () => { + const toaster = createToaster() + const handler = () => {} + + expect(() => { + toaster._internal_pls_dont_touch.subscribe(handler) + }).not.toThrow() + + expect(() => { + toaster._internal_pls_dont_touch.subscribe(handler) + }).toThrow('toaster already has a subscriber') + }) + + it('receives messages in FIFO order', async () => { + const toaster = createToaster({ + animationFrame: createAnimationFrameMock(), + }) + const handler = vitest.fn() + + const toast1 = toaster.show({ duration: 50, text: 'test' }) + const toast2 = toaster.show({ duration: 50, text: 'test 2' }) + + expect(handler.mock.calls).toEqual([]) + toaster._internal_pls_dont_touch.subscribe(handler) + expect(handler.mock.lastCall![0][0]).toMatchObject({ text: 'test' }) + expect(handler.mock.lastCall![0][1]).toMatchObject({ text: 'test 2' }) + + await Promise.all([toast1.done, toast2.done]) + + expect(handler.mock.lastCall).toEqual([[]]) + + const toast3 = toaster.show({ duration: 50, text: 'test 3' }) + expect(handler.mock.lastCall![0][0]).toMatchObject({ text: 'test 3' }) + + await toast3.done + expect(handler.mock.lastCall).toEqual([[]]) + }) + }) + + describe('.unsubscribe()', () => { + it('can unsubscribe', () => { + const toaster = createToaster() + const handler = vitest.fn() + + toaster._internal_pls_dont_touch.subscribe(handler) + toaster._internal_pls_dont_touch.unsubscribe() + + expect(handler.mock.calls).toEqual([[[]]]) + toaster.show({ text: 'test' }) + expect(handler.mock.calls).toEqual([[[]]]) + }) + + it('throws when unsubscribe without a subscription', () => { + const toaster = createToaster() + + expect(() => { + toaster._internal_pls_dont_touch.unsubscribe() + }).toThrow('toaster currently has no subscriber') + }) + }) + }) +}) + +// type-level tests +// HACK: These tests don’t actually need to be run, they work by letting tsc report any type errors +const doNotRun = () => { + const toaster = createToaster<{ + default: Record + error: { error: 'error' } + }>() + + // @ts-expect-error wrong, can not pass arbitrary arguments + toaster.withOptions({ + any: 'thing', + type: 'error', + })({ + custom: { error: 'error' }, + text: 'wow', + }) + + // @ts-expect-error wrong, text is not allowed + toaster.withOptions({ text: 'something' }) + + // @ts-expect-error wrong, custom is not supported in withOptions + toaster.withOptions({ custom: {}, type: 'default' })({ + // @ts-expect-error wrong, overriding types is not supported in withOptions + custom: { error: 'error' }, + text: 'error', + // @ts-expect-error wrong, overriding types is not supported in withOptions + type: 'error', + }) + + // @ts-expect-error wrong, custom should be empty + toaster.withOptions({ custom: {}, type: 'default' })({ text: 'wow' }) + + // @ts-expect-error wrong, custom should not be empty + toaster.withOptions({ + custom: {}, + type: 'error', + }) + + toaster.withOptions({ type: 'default' })({ text: 'wow' }) + toaster.withOptions({ type: 'default' })({ custom: {}, text: 'wow' }) + + // @ts-expect-error wrong, can not override type + toaster.withOptions({ type: 'error' })({ + custom: { + error: 'error', + }, + text: 'wow', + type: 'default', + }) + + toaster.withOptions({ type: 'error' })({ + // @ts-expect-error wrong, custom should not be empty + custom: {}, + text: 'wow', + }) + + toaster.withOptions({ type: 'error' })({ + custom: { error: 'error' }, + text: 'wow', + }) + toaster.withOptions({ + duration: 5000, + type: 'error', + })({ + custom: { error: 'error' }, + duration: 6000, + text: 'wow', + }) + + // @ts-expect-error wrong, text was not provided + toaster.withOptions({ type: 'default' })({ + duration: 4000, + }) + + // @ts-expect-error wrong, custom was not provided + toaster.withOptions({ type: 'error' })({ + text: 'wow', + }) + + // @ts-expect-error wrong, text was not provided + toaster.withOptions({ type: 'error' })({ + custom: { error: 'error' }, + }) + + toaster.withOptions({ type: 'default' })({ + // @ts-expect-error wrong, can not override type + custom: { error: 'error' }, + text: 'wow', + // @ts-expect-error wrong, can not override type + type: 'error', + }) + + // @ts-expect-error wrong, custom should not be empty + toaster.withOptions({ duration: 5000 })({ + custom: {}, // wrong + text: 'wow', + type: 'error', + }) + + toaster.withOptions({ duration: 5000 })({ + // @ts-expect-error wrong, custom should be empty + custom: { error: 'error' }, + text: 'wow', + type: 'default', + }) + + toaster.withOptions({ duration: 5000 })({ + custom: { error: 'error' }, + text: 'wow', + type: 'error', + }) + + // return types + + const myToaster = createToaster<{ + default: Record + error: { error: 'error' } + success: { success: 'success' } + }>() + + const res1 = myToaster.show({ + custom: { + error: 'error', + key: true, // error + }, + text: 'wow', + type: 'error', + }) + + // @ts-expect-error expected type test failurue, should only allow toast1.custom.success + res1.custom.success + res1.custom.error + + res1.metadata +} + +// make linters happy +if (Math.random() > 2) doNotRun() diff --git a/packages/kotti-ui/source/kotti-toaster/create-toaster.ts b/packages/kotti-ui/source/kotti-toaster/create-toaster.ts new file mode 100644 index 0000000000..ca09711842 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/create-toaster.ts @@ -0,0 +1,504 @@ +import { nanoid } from 'nanoid' +import { z } from 'zod' + +import { createDeferred } from './create-deferred' + +const customSchema = z.record(z.unknown()) + +const durationSchema = z.number().int().finite().positive().nullable() + +const metadataSchema = z + .object({ + abortController: z.instanceof(globalThis.AbortController), + id: z.string(), + }) + .strict() + +const queuedToastSchema = z + .object({ + custom: customSchema, + deferred: z + .object({ + promise: z.promise(z.literal('deleted')), + reject: z.function().args(z.unknown()).returns(z.void()), + resolve: z.function().args(z.literal('deleted')).returns(z.void()), + }) + .strict(), + duration: durationSchema, + header: z.string().nullable(), + metadata: metadataSchema, + text: z.string(), + type: z.string(), + }) + .strict() + +export type QueuedToast = z.output + +const renderedMessageSchema = z + .object({ + custom: customSchema, + duration: z.number().positive().finite().nullable(), + header: z.string().nullable(), + metadata: metadataSchema, + progress: z.number().min(0).max(1).nullable(), + text: z.string(), + type: z.string(), + }) + .strict() + +export type RenderedMessage = z.output + +const messageSchema = z + .object({ + custom: customSchema.default(() => ({})), + duration: durationSchema.default(null), + header: z.string().nullable().default(null), + metadata: z + .object({ + abortController: z + .instanceof(globalThis.AbortController) + .default(() => new globalThis.AbortController()), + id: z.string().default(nanoid), + }) + .strict() + .default(() => ({})), + text: z.string(), + type: z.string().default('default'), + }) + .strict() + +const subscribeHandlerSchema = z + .function() + .args(z.array(renderedMessageSchema)) + .returns(z.union([z.promise(z.void()), z.void()])) + +type SubscribeHandler = z.output + +// utilties + +type IsEmptyObject = T extends Record ? true : false + +// messages + +type MessageTypes = { + [key: string]: Record + default: Record +} + +type Messages = { + [TYPE in keyof MESSAGE_TYPES]: Omit< + z.input, + 'custom' | 'type' + > & + (IsEmptyObject extends true + ? { custom?: MESSAGE_TYPES[TYPE] } + : { custom: MESSAGE_TYPES[TYPE] }) & + (TYPE extends 'default' ? { type?: 'default' } : { type: TYPE }) +} + +type MessagesNoDefault = { + [KEY in keyof MESSAGE_TYPES]: { + duration?: number | null + header?: string | null + text: string + type: KEY + } & (IsEmptyObject extends true + ? { custom?: MESSAGE_TYPES[KEY] } + : { custom: MESSAGE_TYPES[KEY] }) +} + +// show etc. + +type ShowResult< + MESSAGE_TYPES extends MessageTypes, + TYPE extends keyof MESSAGE_TYPES, +> = { + abort: () => void + custom: MESSAGE_TYPES[TYPE] + done: Promise<'deleted'> + header: string | null + metadata: z.output + text: string +} + +type Show = < + MESSAGE extends Messages[keyof MESSAGE_TYPES & string], +>( + message: Exclude< + keyof MESSAGE, + keyof Messages[keyof MESSAGE_TYPES & string] + > extends never + ? MESSAGE + : never, +) => ShowResult< + MESSAGE_TYPES, + MESSAGE extends { type: infer TYPE } ? TYPE : 'default' +> + +type WithInferredOptions< + MESSAGE_TYPES extends MessageTypes, + OPTIONS extends { + duration?: number | null + type?: keyof MESSAGE_TYPES + }, +> = OPTIONS extends { + duration?: number | null + type: infer TYPE extends keyof MESSAGE_TYPES +} + ? + | MessagesNoDefault[TYPE] + | Omit[TYPE], 'type'> + : Messages[keyof MESSAGE_TYPES] + +type WithOptions = < + BASE_OPTIONS extends { + duration?: number | null + type?: keyof MESSAGE_TYPES + }, +>( + baseOptions: Exclude extends never + ? BASE_OPTIONS + : `Argument "${Exclude}" is not supported`, +) => >( + options: Exclude< + keyof OPTIONS, + keyof WithInferredOptions + > extends never + ? OPTIONS + : `Argument "${Exclude}" is not supported`, +) => ShowResult< + MESSAGE_TYPES, + BASE_OPTIONS & OPTIONS extends { + type: infer TYPE extends keyof MESSAGE_TYPES + } + ? TYPE + : 'default' +> + +export type ToasterReturn = { + abort: (toastId: string) => void + show: Show + withOptions: WithOptions + + // internal + _internal_pls_dont_touch: { + requestDelete: (toastId: string) => void + subscribe: (handler: z.output) => void + unsubscribe: () => void + } +} + +const createToasterOptions = z + .object({ + animationFrame: z + .object({ + getIsRunning: z.function().args().returns(z.boolean()), + start: z + .function() + .args(z.function().args().returns(z.void())) + .returns(z.void()), + stop: z.function().args().returns(z.void()), + }) + .strict() + .default(() => { + let animationFrameId: number | null = null + return { + getIsRunning: () => animationFrameId !== null, + start: (update) => { + const animate = () => { + // Leave console log for now, so issues with the toaster have a chance to be detected + // eslint-disable-next-line no-console + console.log('create-toaster: update') + animationFrameId = globalThis.requestAnimationFrame(animate) + update() + } + animationFrameId = globalThis.requestAnimationFrame(animate) + }, + stop: () => { + if (animationFrameId) { + globalThis.cancelAnimationFrame(animationFrameId) + animationFrameId = null + } + }, + } + }), + // eslint-disable-next-line no-magic-numbers + numberOfToasts: z.number().int().positive().finite().default(3), + }) + .strict() + .default(() => ({})) + +type CreateToasterOptions = z.input + +type ActiveToast = { + beginTime: number + endTime: number | null + message: QueuedToast + progress: number | null +} + +const INTERNAL_ABORT = 'INTERNAL_ABORT' + +const calculateProgress = (start: number, now: number, end: number): number => { + const unclamped = (now - start) / (end - start) + return Math.max(Math.min(unclamped, 1), 0) +} + +// --------------------------------------------------------------- // +// --------------------------------------------------------------- // +// -- Begin of implementation ------------------------------------ // +// --------------------------------------------------------------- // +// --------------------------------------------------------------- // + +export const createToaster = < + MESSAGE_TYPES extends MessageTypes = { default: Record }, +>( + _options: CreateToasterOptions = {}, +): ToasterReturn => { + const options = createToasterOptions.parse(_options) + + const fifoToasterQueue: Array = [] + const activeToasts: Array = [] + + let subscriber: SubscribeHandler | null = null + const notifySubscriber = () => { + if (subscriber === null) return + + void subscriber( + activeToasts.map((toast) => ({ + custom: toast.message.custom, + duration: toast.message.duration, + header: toast.message.header, + metadata: toast.message.metadata, + progress: toast.progress, + text: toast.message.text, + type: toast.message.type, + })), + ) + } + + const deleteToastFromActiveToasts = (toastId: string) => { + const index = activeToasts.findIndex( + (toast) => toast.message.metadata.id === toastId, + ) + if (index === -1) + throw new Error( + `could not find toast in activeToasts with id “${toastId}”`, + ) + + const removedToast = activeToasts.splice(index, 1)[0] + + if (!removedToast) + throw new Error( + `could not find toast in activeToasts with id “${toastId}”`, + ) + + notifySubscriber() + return removedToast.message + } + + const deleteToastFromFifoQueue = (toastId: string) => { + const index = fifoToasterQueue.findIndex( + (toast) => toast.metadata.id === toastId, + ) + if (index === -1) + throw new Error( + `could not find toast in fifoToasterQueue with id “${toastId}”`, + ) + + const removedToast = fifoToasterQueue.splice(index, 1)[0] + + if (!removedToast) + throw new Error( + `could not find toast in fifoToasterQueue with id “${toastId}”`, + ) + + return removedToast + } + + const deleteAndAbortToast = (mode: 'abort' | 'delete', toastId: string) => { + const removedToast = activeToasts.some( + (toast) => toast.message.metadata.id === toastId, + ) + ? deleteToastFromActiveToasts(toastId) + : deleteToastFromFifoQueue(toastId) + + switch (mode) { + case 'abort': { + const { abortController } = removedToast.metadata + + if (!abortController.signal.aborted) { + abortController.abort(INTERNAL_ABORT) + } + + removedToast.deferred.reject( + abortController.signal.aborted + ? abortController.signal.reason + : 'aborted', + ) + break + } + case 'delete': { + removedToast.deferred.resolve('deleted') + break + } + } + } + + /** + * Updates the list of active toasts, managing their display duration and progress. + * + * - If a toast has an `endTime`, it calculates its progress based on the current time. + * - If a toast's progress reaches 100%, it is deleted and resolved. + * - If there is room for more toasts, it moves items from the `fifoToasterQueue` to `activeToasts`. + * - Manages the animation frame, starting or stopping it based on whether there are active toasts. + * - Notifies the subscriber if the state of `activeToasts` changes. + */ + const updateActiveToasts = (_dirty = false) => { + if (subscriber === null) return + let dirty = _dirty + + let index = 0 + while (index < activeToasts.length) { + const toast = activeToasts[index] as ActiveToast + + if (toast.endTime === null) { + index++ + continue + } + + toast.progress = calculateProgress( + toast.beginTime, + Date.now(), + toast.endTime, + ) + dirty = true + + if (toast.progress >= 1) { + deleteAndAbortToast('delete', toast.message.metadata.id) + continue + } + index++ + } + + while (activeToasts.length < options.numberOfToasts) { + const message = fifoToasterQueue.shift() ?? null + if (message === null) break + + activeToasts.push({ + beginTime: Date.now(), + endTime: message.duration ? Date.now() + message.duration : null, + message, + progress: message.duration ? 0 : null, + }) + dirty = true + } + + const isRunning = options.animationFrame.getIsRunning() + const isNowEmpty = activeToasts.length === 0 + + if (!isRunning && !isNowEmpty) { + options.animationFrame.start(() => { + updateActiveToasts() + }) + } else if (isRunning && isNowEmpty) { + options.animationFrame.stop() + } + + if (dirty) notifySubscriber() + } + + const show: Show = < + MESSAGE, + TYPE extends keyof MESSAGE_TYPES = MESSAGE extends { + type: infer TYPE extends keyof MESSAGE_TYPES + } + ? TYPE + : 'default', + >( + message: MESSAGE, + ) => { + const options = messageSchema.parse(message) + + const doneDeferred = createDeferred<'deleted'>() + const { signal } = options.metadata.abortController + + signal.addEventListener('abort', () => { + if (signal.reason !== INTERNAL_ABORT) + deleteAndAbortToast('abort', options.metadata.id) + }) + + fifoToasterQueue.push({ + custom: options.custom, + deferred: doneDeferred, + duration: options.duration, + header: options.header, + metadata: options.metadata, + text: options.text, + type: options.type, + }) + + updateActiveToasts() + + return { + abort: () => { + deleteAndAbortToast('abort', options.metadata.id) + }, + custom: options.custom as MESSAGE_TYPES[TYPE], + done: doneDeferred.promise, + header: options.header, + metadata: options.metadata, + text: options.text, + type: options.type as TYPE, + } + } + + return { + abort: (toastId: string) => { + deleteAndAbortToast('abort', toastId) + }, + show, + withOptions: (baseOptions) => (options) => + show({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...(baseOptions as any), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...(options as any), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }) as any, + /** + * The methods in here expose the toasts from `activeToasts` to a single subscriber. + * Toasts from `fifoToasterQueue` are kept private. + * + * The subscriber: + * - gets updated whenever `activeToasts` gets mutated + * - can delete a specific toast by id + */ + _internal_pls_dont_touch: { + requestDelete: (deleteId) => { + deleteAndAbortToast('delete', deleteId) + updateActiveToasts(true) + }, + subscribe: (handler) => { + if (subscriber) + throw new Error( + 'create-toaster: toaster already has a subscriber, aborting', + ) + + subscriber = handler + + updateActiveToasts(true) + }, + unsubscribe: () => { + if (!subscriber) + throw new Error( + 'create-toaster: toaster currently has no subscriber, aborting', + ) + + options.animationFrame.stop() + + subscriber = null + }, + }, + } +} diff --git a/packages/kotti-ui/source/kotti-toaster/index.ts b/packages/kotti-ui/source/kotti-toaster/index.ts index 55c8ddd7ab..f5c91bf0ad 100644 --- a/packages/kotti-ui/source/kotti-toaster/index.ts +++ b/packages/kotti-ui/source/kotti-toaster/index.ts @@ -1,15 +1,68 @@ import { MetaDesignType } from '../types/kotti' import { attachMeta, makeInstallable } from '../utilities' +import KtToastVue from './KtToast.vue' import KtToasterVue from './KtToaster.vue' +import { KottiToast, KottiToaster } from './types' + +export { createToaster } from './create-toaster' export const KtToaster = attachMeta(makeInstallable(KtToasterVue), { - addedVersion: '1.0.0', + addedVersion: '8.0.0', deprecated: null, designs: { type: MetaDesignType.FIGMA, - url: 'https://www.figma.com/file/0yFVivSWXgFf2ddEF92zkf/Kotti-Design-System?node-id=128%3A2082', + url: 'https://www.figma.com/design/0yFVivSWXgFf2ddEF92zkf/Kotti-Design-System?node-id=6671-10835', + }, + slots: { + default: { + description: + 'Slots for all message types exist, with default being the fallback', + scope: { + custom: { description: 'Custom data object', type: 'object' }, + delete: { description: 'Deletes the toast', type: 'function' }, + duration: { + description: + 'Total toasting duration in ms, null for persistent toasts', + type: 'integer', + }, + header: { description: 'Optional header text', type: 'string' }, + progress: { description: 'Lifecycle progress (0–1)', type: 'float' }, + text: { description: 'Main text content', type: 'string' }, + type: { description: 'Toast type', type: 'string' }, + }, + }, + }, + typeScript: { + namespace: 'KottiToaster', + schema: KottiToaster.propsSchema, + }, +}) + +export const KtToast = attachMeta(makeInstallable(KtToastVue), { + addedVersion: '8.0.0', + deprecated: null, + designs: { + type: MetaDesignType.FIGMA, + url: 'https://www.figma.com/design/0yFVivSWXgFf2ddEF92zkf/Kotti-Design-System?node-id=6671-10835', + }, + slots: { + actions: { + description: + 'Used to put e.g. buttons or other interactive elements at the bottom of the toast', + scope: null, + }, + header: { + description: 'Used to replace the optional header text', + scope: null, + }, + text: { + description: 'Used to replace the main text', + scope: null, + }, + }, + typeScript: { + namespace: 'KottiToast', + schema: KottiToast.propsSchema, }, - slots: {}, - typeScript: null, }) diff --git a/packages/kotti-ui/source/kotti-toaster/types.ts b/packages/kotti-ui/source/kotti-toaster/types.ts new file mode 100644 index 0000000000..abd5578139 --- /dev/null +++ b/packages/kotti-ui/source/kotti-toaster/types.ts @@ -0,0 +1,34 @@ +import { z } from 'zod' + +import { KottiBanner } from '../kotti-banner/types' + +export module KottiToaster { + export const propsSchema = z.object({ + toaster: z.object({ + _internal_pls_dont_touch: z.object({}).passthrough(), + abort: z.function(), + show: z.function(), + withOptions: z.function(), + }), + }) + + export type Props = z.input + export type PropsInternal = z.output +} + +export module KottiToast { + export const propsSchema = z.object({ + header: z.string().nullable().default(null), + progress: z.number().int().finite().positive().nullable().default(null), + text: z.string().nullable().default(null), + type: z + .union([ + KottiBanner.styleSchema, + z.enum(['error', 'info', 'success', 'warning']), + ]) + .default('info'), + }) + + export type Props = z.input + export type PropsInternal = z.output +} diff --git a/packages/kotti-ui/source/kotti-toaster/utilities.js b/packages/kotti-ui/source/kotti-toaster/utilities.js deleted file mode 100644 index 3dec4101e5..0000000000 --- a/packages/kotti-ui/source/kotti-toaster/utilities.js +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable no-magic-numbers */ -/** - * @description generates a random id - * @param {Number} ID_BITS id entropy in bits, defaults to 64 (4 words) - * @returns {String} random id - */ -export const generateId = (ID_BITS = 64) => { - const randomWord = () => - Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1) - - const result = [] - - for (let i = 0; i < ID_BITS; i += 16) result.push(randomWord()) - - return result.join('') -} - -/** - * @description curried function that filters all ids that don't match a given id - * @param {String} $0.id first id - * @returns {Function} compares id1 to passed id - */ -export const notId = - ({ id: id1 }) => - ({ id: id2 }) => - id1 !== id2 diff --git a/packages/kotti-ui/source/locales/input.json b/packages/kotti-ui/source/locales/input.json index 07acefe9b4..b4b77870d3 100644 --- a/packages/kotti-ui/source/locales/input.json +++ b/packages/kotti-ui/source/locales/input.json @@ -9,10 +9,6 @@ "lessThanOrEqual": "is less than or equal to", "restrictedAccess": "Restricted access" }, - "ktBanner": { - "expandCloseLabel": "Close", - "expandLabel": "View" - }, "ktComment": { "cancelMessage": "Press Esc key or", "clickToCancelLabel": "click to cancel", diff --git a/packages/kotti-ui/source/types/kotti.ts b/packages/kotti-ui/source/types/kotti.ts index 4c5a3d3f68..e4b6734984 100644 --- a/packages/kotti-ui/source/types/kotti.ts +++ b/packages/kotti-ui/source/types/kotti.ts @@ -67,6 +67,10 @@ export { KottiPopover as Popover } from '../kotti-popover/types' export { KottiRow as Row } from '../kotti-row/types' export { KottiTableLegacy as TableLegacy } from '../kotti-table-legacy/types' export { KottiTag as Tag } from '../kotti-tag/types' +export { + KottiToast as Toast, + KottiToaster as Toaster, +} from '../kotti-toaster/types' export { KottiUserMenu as UserMenu } from '../kotti-user-menu/types' export { KottiValueLabel as ValueLabel } from '../kotti-value-label/types' export * from './decimal-separator' @@ -103,7 +107,7 @@ export type Meta = { string, { description: string | null - type: 'function' | 'integer' | 'object' + type: 'float' | 'function' | 'integer' | 'object' | 'string' } > | null } diff --git a/packages/kotti-ui/source/utilities.ts b/packages/kotti-ui/source/utilities.ts index c0a8185ca8..1450ed8d59 100644 --- a/packages/kotti-ui/source/utilities.ts +++ b/packages/kotti-ui/source/utilities.ts @@ -15,10 +15,6 @@ export const attachMeta = ( ): C & { meta: Kotti.Meta & T } => Object.assign(component, { meta: Object.assign({}, meta, other) }) -export const isBrowser = Boolean( - typeof window !== 'undefined' && window.document, -) - /** * Checks if the given HTML element, or any of its children, is in focus * @param element The HTML element diff --git a/packages/kotti-ui/tokens/colors.js b/packages/kotti-ui/tokens/colors.js index 3cbada57fc..182805f58e 100644 --- a/packages/kotti-ui/tokens/colors.js +++ b/packages/kotti-ui/tokens/colors.js @@ -4,9 +4,19 @@ // The tokens are defined with these base colors export const baseColors = { - white: '#FFF', black: '#000', + 'blue-10': '#EAF0FA', + 'blue-100': '#0D244A', + 'blue-20': '#C1D7FB', + 'blue-30': '#AFC5E8', + 'blue-40': '#6795E0', + 'blue-50': '#3173DE', + 'blue-60': '#2C66C4', + 'blue-70': '#2659AB', + 'blue-80': '#1F55AD', + 'blue-90': '#153C7A', 'gray-10': '#F8F8F8', + 'gray-100': '#141414', 'gray-20': '#E0E0E0', 'gray-30': '#C6C6C6', 'gray-40': '#A8A8A8', @@ -15,8 +25,18 @@ export const baseColors = { 'gray-70': '#525252', 'gray-80': '#393939', 'gray-90': '#262626', - 'gray-100': '#141414', + 'green-10': '#E6F8D2', + 'green-20': '#C4E0A5', + 'green-50': '#71C716', + 'green-60': '#64AD13', + 'green-70': '#549410', + 'orange-10': '#FDE2CB', + 'orange-20': '#FAB980', + 'orange-50': '#FF9333', + 'orange-60': '#FF7800', + 'orange-70': '#BA6820', 'primary-10': '#EAF0FA', + 'primary-100': '#0D244A', 'primary-20': '#C1D7FB', 'primary-30': '#AFC5E8', 'primary-40': '#6795E0', @@ -25,27 +45,20 @@ export const baseColors = { 'primary-70': '#2659AB', 'primary-80': '#1F55AD', 'primary-90': '#153C7A', - 'primary-100': '#0D244A', - 'green-20': '#C4E0A5', - 'green-50': '#71C716', - 'green-60': '#64AD13', - 'green-70': '#549410', - 'red-20': '#F0A8A8', - 'red-50': '#F21D1D', - 'red-60': '#D91919', - 'red-70': '#BF1717', 'purple-20': '#B995CA', 'purple-50': '#932DC2', 'purple-60': '#6C218F', 'purple-70': '#591B75', + 'red-10': '#FBE1E1', + 'red-20': '#F0A8A8', + 'red-50': '#F21D1D', + 'red-60': '#D91919', + 'red-70': '#BF1717', + white: '#FFF', 'yellow-20': '#FFF9C0', 'yellow-50': '#FFF490', 'yellow-60': '#FFE60D', 'yellow-70': '#DFC903', - 'orange-20': '#FAB980', - 'orange-50': '#FF9333', - 'orange-60': '#FF7800', - 'orange-70': '#BA6820', } // Tokens are calling base colors @@ -196,6 +209,11 @@ export const tokens = [ description: 'Error', reference: 'red-50', }, + { + name: 'support-error-bg', + description: 'Error Background', + reference: 'red-10', + }, { name: 'support-error-dark', description: 'Error dark', @@ -211,6 +229,11 @@ export const tokens = [ description: 'Warning', reference: 'orange-50', }, + { + name: 'support-warning-bg', + description: 'Warning Background', + reference: 'orange-10', + }, { name: 'support-warning-dark', description: 'Warning dark', @@ -226,6 +249,11 @@ export const tokens = [ description: 'Success', reference: 'green-50', }, + { + name: 'support-success-bg', + description: 'Success Background', + reference: 'green-10', + }, { name: 'support-success-dark', description: 'Success dark', @@ -239,16 +267,21 @@ export const tokens = [ { name: 'support-info', description: 'Information', - reference: 'primary-50', + reference: 'blue-50', + }, + { + name: 'support-info-bg', + description: 'Information Background', + reference: 'blue-10', }, { name: 'support-info-dark', description: 'Information dark', - reference: 'primary-70', + reference: 'blue-70', }, { name: 'support-info-light', description: 'Information light', - reference: 'primary-20', + reference: 'blue-20', }, ] diff --git a/packages/kotti-ui/tokens/generate.js b/packages/kotti-ui/tokens/generate.js index 0e6658ee55..c2c4151e43 100644 --- a/packages/kotti-ui/tokens/generate.js +++ b/packages/kotti-ui/tokens/generate.js @@ -11,9 +11,9 @@ const output = ` Run \`yarn workspace @3yourmind/kotti-ui run build:tokens\` to regenerate it */ -:root{ - ${arrayToCustomProperties(objectToArray(baseColors), 'color')} - ${arrayToCustomProperties(tokens)} +:root { +${arrayToCustomProperties(objectToArray(baseColors), 'color')} +${arrayToCustomProperties(tokens)} }` // Write it diff --git a/packages/kotti-ui/tokens/utilities.js b/packages/kotti-ui/tokens/utilities.js index 53cf01ca63..0d6ce91fb4 100644 --- a/packages/kotti-ui/tokens/utilities.js +++ b/packages/kotti-ui/tokens/utilities.js @@ -2,7 +2,7 @@ export const arrayToCustomProperties = (colors, type = 'reference') => colors .map( (color) => - `--${color.name}: ${ + `\t--${color.name}: ${ type === 'reference' ? `var(--${color.reference})` : color.value };`, ) diff --git a/yarn.lock b/yarn.lock index 3faefce673..01aeab5f80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10237,16 +10237,16 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w== +nanoid@3.x, nanoid@^3.1.23, nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + nanoid@^2.1.0: version "2.1.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== -nanoid@^3.1.23, nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" From 375240e8e87fff529a452140d24c64756edf6638 Mon Sep 17 00:00:00 2001 From: Moritz Vetter <16950410+Isokaeder@users.noreply.github.com> Date: Tue, 19 Nov 2024 23:05:53 +0100 Subject: [PATCH 7/7] version(eslint-config@0.1.3): allow globalThis --- packages/eslint-config/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index e77e38607b..c44281252f 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -64,5 +64,5 @@ }, "type": "module", "types": "./dist/mjs/index.d.ts", - "version": "0.1.2" + "version": "0.1.3" }