Skip to content

Commit

Permalink
chore: add basic drag demo
Browse files Browse the repository at this point in the history
  • Loading branch information
rick-hup committed Dec 22, 2024
1 parent da042d9 commit 9088040
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 60 deletions.
5 changes: 4 additions & 1 deletion docs/app.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useMediaQuery } from '@vueuse/core'
const { page } = useContent()
const config = useConfig()
const route = useRoute()
Expand All @@ -12,6 +14,7 @@ useServerHead({
bodyAttrs: {
},
})
const isMobile = useMediaQuery('(max-width: 768px)')
</script>

<template>
Expand All @@ -20,7 +23,7 @@ useServerHead({
/>
<!-- ClientOnly -->
<LayoutHeader />
<LayoutMobileNav />
<LayoutMobileNav v-if="isMobile" />

<div class="min-h-screen pt-14 dark:bg-[radial-gradient(#ffffff22_1px,transparent_1px)] [background-size:16px_16px] bg-[radial-gradient(#00000021_1px,transparent_1px)]">
<div
Expand Down
77 changes: 77 additions & 0 deletions docs/components/demo/drag-transform/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<script setup lang="ts">
import { useMotionValue, useTransform } from 'motion-v'
const x = useMotionValue(0)
const xInput = [-100, 0, 100]
const background = useTransform(x, xInput, [
'linear-gradient(180deg, #ff008c 0%, rgb(211, 9, 225) 100%)',
'linear-gradient(180deg, #7700ff 0%, rgb(68, 0, 255) 100%)',
'linear-gradient(180deg, rgb(230, 255, 0) 0%, rgb(3, 209, 0) 100%)',
])
const color = useTransform(x, xInput, [
'rgb(211, 9, 225)',
'rgb(68, 0, 255)',
'rgb(3, 209, 0)',
])
const tickPath = useTransform(x, [10, 100], [0, 1])
const crossPathA = useTransform(x, [-10, -55], [0, 1])
const crossPathB = useTransform(x, [-50, -100], [0, 1])
</script>

<template>
<Motion
:style="{ background }"
class="w-[300px] h-[300px] bg-[#dd00ee]/25 rounded-lg flex items-center justify-center"
>
<Motion
:style="{ x }"
drag="x"
:drag-constraints="{ left: 0, right: 0 }"
class="w-[100px] h-[100px] bg-white rounded-lg"
>
<svg
class="progress-icon"
viewBox="0 0 50 50"
>
<Motion
as="path"
fill="none"
stroke-width="2"
:stroke="color"
d="M 0, 20 a 20, 20 0 1,0 40,0 a 20, 20 0 1,0 -40,0"
:style="{ transform: 'translate(5px, 5px)' }"
/>
<Motion
as="path"
fill="none"
stroke-width="2"
:stroke="color"
d="M14,26 L 22,33 L 35,16"
stroke-dasharray="0 1"
:style="{ pathLength: tickPath }"
/>
<Motion
as="path"
fill="none"
stroke-width="2"
:stroke="color"
d="M17,17 L33,33"
stroke-dasharray="0 1"
:style="{ pathLength: crossPathA }"
/>
<Motion
as="path"
fill="none"
stroke-width="2"
:stroke="color"
d="M33,17 L17,33"
stroke-dasharray="0 1"
:style="{ pathLength: crossPathB }"
/>
</svg>
</Motion>
</Motion>
</template>
19 changes: 19 additions & 0 deletions docs/components/demo/drag-with-constraints/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang="ts">
import { Motion } from 'motion-v'
import { ref } from 'vue'
const constraintsRef = ref<HTMLDivElement>()
</script>

<template>
<div
ref="constraintsRef"
class="w-[300px] h-[300px] bg-[#dd00ee]/25 rounded-lg"
>
<Motion
:drag="true"
:drag-constraints="constraintsRef"
class="w-[100px] h-[100px] bg-[#dd00ee] rounded-lg"
/>
</div>
</template>
10 changes: 10 additions & 0 deletions docs/components/demo/drag/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script setup lang="ts">
import { Motion } from 'motion-v'
</script>

<template>
<Motion
:drag="true"
class="w-[100px] h-[100px] bg-[#dd00ee] rounded-lg"
/>
</template>
44 changes: 4 additions & 40 deletions docs/components/layout/Aside.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const tree = computed(() => {
return navigation.value
})
onMounted(() => {
console.log(tree.value, navigation)
})
const path = computed(() => useRoute().path)
</script>
Expand All @@ -26,47 +29,8 @@ const path = computed(() => useRoute().path)
class="relative h-full overflow-hidden py-6 pr-6 text-sm md:pr-4"
type="hover"
>
<ul
v-if="config?.aside.useLevel"
class="flex flex-col gap-1 border-b pb-4"
>
<li
v-for="link in navigation"
:key="link.id"
@click="$emit('close')"
>
<NuxtLink
:to="link._path"
class="flex h-8 items-center gap-2 rounded-md p-2 text-sm text-foreground/80 hover:bg-muted hover:text-primary"
:class="[
path.startsWith(link._path) && 'bg-muted !text-primary',
]"
>
<Icon
v-if="link.icon"
:name="link.icon"
class="self-center"
:size="16"
/>
{{ link.title }}

<span
v-for="(badge, i) in link.navBadges"
:key="i"
>
<Badge
:variant="badge.variant"
:type="badge.type"
:size="badge.size ?? 'sm'"
>
{{ badge.value }}
</Badge>
</span>
</NuxtLink>
</li>
</ul>
<LayoutAsideTree
:links="tree"
:links="navigation"
:level="0"
:class="[config?.aside.useLevel ? 'pt-4' : 'pt-1']"
@click="$emit('close')"
Expand Down
10 changes: 1 addition & 9 deletions docs/components/layout/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ const config = useConfig()
class="flex-1 md:flex"
:class="[config.header.showTitleInMobile ? 'flex' : 'hidden']"
/>
<LayoutHeaderNav class="hidden flex-1 lg:flex" />
<div class="flex flex-1 justify-end gap-2">
<LayoutHeaderSearch v-if="!config.search.inAside && config.search.style === 'input'" />
<div class="flex">
<LayoutHeaderSearch v-if="!config.search.inAside && config.search.style === 'button'" />
<LayoutHeaderSearch />
<LayoutHeaderThemeSwitch />
<NuxtLink
v-for="(link, i) in config.header.links"
Expand All @@ -42,11 +40,5 @@ const config = useConfig()
</div>
</div>
</div>
<div
v-if="config.toc.enable && config.toc.enableInMobile"
class="lg:hidden"
>
<LayoutToc is-small />
</div>
</header>
</template>
6 changes: 4 additions & 2 deletions docs/components/layout/header/Search.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ const commandCenterVariants = {
checked: { pathLength: 0 },
unchecked: { pathLength: 1 },
}
const pathLength = useMotionValue(1)
const route = useRoute()
watch(() => route.path, (value) => {
isOpen.value = false
})
</script>

<template>
Expand Down
4 changes: 0 additions & 4 deletions docs/content/1.getting-started/2.installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ description: How to install motion-v in your app.
navigation.icon: 'lucide:play'
---

::steps

### Installation

:pm-install{name="motion-v"}
Expand All @@ -20,5 +18,3 @@ export default defineNuxtConfig({
],
})
```

::
16 changes: 16 additions & 0 deletions docs/content/3.animation/gesture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Gesture
navigation.icon: 'lucide:hand'
---

Motion provides a set of gesture controls that allow you to create interactive animations.

## Drag

The `Drag` gesture control allows you to drag an element.

<ComponentPreview name="drag" />

### Drag with constraints

<ComponentPreview name="drag-with-constraints" />
4 changes: 4 additions & 0 deletions docs/content/4.motion-value/6.use-transform.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ useTransform(() => x.get() * 2)
useTransform(x, [0, 100], ['#f00', '00f'])
```

