mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-24 17:00:36 +01:00
remove old files
This commit is contained in:
@@ -1,164 +0,0 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import type { ComputedRef, WatchSource } from 'vue'
|
||||
import { logicAnd, logicNot } from '@vueuse/math'
|
||||
import { useEventListener, useDebounceFn } from '@vueuse/core'
|
||||
import { useShortcuts } from './useShortcuts'
|
||||
|
||||
export interface ShortcutConfig {
|
||||
handler: Function
|
||||
usingInput?: string | boolean
|
||||
whenever?: WatchSource<boolean>[]
|
||||
}
|
||||
|
||||
export interface ShortcutsConfig {
|
||||
[key: string]: ShortcutConfig | Function
|
||||
}
|
||||
|
||||
export interface ShortcutsOptions {
|
||||
chainDelay?: number
|
||||
}
|
||||
|
||||
interface Shortcut {
|
||||
handler: Function
|
||||
condition: ComputedRef<boolean>
|
||||
chained: boolean
|
||||
// KeyboardEvent attributes
|
||||
key: string
|
||||
ctrlKey: boolean
|
||||
metaKey: boolean
|
||||
shiftKey: boolean
|
||||
altKey: boolean
|
||||
// code?: string
|
||||
// keyCode?: number
|
||||
}
|
||||
|
||||
const chainedShortcutRegex = /^[^-]+.*-.*[^-]+$/
|
||||
const combinedShortcutRegex = /^[^_]+.*_.*[^_]+$/
|
||||
|
||||
export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptions = {}) => {
|
||||
const { macOS, usingInput } = useShortcuts()
|
||||
|
||||
let shortcuts: Shortcut[] = []
|
||||
|
||||
const chainedInputs = ref<string[]>([])
|
||||
const clearChainedInput = () => {
|
||||
chainedInputs.value.splice(0, chainedInputs.value.length)
|
||||
}
|
||||
const debouncedClearChainedInput = useDebounceFn(clearChainedInput, options.chainDelay ?? 800)
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
// Input autocomplete triggers a keydown event
|
||||
if (!e.key) { return }
|
||||
|
||||
const alphabeticalKey = /^[a-z]{1}$/i.test(e.key)
|
||||
|
||||
let chainedKey
|
||||
chainedInputs.value.push(e.key)
|
||||
// try matching a chained shortcut
|
||||
if (chainedInputs.value.length >= 2) {
|
||||
chainedKey = chainedInputs.value.slice(-2).join('-')
|
||||
|
||||
for (const shortcut of shortcuts.filter(s => s.chained)) {
|
||||
if (shortcut.key !== chainedKey) { continue }
|
||||
|
||||
if (shortcut.condition.value) {
|
||||
e.preventDefault()
|
||||
shortcut.handler()
|
||||
}
|
||||
clearChainedInput()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// try matching a standard shortcut
|
||||
for (const shortcut of shortcuts.filter(s => !s.chained)) {
|
||||
if (e.key.toLowerCase() !== shortcut.key) { continue }
|
||||
if (e.metaKey !== shortcut.metaKey) { continue }
|
||||
if (e.ctrlKey !== shortcut.ctrlKey) { continue }
|
||||
// shift modifier is only checked in combination with alphabetical keys
|
||||
// (shift with non-alphabetical keys would change the key)
|
||||
if (alphabeticalKey && e.shiftKey !== shortcut.shiftKey) { continue }
|
||||
// alt modifier changes the combined key anyways
|
||||
// if (e.altKey !== shortcut.altKey) { continue }
|
||||
|
||||
if (shortcut.condition.value) {
|
||||
e.preventDefault()
|
||||
shortcut.handler()
|
||||
}
|
||||
clearChainedInput()
|
||||
return
|
||||
}
|
||||
|
||||
debouncedClearChainedInput()
|
||||
}
|
||||
|
||||
// Map config to full detailled shortcuts
|
||||
shortcuts = Object.entries(config).map(([key, shortcutConfig]) => {
|
||||
if (!shortcutConfig) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Parse key and modifiers
|
||||
let shortcut: Partial<Shortcut>
|
||||
|
||||
if (key.includes('-') && key !== '-' && !key.match(chainedShortcutRegex)?.length) {
|
||||
console.trace(`[Shortcut] Invalid key: "${key}"`)
|
||||
}
|
||||
|
||||
if (key.includes('_') && key !== '_' && !key.match(combinedShortcutRegex)?.length) {
|
||||
console.trace(`[Shortcut] Invalid key: "${key}"`)
|
||||
}
|
||||
|
||||
const chained = key.includes('-') && key !== '-'
|
||||
if (chained) {
|
||||
shortcut = {
|
||||
key: key.toLowerCase(),
|
||||
metaKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
altKey: false
|
||||
}
|
||||
} else {
|
||||
const keySplit = key.toLowerCase().split('_').map(k => k)
|
||||
shortcut = {
|
||||
key: keySplit.filter(k => !['meta', 'ctrl', 'shift', 'alt'].includes(k)).join('_'),
|
||||
metaKey: keySplit.includes('meta'),
|
||||
ctrlKey: keySplit.includes('ctrl'),
|
||||
shiftKey: keySplit.includes('shift'),
|
||||
altKey: keySplit.includes('alt')
|
||||
}
|
||||
}
|
||||
shortcut.chained = chained
|
||||
|
||||
// Convert Meta to Ctrl for non-MacOS
|
||||
if (!macOS.value && shortcut.metaKey && !shortcut.ctrlKey) {
|
||||
shortcut.metaKey = false
|
||||
shortcut.ctrlKey = true
|
||||
}
|
||||
|
||||
// Retrieve handler function
|
||||
if (typeof shortcutConfig === 'function') {
|
||||
shortcut.handler = shortcutConfig
|
||||
} else if (typeof shortcutConfig === 'object') {
|
||||
shortcut = { ...shortcut, handler: shortcutConfig.handler }
|
||||
}
|
||||
|
||||
if (!shortcut.handler) {
|
||||
console.trace('[Shortcut] Invalid value')
|
||||
return null
|
||||
}
|
||||
|
||||
// Create shortcut computed
|
||||
const conditions: ComputedRef<boolean>[] = []
|
||||
if (!(shortcutConfig as ShortcutConfig).usingInput) {
|
||||
conditions.push(logicNot(usingInput))
|
||||
} else if (typeof (shortcutConfig as ShortcutConfig).usingInput === 'string') {
|
||||
conditions.push(computed(() => usingInput.value === (shortcutConfig as ShortcutConfig).usingInput))
|
||||
}
|
||||
shortcut.condition = logicAnd(...conditions, ...((shortcutConfig as ShortcutConfig).whenever || []))
|
||||
|
||||
return shortcut as Shortcut
|
||||
}).filter(Boolean) as Shortcut[]
|
||||
|
||||
useEventListener('keydown', onKeyDown)
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { computed, ref, provide, inject, onMounted, onUnmounted, getCurrentInstance } from 'vue'
|
||||
import type { Ref, ComponentInternalInstance } from 'vue'
|
||||
import { buttonGroup } from '#ui/ui.config'
|
||||
|
||||
type ButtonGroupProps = {
|
||||
orientation?: Ref<'horizontal' | 'vertical'>
|
||||
size?: Ref<string>
|
||||
ui?: Ref<Partial<typeof buttonGroup>>
|
||||
rounded?: Ref<{ start: string, end: string }>
|
||||
}
|
||||
|
||||
// make a ButtonGroupContext type for injection. Should include ButtonGroupProps
|
||||
type ButtonGroupContext = {
|
||||
children: ComponentInternalInstance[]
|
||||
register (child: ComponentInternalInstance): void
|
||||
unregister (child: ComponentInternalInstance): void
|
||||
orientation: 'horizontal' | 'vertical'
|
||||
size: string
|
||||
ui: Partial<typeof buttonGroup>
|
||||
rounded: { start: string, end: string }
|
||||
}
|
||||
|
||||
export function useProvideButtonGroup (buttonGroupProps: ButtonGroupProps) {
|
||||
const instance = getCurrentInstance()
|
||||
const groupKey = `group-${instance.uid}`
|
||||
const state = ref({
|
||||
children: [],
|
||||
register (child) {
|
||||
this.children.push(child)
|
||||
},
|
||||
unregister (child) {
|
||||
const index = this.children.indexOf(child)
|
||||
if (index > -1) {
|
||||
this.children.splice(index, 1)
|
||||
}
|
||||
},
|
||||
...buttonGroupProps
|
||||
})
|
||||
provide(groupKey, state as Ref<ButtonGroupContext>)
|
||||
}
|
||||
|
||||
export function useInjectButtonGroup ({ ui, props }: { ui: any, props: any }) {
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
provide('ButtonGroupContextConsumer', true)
|
||||
const isParentPartOfGroup = inject('ButtonGroupContextConsumer', false)
|
||||
|
||||
// early return if a parent is already part of the group
|
||||
if (isParentPartOfGroup) {
|
||||
return {
|
||||
size: computed(() => props.size),
|
||||
rounded: computed(() => ui.value.rounded)
|
||||
}
|
||||
}
|
||||
|
||||
let parent = instance.parent
|
||||
let groupContext: Ref<ButtonGroupContext> | undefined
|
||||
|
||||
// Traverse up the parent chain to find the nearest ButtonGroup
|
||||
while (parent && !groupContext) {
|
||||
if (parent.type.name === 'ButtonGroup') {
|
||||
groupContext = inject(`group-${parent.uid}`)
|
||||
break
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
|
||||
const positionInGroup = computed(() => groupContext?.value.children.indexOf(instance))
|
||||
onMounted(() => {
|
||||
groupContext?.value.register(instance)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
groupContext?.value.unregister(instance)
|
||||
})
|
||||
return {
|
||||
size: computed(() => groupContext?.value.size || props.size),
|
||||
rounded: computed(() => {
|
||||
if (!groupContext || positionInGroup.value === -1) return ui.value.rounded
|
||||
if (groupContext.value.children.length === 1) return groupContext.value.ui.rounded
|
||||
if (positionInGroup.value === 0) return groupContext.value.rounded.start
|
||||
if (positionInGroup.value === groupContext.value.children.length - 1) return groupContext.value.rounded.end
|
||||
return 'rounded-none'
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { ref, type Ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
export const useCarouselScroll = (el: Ref<HTMLElement>) => {
|
||||
const x = ref<number>(0)
|
||||
|
||||
function onMouseDown (e) {
|
||||
el.value.style.scrollSnapType = 'none'
|
||||
el.value.style.scrollBehavior = 'auto'
|
||||
|
||||
x.value = e.pageX
|
||||
|
||||
window.addEventListener('mousemove', onMouseMove)
|
||||
window.addEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
function onMouseUp () {
|
||||
el.value.style.removeProperty('scroll-behavior')
|
||||
el.value.style.removeProperty('scroll-snap-type')
|
||||
|
||||
window.removeEventListener('mousemove', onMouseMove)
|
||||
window.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
function onMouseMove (e) {
|
||||
e.preventDefault()
|
||||
|
||||
const delta = e.pageX - x.value
|
||||
|
||||
x.value = e.pageX
|
||||
|
||||
el.value.scrollBy(-delta, 0)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!el.value) {
|
||||
return
|
||||
}
|
||||
|
||||
el.value.addEventListener('mousedown', onMouseDown)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (!el.value) {
|
||||
return
|
||||
}
|
||||
|
||||
el.value.removeEventListener('mousedown', onMouseDown)
|
||||
})
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import type { Notification } from '../types/notification'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
export function useCopyToClipboard (options: Partial<Notification> = {}) {
|
||||
const { copy: copyToClipboard, isSupported } = useClipboard()
|
||||
const toast = useToast()
|
||||
|
||||
function copy (text: string, success: { title?: string, description?: string } = {}, failure: { title?: string, description?: string } = {}) {
|
||||
if (!isSupported) {
|
||||
return
|
||||
}
|
||||
|
||||
copyToClipboard(text).then(() => {
|
||||
if (!success.title && !success.description) {
|
||||
return
|
||||
}
|
||||
|
||||
toast.add({ ...success, ...options })
|
||||
}, function (e) {
|
||||
toast.add({
|
||||
...failure,
|
||||
description: failure.description || e.message,
|
||||
...options
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
copy
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { inject, ref, computed } from 'vue'
|
||||
import { type UseEventBusReturn, useDebounceFn } from '@vueuse/core'
|
||||
import type { FormEvent, FormEventType, InjectedFormGroupValue } from '../types/form'
|
||||
|
||||
type InputProps = {
|
||||
id?: string
|
||||
size?: string | number | symbol
|
||||
color?: string
|
||||
name?: string
|
||||
eagerValidation?: boolean
|
||||
legend?: string | null
|
||||
}
|
||||
|
||||
export const useFormGroup = (inputProps?: InputProps, config?: any) => {
|
||||
const formBus = inject<UseEventBusReturn<FormEvent, string> | undefined>('form-events', undefined)
|
||||
const formGroup = inject<InjectedFormGroupValue | undefined>('form-group', undefined)
|
||||
const formInputs = inject<any>('form-inputs', undefined)
|
||||
|
||||
if (formGroup) {
|
||||
if (inputProps?.id) {
|
||||
// Updates for="..." attribute on label if inputProps.id is provided
|
||||
formGroup.inputId.value = inputProps?.id
|
||||
}
|
||||
|
||||
if (formInputs) {
|
||||
formInputs.value[formGroup.name.value] = formGroup.inputId.value
|
||||
}
|
||||
}
|
||||
|
||||
const blurred = ref(false)
|
||||
|
||||
function emitFormEvent (type: FormEventType, path: string) {
|
||||
if (formBus) {
|
||||
formBus.emit({ type, path })
|
||||
}
|
||||
}
|
||||
|
||||
function emitFormBlur () {
|
||||
emitFormEvent('blur', formGroup?.name.value as string)
|
||||
blurred.value = true
|
||||
}
|
||||
|
||||
function emitFormChange () {
|
||||
emitFormEvent('change', formGroup?.name.value as string)
|
||||
}
|
||||
|
||||
const emitFormInput = useDebounceFn(() => {
|
||||
if (blurred.value || formGroup?.eagerValidation.value) {
|
||||
emitFormEvent('input', formGroup?.name.value as string)
|
||||
}
|
||||
}, 300)
|
||||
|
||||
return {
|
||||
inputId: computed(() => inputProps?.id ?? formGroup?.inputId.value),
|
||||
name: computed(() => inputProps?.name ?? formGroup?.name.value),
|
||||
size: computed(() => {
|
||||
const formGroupSize = config.size[formGroup?.size.value as string] ? formGroup?.size.value : null
|
||||
return inputProps?.size ?? formGroupSize ?? config?.default?.size
|
||||
}),
|
||||
color: computed(() => formGroup?.error?.value ? 'red' : inputProps?.color),
|
||||
emitFormBlur,
|
||||
emitFormInput,
|
||||
emitFormChange
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { ref, inject } from 'vue'
|
||||
import type { ShallowRef, Component, InjectionKey } from 'vue'
|
||||
import { createSharedComposable } from '@vueuse/core'
|
||||
import type { ComponentProps } from '../types/component'
|
||||
import type { Modal, ModalState } from '../types/modal'
|
||||
|
||||
export const modalInjectionKey: InjectionKey<ShallowRef<ModalState>> = Symbol('nuxt-ui.modal')
|
||||
|
||||
function _useModal () {
|
||||
const modalState = inject(modalInjectionKey)
|
||||
|
||||
const isOpen = ref(false)
|
||||
|
||||
function open<T extends Component> (component: T, props?: Modal & ComponentProps<T>) {
|
||||
modalState.value = {
|
||||
component,
|
||||
props: props ?? {}
|
||||
}
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
function close () {
|
||||
isOpen.value = false
|
||||
modalState.value = {
|
||||
component: 'div',
|
||||
props: {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows updating the modal props
|
||||
*/
|
||||
function patch <T extends Component = {}> (props: Partial<Modal & ComponentProps<T>>) {
|
||||
modalState.value = {
|
||||
...modalState.value,
|
||||
props: {
|
||||
...modalState.value.props,
|
||||
...props
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
open,
|
||||
close,
|
||||
patch
|
||||
}
|
||||
}
|
||||
|
||||
export const useModal = createSharedComposable(_useModal)
|
||||
@@ -1,102 +0,0 @@
|
||||
import { ref, onMounted, watchEffect } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { popperGenerator, defaultModifiers } from '@popperjs/core/lib/popper-lite'
|
||||
import type { VirtualElement } from '@popperjs/core/lib/popper-lite'
|
||||
import type { Instance } from '@popperjs/core'
|
||||
import flip from '@popperjs/core/lib/modifiers/flip'
|
||||
import offset from '@popperjs/core/lib/modifiers/offset'
|
||||
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow'
|
||||
import computeStyles from '@popperjs/core/lib/modifiers/computeStyles'
|
||||
import eventListeners from '@popperjs/core/lib/modifiers/eventListeners'
|
||||
import arrowModifier from '@popperjs/core/lib/modifiers/arrow'
|
||||
import { unrefElement } from '@vueuse/core'
|
||||
import type { MaybeElement } from '@vueuse/core'
|
||||
import type { PopperOptions } from '../types/popper'
|
||||
|
||||
export const createPopper = popperGenerator({
|
||||
defaultModifiers: [...defaultModifiers, offset, flip, preventOverflow, computeStyles, eventListeners, arrowModifier]
|
||||
})
|
||||
|
||||
export function usePopper ({
|
||||
locked = false,
|
||||
overflowPadding = 8,
|
||||
offsetDistance = 8,
|
||||
offsetSkid = 0,
|
||||
gpuAcceleration = true,
|
||||
adaptive = true,
|
||||
scroll = true,
|
||||
resize = true,
|
||||
arrow = false,
|
||||
placement,
|
||||
strategy
|
||||
}: PopperOptions, virtualReference?: Ref<Element | VirtualElement>) {
|
||||
const reference = ref<MaybeElement>(null)
|
||||
const popper = ref<MaybeElement>(null)
|
||||
const instance = ref<Instance | null>(null)
|
||||
|
||||
onMounted(() => {
|
||||
watchEffect((onInvalidate) => {
|
||||
if (!popper.value) { return }
|
||||
if (!reference.value && !virtualReference?.value) { return }
|
||||
|
||||
const popperEl = unrefElement(popper)
|
||||
const referenceEl = virtualReference?.value || unrefElement(reference)
|
||||
|
||||
// if (!(referenceEl instanceof HTMLElement)) { return }
|
||||
if (!(popperEl instanceof HTMLElement)) { return }
|
||||
if (!referenceEl) { return }
|
||||
|
||||
const config: Record<string, any> = {
|
||||
modifiers: [
|
||||
{
|
||||
name: 'flip',
|
||||
enabled: !locked
|
||||
},
|
||||
{
|
||||
name: 'preventOverflow',
|
||||
options: {
|
||||
padding: overflowPadding
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [offsetSkid, offsetDistance]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'computeStyles',
|
||||
options: {
|
||||
adaptive,
|
||||
gpuAcceleration
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'eventListeners',
|
||||
options: {
|
||||
scroll,
|
||||
resize
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'arrow',
|
||||
enabled: arrow
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (placement) {
|
||||
config.placement = placement
|
||||
}
|
||||
if (strategy) {
|
||||
config.strategy = strategy
|
||||
}
|
||||
|
||||
instance.value = createPopper(referenceEl, popperEl, config)
|
||||
|
||||
onInvalidate(instance.value.destroy)
|
||||
})
|
||||
})
|
||||
|
||||
return [reference, popper, instance] as const
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { createSharedComposable, useActiveElement } from '@vueuse/core'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import type {} from '@vueuse/shared'
|
||||
|
||||
export const _useShortcuts = () => {
|
||||
const macOS = computed(() => import.meta.client && navigator && navigator.userAgent && navigator.userAgent.match(/Macintosh;/))
|
||||
|
||||
const metaSymbol = ref(' ')
|
||||
|
||||
const activeElement = useActiveElement()
|
||||
const usingInput = computed(() => {
|
||||
const tagName = activeElement.value?.tagName
|
||||
const contentEditable = activeElement.value?.contentEditable
|
||||
|
||||
const usingInput = !!(tagName === 'INPUT' || tagName === 'TEXTAREA' || contentEditable === 'true' || contentEditable === 'plaintext-only')
|
||||
|
||||
if (usingInput) {
|
||||
return ((activeElement.value as any)?.name as string) || true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
metaSymbol.value = macOS.value ? '⌘' : 'Ctrl'
|
||||
})
|
||||
|
||||
return {
|
||||
macOS,
|
||||
metaSymbol,
|
||||
activeElement,
|
||||
usingInput
|
||||
}
|
||||
}
|
||||
|
||||
export const useShortcuts = createSharedComposable(_useShortcuts)
|
||||
@@ -1,55 +0,0 @@
|
||||
import { ref, inject } from 'vue'
|
||||
import { createSharedComposable } from '@vueuse/core'
|
||||
import type { ShallowRef, Component, InjectionKey } from 'vue'
|
||||
import type { ComponentProps } from '../types/component'
|
||||
import type { Slideover, SlideoverState } from '../types/slideover'
|
||||
|
||||
export const slidOverInjectionKey: InjectionKey<ShallowRef<SlideoverState>> =
|
||||
Symbol('nuxt-ui.slideover')
|
||||
|
||||
function _useSlideover () {
|
||||
const slideoverState = inject(slidOverInjectionKey)
|
||||
const isOpen = ref(false)
|
||||
|
||||
function open<T extends Component> (component: T, props?: Slideover & ComponentProps<T>) {
|
||||
if (!slideoverState) {
|
||||
throw new Error('useSlideover() is called without provider')
|
||||
}
|
||||
|
||||
slideoverState.value = {
|
||||
component,
|
||||
props: props ?? {}
|
||||
}
|
||||
|
||||
isOpen.value = true
|
||||
}
|
||||
|
||||
function close () {
|
||||
if (!slideoverState) return
|
||||
|
||||
isOpen.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows updating the slideover props
|
||||
*/
|
||||
function patch<T extends Component = {}> (props: Partial<Slideover & ComponentProps<T>>) {
|
||||
if (!slideoverState) return
|
||||
|
||||
slideoverState.value = {
|
||||
...slideoverState.value,
|
||||
props: {
|
||||
...slideoverState.value.props,
|
||||
...props
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
open,
|
||||
close,
|
||||
patch,
|
||||
isOpen
|
||||
}
|
||||
}
|
||||
|
||||
export const useSlideover = createSharedComposable(_useSlideover)
|
||||
@@ -1,63 +0,0 @@
|
||||
import { ref, computed } from 'vue-demi'
|
||||
import { useTimestamp } from '@vueuse/core'
|
||||
import type { UseTimestampOptions } from '@vueuse/core'
|
||||
|
||||
export function useTimer (cb: (...args: unknown[]) => any, interval: number, options?: UseTimestampOptions<true>) {
|
||||
let timer: number | null = null
|
||||
const { pause: tPause, resume: tResume, timestamp } = useTimestamp({ ...(options || {}), controls: true })
|
||||
const startTime = ref<number | null>(null)
|
||||
|
||||
const remaining = computed(() => {
|
||||
if (!startTime.value) {
|
||||
return 0
|
||||
}
|
||||
return interval - (timestamp.value - startTime.value)
|
||||
})
|
||||
|
||||
function set (...args: unknown[]) {
|
||||
timer = setTimeout(() => {
|
||||
timer = null
|
||||
startTime.value = null
|
||||
cb(...args)
|
||||
}, remaining.value) as unknown as number
|
||||
}
|
||||
|
||||
function clear () {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
|
||||
function start () {
|
||||
startTime.value = Date.now()
|
||||
|
||||
set()
|
||||
}
|
||||
|
||||
function stop () {
|
||||
clear()
|
||||
tPause()
|
||||
}
|
||||
|
||||
function pause () {
|
||||
clear()
|
||||
tPause()
|
||||
}
|
||||
|
||||
function resume () {
|
||||
set()
|
||||
tResume()
|
||||
startTime.value = (startTime.value || 0) + (Date.now() - timestamp.value)
|
||||
}
|
||||
|
||||
start()
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
pause,
|
||||
resume,
|
||||
remaining
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import type { Notification } from '../types/notification'
|
||||
import { useState } from '#imports'
|
||||
|
||||
export function useToast () {
|
||||
const notifications = useState<Notification[]>('notifications', () => [])
|
||||
|
||||
function add (notification: Partial<Notification>) {
|
||||
const body = {
|
||||
id: new Date().getTime().toString(),
|
||||
...notification
|
||||
}
|
||||
|
||||
const index = notifications.value.findIndex((n: Notification) => n.id === body.id)
|
||||
if (index === -1) {
|
||||
notifications.value.push(body as Notification)
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
function remove (id: string) {
|
||||
notifications.value = notifications.value.filter((n: Notification) => n.id !== id)
|
||||
}
|
||||
|
||||
return {
|
||||
add,
|
||||
remove
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { computed, toValue, useAttrs } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { mergeConfig, omit, get } from '../utils'
|
||||
import type { Strategy } from '../types'
|
||||
|
||||
export const useUI = <T>(key, $ui?: Ref<Partial<T> & { strategy?: Strategy } | undefined>, $config?: Ref<T> | T, $wrapperClass?: Ref<string>, withAppConfig: boolean = false) => {
|
||||
const $attrs = useAttrs()
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed(() => {
|
||||
const _ui = toValue($ui)
|
||||
const _config = toValue($config)
|
||||
const _wrapperClass = toValue($wrapperClass)
|
||||
|
||||
return mergeConfig<T>(
|
||||
_ui?.strategy || (appConfig.ui?.strategy as Strategy),
|
||||
_wrapperClass ? { wrapper: _wrapperClass } : {},
|
||||
_ui || {},
|
||||
(process.dev || withAppConfig) ? get(appConfig.ui, key, {}) : {},
|
||||
_config || {}
|
||||
)
|
||||
})
|
||||
|
||||
const attrs = computed(() => omit($attrs, ['class']))
|
||||
|
||||
return {
|
||||
ui,
|
||||
attrs
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user