From 6f68f60635a21987c62ce9f986f6ebe9503ca551 Mon Sep 17 00:00:00 2001 From: Jonathan Carle Date: Thu, 16 Jan 2025 09:34:19 +0100 Subject: [PATCH 01/12] replaced managed state with defineModel --- .../composables/helpers/useOutsideClick.ts | 7 +- packages/headless/src/utils/types.ts | 6 +- packages/sit-onyx/.storybook/managed.ts | 9 -- packages/sit-onyx/.storybook/preview.ts | 9 +- packages/sit-onyx/.storybook/vModel.ts | 16 --- .../OnyxMiniSearch/OnyxMiniSearch.vue | 19 +-- .../src/components/OnyxMiniSearch/types.ts | 4 - .../modules/OnyxFlyoutMenu/OnyxFlyoutMenu.vue | 17 +-- .../modules/OnyxFlyoutMenu/types.ts | 7 -- .../modules/OnyxNavButton/OnyxNavButton.vue | 19 +-- .../OnyxNavBar/modules/OnyxNavButton/types.ts | 6 - .../modules/OnyxUserMenu/OnyxUserMenu.vue | 15 ++- .../modules/OnyxUserMenu/UserMenuLayout.vue | 32 ++--- .../OnyxNavBar/modules/OnyxUserMenu/types.ts | 7 -- .../OnyxSelect/OnyxSelect.stories.ts | 17 --- .../src/components/OnyxSelect/OnyxSelect.vue | 88 +++++++------- .../src/components/OnyxSelect/types.ts | 109 ++++++------------ .../src/composables/useManagedState.spec.ts | 38 ------ .../src/composables/useManagedState.ts | 53 --------- 19 files changed, 124 insertions(+), 354 deletions(-) delete mode 100644 packages/sit-onyx/.storybook/managed.ts delete mode 100644 packages/sit-onyx/.storybook/vModel.ts delete mode 100644 packages/sit-onyx/src/composables/useManagedState.spec.ts delete mode 100644 packages/sit-onyx/src/composables/useManagedState.ts diff --git a/packages/headless/src/composables/helpers/useOutsideClick.ts b/packages/headless/src/composables/helpers/useOutsideClick.ts index 2ecc031c6..96d564da4 100644 --- a/packages/headless/src/composables/helpers/useOutsideClick.ts +++ b/packages/headless/src/composables/helpers/useOutsideClick.ts @@ -1,13 +1,12 @@ -import type { Arrayable } from "vitest"; -import { toValue, type Ref } from "vue"; -import type { MaybeReactiveSource } from "../../utils/types"; +import { toValue, type MaybeRefOrGetter, type Ref } from "vue"; +import type { Arrayable } from "../../utils/types"; import { useGlobalEventListener } from "./useGlobalListener"; export type UseOutsideClickOptions = { /** * HTML element of the component where clicks should be ignored */ - inside: MaybeReactiveSource>; + inside: MaybeRefOrGetter>; /** * Callback when an outside click occurred. */ diff --git a/packages/headless/src/utils/types.ts b/packages/headless/src/utils/types.ts index 897d6f2c1..e7c5995e7 100644 --- a/packages/headless/src/utils/types.ts +++ b/packages/headless/src/utils/types.ts @@ -1,5 +1,3 @@ -import type { ComputedRef, MaybeRefOrGetter } from "vue"; - /** * Adds the entry with the key `Key` and the value of type `TValue` to a record when it is defined. * Then the entry is either undefined or exists without being optional. @@ -25,6 +23,6 @@ export type IsArray = TMultiple exten : TValue; /** - * Type for any kind of ref source. Preferably used in combination with vue's `toValue` method + * A type that can be wrapped in an array. */ -export type MaybeReactiveSource = MaybeRefOrGetter | ComputedRef; +export type Arrayable = T | Array; diff --git a/packages/sit-onyx/.storybook/managed.ts b/packages/sit-onyx/.storybook/managed.ts deleted file mode 100644 index c02513b43..000000000 --- a/packages/sit-onyx/.storybook/managed.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createSymbolArgTypeEnhancer } from "@sit-onyx/storybook-utils"; - -export const enhanceManagedSymbol = createSymbolArgTypeEnhancer( - "MANAGED_SYMBOL", - "If no value (or `undefined`) is passed, `MANAGED_SYMBOL` is the internal default value for this prop.\n" + - "It signals the component that the prop is managed and it's state tracked internally.\n" + - "So in that case no prop binding or `v-model` is necessary.\n" + - "Updates for the prop will still be emitted.\n", -); diff --git a/packages/sit-onyx/.storybook/preview.ts b/packages/sit-onyx/.storybook/preview.ts index a9b54ec39..29ef0fba3 100644 --- a/packages/sit-onyx/.storybook/preview.ts +++ b/packages/sit-onyx/.storybook/preview.ts @@ -1,4 +1,4 @@ -import { createPreview } from "@sit-onyx/storybook-utils"; +import { createPreview, withVModelDecorator } from "@sit-onyx/storybook-utils"; import { setup, type Preview } from "@storybook/vue3"; import { createToastProvider, TOAST_PROVIDER_INJECTION_KEY } from "../src"; import docsTemplate from "./docs-template.mdx"; @@ -12,9 +12,8 @@ import { a11yTags } from "../src/a11yConfig"; import "../src/styles/index.scss"; import "./docs-template.scss"; import { enhanceFormInjectedSymbol } from "./formInjected"; -import { enhanceManagedSymbol } from "./managed"; import brandImage from "./public/onyx-logo-long.svg"; -import { withOnyxVModelDecorator } from "./vModel"; + const enabledRules = getRules(a11yTags).map((ruleMetadata) => ({ id: ruleMetadata.ruleId, enabled: true, @@ -24,7 +23,7 @@ const axeConfig: Spec = { rules: enabledRules }; const basePreview = createPreview( { - argTypesEnhancers: [enhanceManagedSymbol, enhanceFormInjectedSymbol], + argTypesEnhancers: [enhanceFormInjectedSymbol], parameters: { docs: { page: docsTemplate, @@ -42,7 +41,7 @@ const basePreview = createPreview( globalTypes: { ...onyxThemeGlobalType, }, - decorators: [withOnyxTheme, withOnyxVModelDecorator], + decorators: [withOnyxTheme, withVModelDecorator()], }, { brandImage, diff --git a/packages/sit-onyx/.storybook/vModel.ts b/packages/sit-onyx/.storybook/vModel.ts deleted file mode 100644 index db9b18e59..000000000 --- a/packages/sit-onyx/.storybook/vModel.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { withVModelDecorator } from "@sit-onyx/storybook-utils"; -import type { StrictInputType } from "storybook/internal/types"; - -const isManaged = (argType: StrictInputType) => - argType.table?.defaultValue?.summary === "MANAGED_SYMBOL"; - -/** - * Custom `withVModelDecorator` filter function, because we want don't want to override values that are managed. - */ -export const withOnyxVModelDecorator = withVModelDecorator({ - filter: ({ table, name }, _, argTypes) => { - if (table?.category !== "events" || !name.startsWith("update:")) return false; - const propName = name.replace(/^update:/, ""); - return !argTypes.some((argType) => argType.name === propName && isManaged(argType)); - }, -}); diff --git a/packages/sit-onyx/src/components/OnyxMiniSearch/OnyxMiniSearch.vue b/packages/sit-onyx/src/components/OnyxMiniSearch/OnyxMiniSearch.vue index 672141800..ca7901fbe 100644 --- a/packages/sit-onyx/src/components/OnyxMiniSearch/OnyxMiniSearch.vue +++ b/packages/sit-onyx/src/components/OnyxMiniSearch/OnyxMiniSearch.vue @@ -13,29 +13,22 @@ defineOptions({ inheritAttrs: false }); const props = defineProps(); const emit = defineEmits<{ - /** - * Emitted when the current search value changes. - */ - "update:modelValue": [input: string]; /** * Emitted when the clear button is clicked. */ clear: []; }>(); +/** + * Current input/search value. + */ +const modelValue = defineModel(); + const { rootAttrs, restAttrs } = useRootAttrs(); const { densityClass } = useDensity(props); const { t } = injectI18n(); const input = ref(); -/** - * Current value (with getter and setter) that can be used as "v-model" for the native input. - */ -const value = computed({ - get: () => props.modelValue, - set: (value) => emit("update:modelValue", value ?? ""), -}); - const placeholder = computed(() => t.value("select.searchPlaceholder")); defineExpose({ @@ -54,7 +47,7 @@ defineExpose({ > import { createMenuButton } from "@sit-onyx/headless"; -import { computed, toRef } from "vue"; -import { MANAGED_SYMBOL, useManagedState } from "../../../../composables/useManagedState"; +import { computed } from "vue"; import type { SelectOptionValue } from "../../../../types"; import type { OnyxFlyoutMenuProps } from "./types"; const props = withDefaults(defineProps(), { - open: MANAGED_SYMBOL, trigger: "hover", }); -const emit = defineEmits<{ - "update:open": [isOpen: boolean]; -}>(); - -const { state: isExpanded } = useManagedState( - toRef(() => props.open), - false, - (newVal) => emit("update:open", newVal), -); +/** + * If the flyout is expanded or not. + */ +const isExpanded = defineModel("open", { default: false }); const slots = defineSlots<{ /** diff --git a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxFlyoutMenu/types.ts b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxFlyoutMenu/types.ts index 8e67014f8..29987b36e 100644 --- a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxFlyoutMenu/types.ts +++ b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxFlyoutMenu/types.ts @@ -1,11 +1,4 @@ -import type { ManagedProp } from "../../../../composables/useManagedState"; - export type OnyxFlyoutMenuProps = { - /** - * If the flyout is expanded or not. - * If `undefined`, the state will be managed internally. - */ - open?: ManagedProp; /** * If the flyout is expanded on click or hover. * The default value is 'hover' which will expand the flyout on hover. diff --git a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxNavButton/OnyxNavButton.vue b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxNavButton/OnyxNavButton.vue index d9ad0d17e..2204204eb 100644 --- a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxNavButton/OnyxNavButton.vue +++ b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxNavButton/OnyxNavButton.vue @@ -1,7 +1,6 @@