Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] make existent props reactive and new whileElementsMount prop #1

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
5 changes: 3 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
reference,
floating,
strategy: computedStrategy,
placement: computedPlacement,
} = useFloating({
placement,
strategy,
Expand All @@ -36,13 +37,13 @@ function toggleMiddleware() {
class="px-2 text-sm py-1 bg-gray-900 text-gray-100 rounded inline-block"
@click="togglePlacement"
>
Toggle placement: {{ placement }}
Toggle placement: {{ placement }} | {{ computedPlacement }}
</button>
<button
class="px-2 text-sm py-1 bg-gray-900 text-gray-100 rounded inline-block"
@click="toggleStrategy"
>
Toggle strategy: {{ strategy }}
Toggle strategy: {{ strategy }} | {{ computedStrategy }}
</button>
<button
class="px-2 text-sm py-1 bg-gray-900 text-gray-100 rounded inline-block"
Expand Down
42 changes: 18 additions & 24 deletions src/vue-floating-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
ReferenceElement,
FloatingElement,
} from "@floating-ui/dom";
import { ref, Ref, ToRefs, watch, isRef } from "vue";
import { ref, Ref, ToRefs, watch, isRef, toRefs, unref, reactive } from "vue";

export {
autoPlacement,
Expand Down Expand Up @@ -60,36 +60,34 @@ export function useFloating({
}: UseFloatingProps = {}): UseFloatingReturn {
const reference = ref<ReferenceElement | null>(null);
const floating = ref<FloatingElement | null>(null);
const middlewareRef = ref(middleware);
const cleanupRef = ref<Function | void | null>(null);
// Setting these to `null` will allow the consumer to determine if
// `computePosition()` has run yet
const x = ref<number | null>(null);
const y = ref<number | null>(null);
const _placement = ref(placement);
const _strategy = ref(strategy);
const _middleware = ref(middleware);
const middlewareData = ref<MiddlewareData>({});
const cleanupRef = ref<Function | void | null>(null);
const data = reactive<Data>({
x: null,
y: null,
placement: unref(placement),
strategy: unref(strategy),
Comment on lines +70 to +71
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reactive conversion is "deep": it affects all nested properties. A reactive object also deeply unwraps any properties that are refs while maintaining reactivity.
https://vuejs.org/api/reactivity-core.html#reactive

unref can be omitted

Copy link
Author

@renatodeleao renatodeleao Sep 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the key part is "unwraps while maintaining reactivity", we don't want to keep reactivity or it would mutate original props refs as before. We just want o use its value like an initial value. EDIT: Also, since we can provide static strings as props, unref does the isRef(prop) ? prop.value : prop for us.

Codesandbox

middlewareData: {},
});

const update = () => {
if (!reference.value || !floating.value) {
return;
}

computePosition(reference.value, floating.value, {
middleware: _middleware.value,
placement: _placement.value,
strategy: _strategy.value,
}).then((data) => {
x.value = data.x;
y.value = data.y;
_placement.value = data.placement;
_strategy.value = data.strategy;
middlewareData.value = data.middlewareData;
middleware: unref(middlewareRef),
placement: unref(placement),
strategy: unref(strategy),
}).then((computedData) => {
Object.assign(data, computedData);
});
};

watch([_placement, _strategy], update);
watch(_middleware, update, { deep: true });
watch([placement, strategy], update);
watch(middlewareRef, update, { deep: true });

watch([reference, floating], () => {
if (cleanupRef.value) {
Expand All @@ -113,11 +111,7 @@ export function useFloating({
});

return {
x,
y,
strategy: _strategy,
placement: _placement,
middlewareData,
...toRefs(data),
update,
reference,
floating,
Expand Down