## Drag transform

<ComponentPreview name="drag-transform" />

<iframe src="https://stackblitz.com/edit/vitejs-vite-ff3czw?ctl=1&embed=1&file=src%2FApp.vue&hideExplorer=1"
style="width:100%; height: 500px; border:0; border-radius: 4px; overflow:hidden;"
title="motion-use-spring"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { mixNumber } from '@/utils/mix/number'
import type { LayoutUpdateData } from '@/projection/node/types'
import { invariant } from 'hey-listen'
import { isPresent } from '@/state/utils/is-present'
import type { MotionState } from '@/state'

export const elementDragControls = new WeakMap<
VisualElement,
Expand Down Expand Up @@ -153,8 +154,8 @@ export class VisualElementDragControls {

addValueToWillChange(this.visualElement, 'transform')

const { animationState } = this.visualElement
animationState && animationState.setActive('whileDrag', true)
const state = (this.visualElement as any).state as MotionState
state.setActive('whileDrag', true)
}

const onMove = (event: PointerEvent, info: PanInfo) => {
Expand Down Expand Up @@ -259,7 +260,8 @@ export class VisualElementDragControls {
this.openGlobalLock = null
}

animationState && animationState.setActive('whileDrag', false)
const state = (this.visualElement as any).state as MotionState
state.setActive('whileDrag', false)
}

private updateAxis(axis: DragDirection, _point: Point, offset?: Point) {
Expand Down
2 changes: 1 addition & 1 deletion packages/motion/src/state/motion-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { createVisualElement } from '@/state/create-visual-element'
import { type ActiveVariant, animateVariantsChildren } from '@/state/animate-variants-children'
import { doneCallbacks } from '@/components/presence'

const STATE_TYPES = ['initial', 'animate', 'inView', 'hover', 'press', 'exit', 'drag'] as const
const STATE_TYPES = ['initial', 'animate', 'inView', 'hover', 'press', 'whileDrag', 'exit'] as const
type StateType = typeof STATE_TYPES[number]
export const mountedStates = new WeakMap<Element, MotionState>()
let id = 0
Expand Down

0 comments on commit 9088040

Please sign in to comment.