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

fix: optimize expose #84

Merged
merged 6 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions packages/components/aspect-ratio/src/aspect-ratio.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineComponent, h, ref } from 'vue'
import type { ComponentPublicInstance } from 'vue'
import { computed, defineComponent, h, ref } from 'vue'
import type { ComponentPropsWithoutRef, ElementRef } from '@oku-ui/primitive'
import { Primitive } from '@oku-ui/primitive'

Expand All @@ -10,19 +11,19 @@ interface AspectRatioProps extends PrimitiveAspectRatioProps {
}
const NAME = 'AspectRatio'

const AspectRatio = defineComponent<AspectRatioProps, { hello: string }>({
const AspectRatio = defineComponent({
name: NAME,
inheritAttrs: false,
setup(props, { attrs, slots, expose }) {
// TODO: as any how to fix?
const { ratio = 1 / 1, style, ...aspectRatioProps } = attrs as any
const inferRef = ref<AspectRatioElement>()
const innerRef = ref<ComponentPublicInstance>()

expose({
inferRef,
innerRef: computed(() => innerRef.value?.$el),
})

return () => h(
const originalReturn = () => h(
'div', {
'style': {
position: 'relative',
Expand All @@ -36,7 +37,7 @@ const AspectRatio = defineComponent<AspectRatioProps, { hello: string }>({
Primitive.div,
{
...aspectRatioProps,
ref: inferRef,
ref: innerRef,
style: {
...style,
position: 'absolute',
Expand All @@ -50,10 +51,14 @@ const AspectRatio = defineComponent<AspectRatioProps, { hello: string }>({
),
],
)

return originalReturn as unknown as {
innerRef: AspectRatioElement
}
},
})

const OkuAspectRatio = AspectRatio
const OkuAspectRatio = AspectRatio as typeof AspectRatio & (new () => { $props: AspectRatioProps })

export { OkuAspectRatio, AspectRatio }
export { OkuAspectRatio }
export type { AspectRatioProps }
1 change: 0 additions & 1 deletion packages/components/aspect-ratio/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export {
AspectRatio,
OkuAspectRatio,
} from './aspect-ratio'
export type { AspectRatioProps } from './aspect-ratio'
49 changes: 30 additions & 19 deletions packages/components/avatar/src/avatar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable vue/one-component-per-file */
import { defineComponent, h, onMounted, onUnmounted, ref, watch, watchEffect } from 'vue'
import type { ComponentPublicInstance } from 'vue'
import { computed, defineComponent, h, onMounted, onUnmounted, ref, watch, watchEffect } from 'vue'
import type { ComponentPropsWithoutRef } from '@oku-ui/primitive'
import { Primitive } from '@oku-ui/primitive'
import type { Scope } from '@oku-ui/provide'
Expand Down Expand Up @@ -58,12 +59,12 @@ type AvatarElement = ComponentPropsWithoutRef<typeof Primitive.span>
type PrimitiveSpanProps = ComponentPropsWithoutRef<typeof Primitive.span>
interface AvatarProps extends PrimitiveSpanProps {}

const Avatar = defineComponent<ScopedProps<AvatarProps>>({
const Avatar = defineComponent({
name: AVATAR_NAME,
inheritAttrs: false,
setup(props, { attrs, slots, expose }) {
const { __scopeAvatar, ...avatarProps } = attrs as any
const innerRef = ref<AvatarElement>()
const { __scopeAvatar, ...avatarProps } = attrs as ScopedProps<AvatarProps>
const innerRef = ref()
const imageLoadingStatus = ref<ImageLoadingStatus>('idle')

AvatarProvider({
Expand All @@ -75,16 +76,19 @@ const Avatar = defineComponent<ScopedProps<AvatarProps>>({
})

expose({
innerRef,
inferRef: computed(() => innerRef.value?.$el),
})

return () => h(
const originalReturn = () => h(
Primitive.span, {
...avatarProps,
ref: innerRef,
},
slots.default && slots.default(),
)
return originalReturn as unknown as {
innerRef: AvatarElement
}
},
})

Expand All @@ -100,13 +104,13 @@ interface AvatarImageProps extends PrimitiveImgProps {
onLoadingStatusChange?: (status: ImageLoadingStatus) => void
}

const AvatarImage = defineComponent<ScopedProps<AvatarImageProps>>({
const AvatarImage = defineComponent({
name: IMAGE_NAME,
inheritAttrs: false,
setup(props, { attrs, slots, expose }) {
const { __scopeAvatar, src, onLoadingStatusChange = () => {}, ...imageProps } = attrs as any
const { __scopeAvatar, src, onLoadingStatusChange = () => {}, ...imageProps } = attrs as ScopedProps<AvatarImageProps>
const inject = useAvatarInject(IMAGE_NAME, __scopeAvatar)
const innerRef = ref<AvatarImageElement>()
const innerRef = ref<ComponentPublicInstance>()
const imageLoadingStatus = useImageLoadingStatus(src)

const handleLoadingStatusChange = useCallbackRef((status: ImageLoadingStatus) => {
Expand All @@ -125,10 +129,10 @@ const AvatarImage = defineComponent<ScopedProps<AvatarImageProps>>({
})

expose({
innerRef,
innerRef: computed(() => innerRef.value?.$el),
})

return () => imageLoadingStatus.value === 'loaded'
const originalReturn = () => imageLoadingStatus.value === 'loaded'
? h(
Primitive.img, {
...imageProps,
Expand All @@ -138,6 +142,10 @@ const AvatarImage = defineComponent<ScopedProps<AvatarImageProps>>({
slots.default && slots.default(),
)
: null

return originalReturn as unknown as {
innerRef: AvatarImageElement
}
},
})

Expand All @@ -152,15 +160,14 @@ type PrimitiveSpanElement = ComponentPropsWithoutRef<typeof Primitive.span>
interface AvatarFallbackProps extends PrimitiveAvatarFallbackProps, PrimitiveSpanProps {
delayms?: number
}

const AvatarFallback = defineComponent<ScopedProps<AvatarFallbackProps>>({
const AvatarFallback = defineComponent({
name: FALLBACK_NAME,
inheritAttrs: false,
setup(props, { attrs, expose, slots }) {
const { __scopeAvatar, delayms, ...fallbackProps } = attrs as any
const provide = useAvatarInject(FALLBACK_NAME, __scopeAvatar)
const canRender = ref(delayms === undefined)
const innerRef = ref<PrimitiveSpanElement>()
const innerRef = ref<ComponentPublicInstance>()

onMounted(() => {
if (delayms === undefined)
Expand All @@ -179,10 +186,10 @@ const AvatarFallback = defineComponent<ScopedProps<AvatarFallbackProps>>({
})

expose({
innerRef,
innerRef: computed(() => innerRef.value?.$el),
})

return () => {
const originalReturn = () => {
return (canRender.value && (provide.value.imageLoadingStatus !== 'loaded'))
? h(
Primitive.span, {
Expand All @@ -193,14 +200,18 @@ const AvatarFallback = defineComponent<ScopedProps<AvatarFallbackProps>>({
)
: canRender.value
}

return originalReturn as unknown as {
innerRef: PrimitiveSpanElement
}
},
})

/* ----------------------------------------------------------------------------------------------- */

const OkuAvatar = Avatar
const OkuAvatarImage = AvatarImage
const OkuAvatarFallback = AvatarFallback
const OkuAvatar = Avatar as typeof Avatar & (new () => { $props: ScopedProps<AvatarProps> })
const OkuAvatarImage = AvatarImage as typeof AvatarImage & (new () => { $props: ScopedProps<AvatarImageProps> })
const OkuAvatarFallback = AvatarFallback as typeof AvatarFallback & (new () => { $props: ScopedProps<AvatarFallbackProps> })

export {
OkuAvatar,
Expand Down
1 change: 0 additions & 1 deletion packages/components/label/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export {
OkuLabel,
label,
} from './label'
export type { LabelProps } from './label'
24 changes: 14 additions & 10 deletions packages/components/label/src/label.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineComponent, h, ref } from 'vue'
import { computed, defineComponent, h, ref } from 'vue'
import type { ComponentPropsWithoutRef, ElementRef } from '@oku-ui/primitive'
import { Primitive } from '@oku-ui/primitive'

Expand All @@ -9,32 +9,36 @@ type LabelElement = ElementRef<typeof Primitive.label>

const NAME = 'Label'

const label = defineComponent<LabelProps>({
const label = defineComponent({
name: NAME,
inheritAttrs: false,
setup(props, { attrs, slots, expose }) {
const inferRef = ref<LabelElement>()
const innerRef = ref()
const { ...restAttrs } = attrs as LabelProps

expose({
inferRef,
innerRef: computed(() => innerRef.value?.$el),
})

return () => h(Primitive.label, {
...attrs,
ref: inferRef,
const originalReturn = () => h(Primitive.label, {
...restAttrs,
ref: innerRef,
onMousedown: (event: MouseEvent) => {
props.onMousedown?.(event)
restAttrs.onMousedown?.(event)
// prevent text selection when double clicking label
if (!event.defaultPrevented && event.detail > 1)
event.preventDefault()
},
},
slots.default?.(),
)
return originalReturn as unknown as {
innerRef: LabelElement
}
},
})

const OkuLabel = label
const OkuLabel = label as typeof label & (new () => { $props: LabelProps })

export { OkuLabel, label }
export { OkuLabel }
export type { LabelProps }
1 change: 0 additions & 1 deletion packages/components/separator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export {
OkuSeparator,
Separator,
} from './separator'
export type { SeparatorProps } from './separator'
29 changes: 14 additions & 15 deletions packages/components/separator/src/separator.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { defineComponent, h, ref } from 'vue'
import type { ComponentPublicInstance } from 'vue'
import { computed, defineComponent, h, ref } from 'vue'
import type { ComponentPropsWithoutRef, ElementRef } from '@oku-ui/primitive'
import { Primitive } from '@oku-ui/primitive'

type PrimitiveSeparatorProps = ComponentPropsWithoutRef<typeof Primitive.div>

// interface SeparatorProps extends PrimitiveSeparatorProps {}
// type SeparatorElement = ElementRef<typeof Primitive.div>

const NAME = 'Separator'
const DEFAULT_ORIENTATION = 'horizontal'
const ORIENTATIONS = ['horizontal', 'vertical'] as const
Expand All @@ -23,46 +21,47 @@ interface SeparatorProps extends PrimitiveSeparatorProps {
* are updated so that that the rendered element is removed from the accessibility tree.
*/
decorative?: boolean
// height?: string
// width?: string
}

const Separator = defineComponent<SeparatorProps>({
name: NAME,
inheritAttrs: false,
setup(props, { attrs, slots, expose }) {
const { decorative, orientation: orientationProp = DEFAULT_ORIENTATION, style } = attrs as any

const { decorative, orientation: orientationProp = DEFAULT_ORIENTATION, ...domProps } = attrs as SeparatorProps
const orientation = ORIENTATIONS.includes(orientationProp) ? orientationProp : DEFAULT_ORIENTATION
// `aria-orientation` defaults to `horizontal` so we only need it if `orientation` is vertical
const ariaOrientation = orientation === 'vertical' ? orientation : undefined
const semanticProps = decorative ? { role: 'none' } : { 'aria-orientation': ariaOrientation, 'role': 'separator' }

const inferRef = ref<SeparatorElement>()
const innerRef = ref<ComponentPublicInstance>()

expose({
inferRef,
innerRef: computed(() => innerRef.value?.$el),
})

return () =>
const originalReturn = () =>
h(
Primitive.div,
{
...attrs,
ref: inferRef,
ref: innerRef,
...semanticProps,
dataOrientation: orientation,
style: {
...style,
...domProps,
border: 'none',
},
},
slots.default?.(),
)

return originalReturn as unknown as {
innerRef: SeparatorElement
}
},
})

const OkuSeparator = Separator
const OkuSeparator = Separator as typeof Separator & (new () => { $props: SeparatorProps })

export { OkuSeparator, Separator }
export { OkuSeparator }
export type { SeparatorProps }
4 changes: 2 additions & 2 deletions packages/core/primitive/src/primitive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ const Primitive = NODES.reduce((primitive, node) => {
inheritAttrs: false,
setup(props, { attrs, slots }) {
onMounted(() => {
(window as any)[Symbol.for('okui-vue')] = true
(window as any)[Symbol.for('oku-ui')] = true
})
const Tag: any = props.asChild ? 'slot' : node

return () => h(Tag, attrs, slots.default && slots.default())
return () => props.asChild ? slots.default?.() : h(Tag, { ...attrs }, slots.default?.())
},
})
return { ...primitive, [node]: Node }
Expand Down
Loading