Skip to content

Commit

Permalink
feat(components): add trigger component
Browse files Browse the repository at this point in the history
  • Loading branch information
yzh990918 committed Sep 16, 2022
1 parent 87c664c commit 9d6580f
Show file tree
Hide file tree
Showing 21 changed files with 1,616 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@chris-zhu"
],
"rules": {
"react/display-name": "off"
"react/display-name": "off",
"react-hooks/rules-of-hooks": "off"
}
}
8 changes: 8 additions & 0 deletions packages/components/_components/ClientOnly.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<template>
<slot v-if="mounted" />
</template>

<script setup lang='ts'>
const mounted = ref(false)
onMounted(() => { mounted.value = true })
</script>
46 changes: 46 additions & 0 deletions packages/components/_components/ResizeObserver.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { defineComponent } from 'vue'
import ResizeObserver from 'resize-observer-polyfill'
import { useFirstElement } from '../_hooks'

export default defineComponent({
name: 'ResizeObserver',
props: {
watchOnUpdated: Boolean,
},
emits: ['resize'],
setup(_, { emit, slots }) {
const { children, firstElement } = useFirstElement()
let resizeObserver: ResizeObserver | null

const createResizeObserver = (target: HTMLElement) => {
if (!target) return
resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
const entry = entries[0]
emit('resize', entry)
})
resizeObserver.observe(target)
}

const destroyResizeObserver = () => {
if (resizeObserver) {
resizeObserver.disconnect()
resizeObserver = null
}
}

watch(firstElement, (element) => {
if (resizeObserver) destroyResizeObserver()
if (element)
createResizeObserver(element)
})

onBeforeUnmount(() => {
if (resizeObserver) destroyResizeObserver()
})

return () => {
children.value = slots.default?.()
return children.value
}
},
})
3 changes: 3 additions & 0 deletions packages/components/_hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './useFirstElement'
export * from './useTeleport'
export * from './useResizeObserver'
20 changes: 20 additions & 0 deletions packages/components/_hooks/useFirstElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getFirstElementFromChildren } from '@onu-ui/utils'
import type{ VNode } from 'vue'
export const useFirstElement = () => {
const children: { value?: VNode[] } = {}
const firstElement = ref<HTMLElement>()

const getFirstElement = () => {
const element = getFirstElementFromChildren(children.value)
if (element !== firstElement.value)
firstElement.value = element
}

onMounted(() => getFirstElement())
onUpdated(() => getFirstElement())

return {
children,
firstElement,
}
}
34 changes: 34 additions & 0 deletions packages/components/_hooks/useResizeObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { isFunction } from '@onu-ui/utils'
import ResizeObserver from 'resize-observer-polyfill'
import type { Ref } from 'vue'

export const useResizeObserver = ({
elementRef,
onResize,
}: {
elementRef: Ref<HTMLElement | undefined>
onResize: (entry?: ResizeObserverEntry) => void
}) => {
let resizeObserver: ResizeObserver | null

const createResizeObserver = () => {
if (!elementRef.value) return
resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
const entry = entries[0]
isFunction(onResize) && onResize(entry)
})
resizeObserver.observe(elementRef.value)
}

const destroyResizeObserver = () => {
if (resizeObserver) {
resizeObserver.disconnect()
resizeObserver = null
}
}

return {
createResizeObserver,
destroyResizeObserver,
}
}
52 changes: 52 additions & 0 deletions packages/components/_hooks/useTeleport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { onMounted, ref, watch } from 'vue'
import { getElement } from '@onu-ui/utils'
import type { Ref } from 'vue'

/**
*
* @param param0
* @returns teleportContainer: mounted Teleport container,containerRef: popupContainer element
*/
export const useTeleport = ({
popupContainer,
visible,
defaultContainer = 'body',
documentContainer,
}: {
popupContainer: Ref<string | HTMLElement | undefined>
visible: Ref<boolean>
defaultContainer?: string
documentContainer?: boolean
}) => {
const teleportContainer = ref(popupContainer.value)
const containerRef = ref<HTMLElement>()

const getContainer = () => {
const element = getElement(popupContainer.value)
const _teleportContainer = element
? popupContainer.value
: defaultContainer
const _containerElement
= element
?? (documentContainer
? document.documentElement
: getElement(defaultContainer))
if (_teleportContainer !== teleportContainer.value)
teleportContainer.value = _teleportContainer

if (_containerElement !== containerRef.value)
containerRef.value = _containerElement
}

onMounted(() => getContainer())

watch(visible, (visible) => {
if (teleportContainer.value !== popupContainer.value && visible)
getContainer()
})

return {
teleportContainer,
containerRef,
}
}
1 change: 0 additions & 1 deletion packages/components/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ declare global {
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
Expand Down
3 changes: 3 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
"@vueuse/core": "^9.1.0",
"vue": "^3.2.0"
},
"devDependencies": {
"resize-observer-polyfill": "^1.5.1"
},
"publishConfig": {
"access": "public"
}
Expand Down
Empty file.
12 changes: 12 additions & 0 deletions packages/components/trigger/src/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { InjectionKey } from 'vue'

export interface TriggerContext {
onMouseenter: (ev: MouseEvent) => void
onMouseleave: (ev: MouseEvent) => void
addChildRef: (ref: any) => void
removeChildRef: (ref: any) => void
}

/** use for Nesting triggers */
export const triggerInjectionKey: InjectionKey<TriggerContext>
= Symbol('OnuTrigger')
Loading

0 comments on commit 9d6580f

Please sign in to comment.