Skip to content

Conversation

@github-actions
Copy link
Contributor

Release
@floating-ui/vue@1.1.0

Diff for packages/vue

Diff
diff --git a/packages/vue/CHANGELOG.md b/packages/vue/CHANGELOG.md
index 7bd9d286..8b0d8d4c 100644
--- a/packages/vue/CHANGELOG.md
+++ b/packages/vue/CHANGELOG.md
@@ -1,5 +1,15 @@
 # @floating-ui/vue
 
+## 1.1.0
+
+### Minor Changes
+
+- feat: support `MaybeReadonlyRefOrGetter` in `useFloating`
+
+### Patch Changes
+
+- Update dependencies: `@floating-ui/utils@0.2.4`
+
 ## 1.0.7
 
 ### Patch Changes
diff --git a/packages/vue/package.json b/packages/vue/package.json
index 367610f2..4b88d35f 100644
--- a/packages/vue/package.json
+++ b/packages/vue/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@floating-ui/vue",
-  "version": "1.0.7",
+  "version": "1.1.0",
   "description": "Floating UI for Vue",
   "publishConfig": {
     "access": "public"
diff --git a/packages/vue/src/arrow.ts b/packages/vue/src/arrow.ts
index cc636e3f..b431f4a3 100644
--- a/packages/vue/src/arrow.ts
+++ b/packages/vue/src/arrow.ts
@@ -1,6 +1,6 @@
 import type {Middleware} from '@floating-ui/dom';
 import {arrow as apply} from '@floating-ui/dom';
-import {unref} from 'vue-demi';
+import {toValue} from 'vue-demi';
 
 import type {ArrowOptions} from './types';
 import {unwrapElement} from './utils/unwrapElement';
@@ -15,7 +15,7 @@ export function arrow(options: ArrowOptions): Middleware {
     name: 'arrow',
     options,
     fn(args) {
-      const element = unwrapElement(unref(options.element));
+      const element = unwrapElement(toValue(options.element));
 
       if (element == null) {
         return {};
diff --git a/packages/vue/src/types.ts b/packages/vue/src/types.ts
index a464239a..02aea117 100644
--- a/packages/vue/src/types.ts
+++ b/packages/vue/src/types.ts
@@ -53,6 +53,8 @@ export type {
 
 export type MaybeReadonlyRef<T> = T | Readonly<Ref<T>>;
 
+export type MaybeReadonlyRefOrGetter<T> = MaybeReadonlyRef<T> | (() => T);
+
 export type MaybeElement<T> = T | ComponentPublicInstance | null | undefined;
 
 export type UseFloatingOptions<T extends ReferenceElement = ReferenceElement> =
@@ -61,28 +63,28 @@ export type UseFloatingOptions<T extends ReferenceElement = ReferenceElement> =
      * Represents the open/close state of the floating element.
      * @default true
      */
-    open?: MaybeReadonlyRef<boolean | undefined>;
+    open?: MaybeReadonlyRefOrGetter<boolean | undefined>;
     /**
      * Where to place the floating element relative to its reference element.
      * @default 'bottom'
      */
-    placement?: MaybeReadonlyRef<Placement | undefined>;
+    placement?: MaybeReadonlyRefOrGetter<Placement | undefined>;
     /**
      * The type of CSS position property to use.
      * @default 'absolute'
      */
-    strategy?: MaybeReadonlyRef<Strategy | undefined>;
+    strategy?: MaybeReadonlyRefOrGetter<Strategy | undefined>;
     /**
      * These are plain objects that modify the positioning coordinates in some fashion, or provide useful data for the consumer to use.
      * @default undefined
      */
-    middleware?: MaybeReadonlyRef<Middleware[] | undefined>;
+    middleware?: MaybeReadonlyRefOrGetter<Middleware[] | undefined>;
     /**
      * Whether to use `transform` instead of `top` and `left` styles to
      * position the floating element (`floatingStyles`).
      * @default true
      */
-    transform?: MaybeReadonlyRef<boolean | undefined>;
+    transform?: MaybeReadonlyRefOrGetter<boolean | undefined>;
     /**
      * Callback to handle mounting/unmounting of the elements.
      * @default undefined
@@ -142,7 +144,7 @@ export type ArrowOptions = {
    * The arrow element or template ref to be positioned.
    * @required
    */
-  element: MaybeReadonlyRef<MaybeElement<Element>>;
+  element: MaybeReadonlyRefOrGetter<MaybeElement<Element>>;
   /**
    * The padding between the arrow element and the floating element edges. Useful when the floating element has rounded corners.
    * @default 0
diff --git a/packages/vue/src/useFloating.ts b/packages/vue/src/useFloating.ts
index 76b34ff4..5e83a9f0 100644
--- a/packages/vue/src/useFloating.ts
+++ b/packages/vue/src/useFloating.ts
@@ -12,8 +12,8 @@ import {
   ref,
   shallowReadonly,
   shallowRef,
-  unref,
   watch,
+  toValue,
 } from 'vue-demi';
 
 import type {
@@ -38,11 +38,15 @@ export function useFloating<T extends ReferenceElement = ReferenceElement>(
   options: UseFloatingOptions<T> = {},
 ): UseFloatingReturn {
   const whileElementsMountedOption = options.whileElementsMounted;
-  const openOption = computed(() => unref(options.open) ?? true);
-  const middlewareOption = computed(() => unref(options.middleware));
-  const placementOption = computed(() => unref(options.placement) ?? 'bottom');
-  const strategyOption = computed(() => unref(options.strategy) ?? 'absolute');
-  const transformOption = computed(() => unref(options.transform) ?? true);
+  const openOption = computed(() => toValue(options.open) ?? true);
+  const middlewareOption = computed(() => toValue(options.middleware));
+  const placementOption = computed(
+    () => toValue(options.placement) ?? 'bottom',
+  );
+  const strategyOption = computed(
+    () => toValue(options.strategy) ?? 'absolute',
+  );
+  const transformOption = computed(() => toValue(options.transform) ?? true);
   const referenceElement = computed(() => unwrapElement(reference.value));
   const floatingElement = computed(() => unwrapElement(floating.value));
   const x = ref(0);
diff --git a/packages/vue/test/index.test.ts b/packages/vue/test/index.test.ts
index b105a09b..e98bbe03 100644
--- a/packages/vue/test/index.test.ts
+++ b/packages/vue/test/index.test.ts
@@ -141,6 +141,102 @@ describe('useFloating', () => {
     });
   });
 
+  test('updates floating coords when placement is a getter function', async () => {
+    const App = defineComponent({
+      name: 'App',
+      props: ['placement'],
+      setup(props: {placement?: Placement}) {
+        return setup({
+          placement: () => props.placement,
+          middleware: [offset(5)],
+        });
+      },
+      template: /* HTML */ `
+        <div ref="reference" />
+        <div ref="floating" />
+        <div data-testid="x">{{x}}</div>
+        <div data-testid="y">{{y}}</div>
+      `,
+    });
+
+    const {rerender, getByTestId} = render(App, {
+      props: {placement: 'bottom'},
+    });
+
+    await waitFor(() => {
+      expect(getByTestId('x').textContent).toBe('0');
+      expect(getByTestId('y').textContent).toBe('5');
+    });
+
+    await rerender({placement: 'right'});
+
+    await waitFor(() => {
+      expect(getByTestId('x').textContent).toBe('5');
+      expect(getByTestId('y').textContent).toBe('0');
+    });
+  });
+
+  test('updates floating coords when middleware is a getter function', async () => {
+    const App = defineComponent({
+      name: 'App',
+      props: ['middleware'],
+      setup(props) {
+        return setup({middleware: () => props.middleware});
+      },
+      template: /* HTML */ `
+        <div ref="reference" />
+        <div ref="floating" />
+        <div data-testid="x">{{x}}</div>
+        <div data-testid="y">{{y}}</div>
+      `,
+    });
+
+    const {rerender, getByTestId} = render(App, {
+      props: {middleware: []},
+    });
+
+    await waitFor(() => {
+      expect(getByTestId('x').textContent).toBe('0');
+      expect(getByTestId('y').textContent).toBe('0');
+    });
+
+    await rerender({middleware: [offset(10)]});
+
+    await waitFor(() => {
+      expect(getByTestId('x').textContent).toBe('0');
+      expect(getByTestId('y').textContent).toBe('10');
+    });
+  });
+
+  test('updates floating position when strategy is a getter function', async () => {
+    const App = defineComponent({
+      name: 'App',
+      props: ['strategy'],
+      setup(props: {strategy?: Strategy}) {
+        return setup({strategy: () => props.strategy});
+      },
+      template: /* HTML */ `
+        <div ref="reference" />
+        <div ref="floating" />
+        <div data-testid="position">{{strategy}}</div>
+      `,
+    });
+
+    const {rerender, getByTestId} = render(App, {
+      props: {strategy: 'absolute'},
+    });
+
+    await waitFor(() => {
+      expect(getByTestId('position').textContent).toBe('absolute');
+    });
+
+    await rerender({strategy: 'fixed'});
+
+    await waitFor(() => {
+      expect(getByTestId('position').textContent).toBe('fixed');
+    });
+  });
+
   test('resets `isPositioned` on open change', async () => {
     const App = defineComponent({
       name: 'App',
@@ -170,6 +266,35 @@ describe('useFloating', () => {
     });
   });
 
+  test('resets `isPositioned` on open change and open is a getter function', async () => {
+    const App = defineComponent({
+      name: 'App',
+      props: ['open'],
+      setup(props: {open?: boolean}) {
+        return setup({open: () => props.open});
+      },
+      template: /* HTML */ `
+        <div ref="reference" />
+        <div ref="floating" />
+        <div data-testid="isPositioned">{{isPositioned}}</div>
+      `,
+    });
+
+    const {rerender, getByTestId} = render(App, {
+      props: {open: true},
+    });
+
+    await waitFor(() => {
+      expect(getByTestId('isPositioned').textContent).toBe('true');
+    });
+
+    await rerender({open: false});
+
+    await waitFor(() => {
+      expect(getByTestId('isPositioned').textContent).toBe('false');
+    });
+  });
+
   test('fallbacks to default when placement becomes undefined', async () => {
     const App = defineComponent({
       name: 'App',

Full diff
1.0.7...1.1.0.

@DanielleHuisman DanielleHuisman marked this pull request as ready for review July 10, 2024 16:14
@DanielleHuisman DanielleHuisman enabled auto-merge (squash) July 10, 2024 16:14
@DanielleHuisman DanielleHuisman merged commit 9695cbf into main Jul 10, 2024
@DanielleHuisman DanielleHuisman deleted the upstream/vue-1.1.0 branch July 10, 2024 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants