motion-v
Version:
<p align="center"> <img width="100" height="100" alt="Motion logo" src="https://user-images.githubusercontent.com/7850794/164965523-3eced4c4-6020-467e-acde-f11b7900ad62.png" /> </p> <h1 align="center">Motion for Vue</h1>
134 lines (133 loc) • 4.66 kB
JavaScript
import { getMotionElement } from "../hooks/use-motion-elm.mjs";
import { defineComponent, h, Comment, mergeProps, cloneVNode } from "vue";
import { useMotionState } from "./use-motion-state.mjs";
import { MotionComponentProps } from "./props.mjs";
function checkMotionIsHidden(instance) {
var _a;
const isHidden = ((_a = getMotionElement(instance.$el)) == null ? void 0 : _a.style.display) === "none";
const hasTransition = instance.$.vnode.transition;
return hasTransition && isHidden;
}
const componentMaxCache = /* @__PURE__ */ new Map();
const componentMiniCache = /* @__PURE__ */ new Map();
function renderSlotFragments(fragments) {
if (!Array.isArray(fragments))
return [fragments];
const result = [];
for (const item of fragments) {
if (Array.isArray(item))
result.push(...item);
else
result.push(item);
}
return result;
}
const SELF_CLOSING_TAGS = ["area", "img", "input"];
function handlePrimitiveAndSlot(asTag, allAttrs, slots) {
var _a, _b;
if (typeof asTag === "string" && SELF_CLOSING_TAGS.includes(asTag)) {
return h(asTag, allAttrs);
}
if (asTag === "template") {
if (!slots.default)
return null;
const childrens = renderSlotFragments(slots.default());
const firstNonCommentChildrenIndex = childrens.findIndex((child) => child.type !== Comment);
if (firstNonCommentChildrenIndex === -1)
return childrens;
const firstNonCommentChildren = childrens[firstNonCommentChildrenIndex];
(_a = firstNonCommentChildren.props) == null ? true : delete _a.ref;
const mergedProps = firstNonCommentChildren.props ? mergeProps(allAttrs, firstNonCommentChildren.props) : allAttrs;
if (allAttrs.class && ((_b = firstNonCommentChildren.props) == null ? void 0 : _b.class))
delete firstNonCommentChildren.props.class;
const cloned = cloneVNode(firstNonCommentChildren, mergedProps);
for (const prop in mergedProps) {
if (prop.startsWith("on")) {
cloned.props || (cloned.props = {});
cloned.props[prop] = mergedProps[prop];
}
}
if (childrens.length === 1)
return cloned;
childrens[firstNonCommentChildrenIndex] = cloned;
return childrens;
}
return null;
}
function createMotionComponent(component, options = {}) {
var _a;
const isString = typeof component === "string";
const name = isString ? component : component.name || "";
const componentCache = ((_a = options.features) == null ? void 0 : _a.length) > 0 ? componentMaxCache : componentMiniCache;
if (isString && (componentCache == null ? void 0 : componentCache.has(component))) {
return componentCache.get(component);
}
const motionComponent = defineComponent({
inheritAttrs: false,
props: {
...MotionComponentProps,
features: {
type: Object,
default: () => options.features || []
},
as: { type: [String, Object], default: component || "div" }
},
name: name ? `motion.${name}` : "Motion",
setup(props, { slots }) {
const { getProps, getAttrs, state } = useMotionState(props);
function onVnodeUpdated() {
const el = state.element;
const isComponent = typeof props.as === "object";
if ((!isComponent || props.asChild) && el) {
const { style } = getAttrs();
if (style) {
for (const [key, val] of Object.entries(style)) {
el.style[key] = val;
}
}
}
}
return () => {
const motionProps = getProps();
const motionAttrs = getAttrs();
const asTag = props.asChild ? "template" : props.as;
const allAttrs = {
...options.forwardMotionProps || props.forwardMotionProps ? motionProps : {},
...motionAttrs,
onVnodeUpdated
};
const primitiveOrSlotResult = handlePrimitiveAndSlot(asTag, allAttrs, slots);
if (primitiveOrSlotResult !== null) {
return primitiveOrSlotResult;
}
return h(asTag, {
...allAttrs
}, slots);
};
}
});
if (isString) {
componentCache == null ? void 0 : componentCache.set(component, motionComponent);
}
return motionComponent;
}
function createMotionComponentWithFeatures(features = []) {
return new Proxy({}, {
get(target, prop) {
if (prop === "create") {
return (component, options) => createMotionComponent(component, {
...options,
features
});
}
return createMotionComponent(prop, {
features
});
}
});
}
export {
checkMotionIsHidden,
createMotionComponent,
createMotionComponentWithFeatures
};