Co-authored-by: neverland <jait.chen@foxmail.com>
This commit is contained in:
co-authored by
neverland
parent
5a7042c182
commit
d739f678b4
@@ -20,7 +20,7 @@ import {
|
|||||||
addUnit,
|
addUnit,
|
||||||
closest,
|
closest,
|
||||||
createNamespace,
|
createNamespace,
|
||||||
makeNumberProp,
|
isObject,
|
||||||
makeStringProp,
|
makeStringProp,
|
||||||
windowWidth,
|
windowWidth,
|
||||||
windowHeight,
|
windowHeight,
|
||||||
@@ -38,11 +38,15 @@ import {
|
|||||||
FloatingBubbleAxis,
|
FloatingBubbleAxis,
|
||||||
FloatingBubbleMagnetic,
|
FloatingBubbleMagnetic,
|
||||||
FloatingBubbleOffset,
|
FloatingBubbleOffset,
|
||||||
|
FloatingBubbleGap,
|
||||||
FloatingBubbleBoundary,
|
FloatingBubbleBoundary,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export const floatingBubbleProps = {
|
export const floatingBubbleProps = {
|
||||||
gap: makeNumberProp(24),
|
gap: {
|
||||||
|
type: [Number, Object] as unknown as PropType<FloatingBubbleGap>,
|
||||||
|
default: 24,
|
||||||
|
},
|
||||||
icon: String,
|
icon: String,
|
||||||
axis: makeStringProp<FloatingBubbleAxis>('y'),
|
axis: makeStringProp<FloatingBubbleAxis>('y'),
|
||||||
magnetic: String as PropType<FloatingBubbleMagnetic>,
|
magnetic: String as PropType<FloatingBubbleMagnetic>,
|
||||||
@@ -79,11 +83,17 @@ export default defineComponent({
|
|||||||
height: 0,
|
height: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const gapX = computed(() =>
|
||||||
|
isObject(props.gap) ? props.gap.x : props.gap,
|
||||||
|
);
|
||||||
|
const gapY = computed(() =>
|
||||||
|
isObject(props.gap) ? props.gap.y : props.gap,
|
||||||
|
);
|
||||||
const boundary = computed<FloatingBubbleBoundary>(() => ({
|
const boundary = computed<FloatingBubbleBoundary>(() => ({
|
||||||
top: props.gap,
|
top: gapY.value,
|
||||||
right: windowWidth.value - state.value.width - props.gap,
|
right: windowWidth.value - state.value.width - gapX.value,
|
||||||
bottom: windowHeight.value - state.value.height - props.gap,
|
bottom: windowHeight.value - state.value.height - gapY.value,
|
||||||
left: props.gap,
|
left: gapX.value,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const dragging = ref(false);
|
const dragging = ref(false);
|
||||||
@@ -110,8 +120,8 @@ export default defineComponent({
|
|||||||
const { width, height } = useRect(rootRef.value!);
|
const { width, height } = useRect(rootRef.value!);
|
||||||
const { offset } = props;
|
const { offset } = props;
|
||||||
state.value = {
|
state.value = {
|
||||||
x: offset.x > -1 ? offset.x : windowWidth.value - width - props.gap,
|
x: offset.x > -1 ? offset.x : windowWidth.value - width - gapX.value,
|
||||||
y: offset.y > -1 ? offset.y : windowHeight.value - height - props.gap,
|
y: offset.y > -1 ? offset.y : windowHeight.value - height - gapY.value,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
@@ -203,7 +213,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[windowWidth, windowHeight, () => props.gap, () => props.offset],
|
[windowWidth, windowHeight, gapX, gapY, () => props.offset],
|
||||||
updateState,
|
updateState,
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export default {
|
|||||||
| axis | Drag direction, `xy` stands for free drag, `lock` stands for disable drag | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
|
| axis | Drag direction, `xy` stands for free drag, `lock` stands for disable drag | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
|
||||||
| magnetic | Direction of automatic magnetic absorption | _'x' \| 'y'_ | - |
|
| magnetic | Direction of automatic magnetic absorption | _'x' \| 'y'_ | - |
|
||||||
| icon | Bubble icon | _string_ | - |
|
| icon | Bubble icon | _string_ | - |
|
||||||
| gap | Minimum gap between the bubble and the window, unit `px` | _number_ | `24` |
|
| gap | Minimum gap between the bubble and the window, unit `px` | _number \| { x: number, y: number }_ | `24` |
|
||||||
| teleport | Specifies a target element where BackTop will be mounted | _string \| Element_ | `body` |
|
| teleport | Specifies a target element where BackTop will be mounted | _string \| Element_ | `body` |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export default {
|
|||||||
| axis | 拖拽的方向,`xy` 代表自由拖拽,`lock` 代表禁止拖拽 | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
|
| axis | 拖拽的方向,`xy` 代表自由拖拽,`lock` 代表禁止拖拽 | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
|
||||||
| magnetic | 自动磁吸的方向 | _'x' \| 'y'_ | - |
|
| magnetic | 自动磁吸的方向 | _'x' \| 'y'_ | - |
|
||||||
| icon | 气泡图标名称或图片链接,等同于 Icon 组件的 [name 属性](#/zh-CN/icon#props) | _string_ | - |
|
| icon | 气泡图标名称或图片链接,等同于 Icon 组件的 [name 属性](#/zh-CN/icon#props) | _string_ | - |
|
||||||
| gap | 气泡与窗口的最小间距,单位为 `px` | _number_ | `24` |
|
| gap | 气泡与窗口的最小间距,单位为 `px` | _number \| { x: number, y: number }_ | `24` |
|
||||||
| teleport | 指定挂载的节点,等同于 Teleport 组件的 [to 属性](https://cn.vuejs.org/api/built-in-components.html#teleport) | _string \| Element_ | `body` |
|
| teleport | 指定挂载的节点,等同于 Teleport 组件的 [to 属性](https://cn.vuejs.org/api/built-in-components.html#teleport) | _string \| Element_ | `body` |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|||||||
@@ -62,6 +62,33 @@ test('should render correctly when all props set', async () => {
|
|||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should render with xy gaps', async () => {
|
||||||
|
useWindowSize();
|
||||||
|
const restore = mockGetBoundingClientRect({ width: 48, height: 48 });
|
||||||
|
|
||||||
|
const root = document.createElement('div');
|
||||||
|
mount(FloatingBubble, {
|
||||||
|
props: {
|
||||||
|
teleport: root,
|
||||||
|
gap: { x: 50, y: 27 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const floatingBubbleEl = root.querySelector<HTMLDivElement>(
|
||||||
|
'.van-floating-bubble',
|
||||||
|
)!;
|
||||||
|
|
||||||
|
await later();
|
||||||
|
|
||||||
|
expect(floatingBubbleEl.style.transform).toEqual(
|
||||||
|
`translate3d(${window.innerWidth - 48 - 50}px, ${
|
||||||
|
window.innerHeight - 48 - 27
|
||||||
|
}px, 0)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
restore();
|
||||||
|
});
|
||||||
|
|
||||||
test('should only y axis direction move when axis is default', async () => {
|
test('should only y axis direction move when axis is default', async () => {
|
||||||
const restore = mockGetBoundingClientRect({ width: 48, height: 48 });
|
const restore = mockGetBoundingClientRect({ width: 48, height: 48 });
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ export type FloatingBubbleOffset = {
|
|||||||
y: number;
|
y: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FloatingBubbleGap =
|
||||||
|
| number
|
||||||
|
| {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type FloatingBubbleBoundary = {
|
export type FloatingBubbleBoundary = {
|
||||||
top: number;
|
top: number;
|
||||||
right: number;
|
right: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user