@quasar/quasar-ui-qcalendar
Version:
QCalendar - Day/Month/Week Calendars, Popups, Date Pickers, Schedules, Agendas, Planners and Tasks for your Vue Apps
167 lines (152 loc) • 5.59 kB
text/typescript
import { EmitFn } from 'vue'
import { EmitListeners } from './useEmitListeners'
/**
* Converts a kebab-case string to camelCase.
* @param {string} str - The kebab-case string.
* @returns {string} - The camelCase formatted string.
*/
const toCamelCase = (str: string): string => str.replace(/(-\w)/g, (m) => m[1].toUpperCase())
/**
* Defines the structure for a mouse event configuration.
*/
interface MouseEventOptions {
event: string
button?: number
prevent?: boolean
stop?: boolean
result?: any
}
/**
* Defines a function signature for event transformation.
*/
type GetEventFunction = (_event: MouseEvent | TouchEvent, _eventName: string) => any
/**
* Generates mouse event handlers based on event listeners.
* @param {Function} emit - Vue's emit function.
* @param {Ref<Listeners>} listeners - Vue ref containing event listeners.
* @param {Record<string, MouseEventOptions>} events - Object defining mouse events and their options.
* @param {GetEventFunction} getEvent - Function to transform event objects.
* @returns {Record<string, Function | Function[]>} - The mapped mouse event handlers.
*/
export function getMouseEventHandlers(
emit: EmitFn,
listeners: EmitListeners,
events: Record<string, MouseEventOptions>,
getEvent: GetEventFunction,
): Record<string, Function | Function[]> {
const on: Record<string, Function | Function[]> = {}
for (const eventName in events) {
const eventOptions = events[eventName]
const eventKey = toCamelCase('on-' + eventName)
if (!listeners.value) {
console.warn('$listeners has not been set up')
return {}
}
if (listeners.value[eventKey] === undefined) continue
const key = 'on' + eventOptions.event.charAt(0).toUpperCase() + eventOptions.event.slice(1)
const handler = (event: MouseEvent | TouchEvent): any => {
if (
eventOptions.button === undefined ||
('buttons' in event && event.buttons > 0 && event.button === eventOptions.button)
) {
if (eventOptions.prevent) {
event.preventDefault()
}
if (eventOptions.stop) {
event.stopPropagation()
}
emit(eventName, getEvent(event, eventName))
}
return eventOptions.result
}
if (key in on) {
if (Array.isArray(on[key])) {
;(on[key] as Function[]).push(handler)
} else {
on[key] = [on[key] as Function, handler]
}
} else {
on[key] = handler
}
}
return on
}
/**
* Returns default mouse event handlers based on a suffix.
* @param {Function} emit - Vue's emit function.
* @param {Ref<Listeners>} listeners - Vue ref containing event listeners.
* @param {string} suffix - Event suffix (e.g., '-day' for 'click-day').
* @param {GetEventFunction} getEvent - Function to transform event objects.
* @returns {Record<string, Function | Function[]>} - The mapped event handlers.
*/
export function getDefaultMouseEventHandlers(
emit: EmitFn,
listeners: EmitListeners,
suffix: string,
getEvent: GetEventFunction,
): Record<string, Function | Function[]> {
return getMouseEventHandlers(emit, listeners, getMouseEventName(suffix), getEvent)
}
/**
* Generates event names for different mouse interactions.
* @param {string} suffix - Event suffix (e.g., '-day' for 'click-day').
* @returns {Record<string, MouseEventOptions>} - The event name map.
*/
export function getMouseEventName(suffix: string): Record<string, MouseEventOptions> {
return {
['click' + suffix]: { event: 'click' },
['contextmenu' + suffix]: { event: 'contextmenu', prevent: true, result: false },
['mousedown' + suffix]: { event: 'mousedown' },
['mousemove' + suffix]: { event: 'mousemove' },
['mouseup' + suffix]: { event: 'mouseup' },
['mouseenter' + suffix]: { event: 'mouseenter' },
['mouseleave' + suffix]: { event: 'mouseleave' },
['touchstart' + suffix]: { event: 'touchstart' },
['touchmove' + suffix]: { event: 'touchmove' },
['touchend' + suffix]: { event: 'touchend' },
}
}
/**
* Returns an array of raw event names based on a suffix.
* @param {string} suffix - Event suffix.
* @returns {string[]} - The raw event names.
*/
export function getRawMouseEvents(suffix: string): string[] {
return Object.keys(getMouseEventName(suffix))
}
/**
* Default function export that provides mouse event handling utilities.
* @param {Function} emit - Vue's emit function.
* @param {Ref<Listeners>} listeners - Vue ref containing event listeners.
* @returns {Object} - Functions for managing mouse event handlers.
*/
export default function useMouseEvents(
emit: EmitFn,
listeners: EmitListeners,
): {
getMouseEventHandlers: (
_events: Record<string, MouseEventOptions>,
_getEvent: GetEventFunction,
) => Record<string, Function | Function[]>
getDefaultMouseEventHandlers: (
_suffix: string,
_getEvent: GetEventFunction,
) => Record<string, Function | Function[]>
getMouseEventName: (_suffix: string) => Record<string, MouseEventOptions>
getRawMouseEvents: (_suffix: string) => string[]
} {
return {
getMouseEventHandlers: (
events: Record<string, MouseEventOptions>,
getEvent: GetEventFunction,
): Record<string, Function | Function[]> =>
getMouseEventHandlers(emit, listeners, events, getEvent),
getDefaultMouseEventHandlers: (
suffix: string,
getEvent: GetEventFunction,
): Record<string, Function | Function[]> =>
getDefaultMouseEventHandlers(emit, listeners, suffix, getEvent),
getMouseEventName,
getRawMouseEvents,
}
}