routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
import type { DirectiveBinding } from 'vue';
interface ClickOutsideBindingArgs {
handler: (e: MouseEvent) => void;
closeConditional?: (e: Event) => boolean;
include?: () => HTMLElement[];
}
interface ClickOutsideDirectiveBinding extends DirectiveBinding {
value: ((e: MouseEvent) => void) | ClickOutsideBindingArgs;
}
export declare const ClickOutside: {
mounted(el: HTMLElement, binding: ClickOutsideDirectiveBinding): void;
beforeUnmount(el: HTMLElement, binding: ClickOutsideDirectiveBinding): void;
};
export default ClickOutside;
+92
View File
@@ -0,0 +1,92 @@
// Utilities
import { attachedRoot } from "../../util/index.js"; // Types
function defaultConditional() {
return true;
}
function checkEvent(e, el, binding) {
// The include element callbacks below can be expensive
// so we should avoid calling them when we're not active.
// Explicitly check for false to allow fallback compatibility
// with non-toggleable components
if (!e || checkIsActive(e, binding) === false) return false;
// If we're clicking inside the shadowroot, then the app root doesn't get the same
// level of introspection as to _what_ we're clicking. We want to check to see if
// our target is the shadowroot parent container, and if it is, ignore.
const root = attachedRoot(el);
if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;
// Check if additional elements were passed to be included in check
// (click must be outside all included elements, if any)
const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
// Add the root element for the component this directive was defined on
elements.push(el);
// Check if it's a click outside our elements, and then if our callback returns true.
// Non-toggleable components should take action in their callback and return falsy.
// Toggleable can return true if it wants to deactivate.
// Note that, because we're in the capture phase, this callback will occur before
// the bubbling click event on any outside elements.
return !elements.some(el => el?.contains(e.target));
}
function checkIsActive(e, binding) {
const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
return isActive(e);
}
function directive(e, el, binding) {
const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;
// Clicks in the Shadow DOM change their target while using setTimeout, so the original target is saved here
e.shadowTarget = e.target;
el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
checkIsActive(e, binding) && handler && handler(e);
}, 0);
}
function handleShadow(el, callback) {
const root = attachedRoot(el);
callback(document);
if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
callback(root);
}
}
export const ClickOutside = {
// [data-app] may not be found
// if using bind, inserted makes
// sure that the root element is
// available, iOS does not support
// clicks on body
mounted(el, binding) {
const onClick = e => directive(e, el, binding);
const onMousedown = e => {
el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding);
};
handleShadow(el, app => {
app.addEventListener('click', onClick, true);
app.addEventListener('mousedown', onMousedown, true);
});
if (!el._clickOutside) {
el._clickOutside = {
lastMousedownWasOutside: false
};
}
el._clickOutside[binding.instance.$.uid] = {
onClick,
onMousedown
};
},
beforeUnmount(el, binding) {
if (!el._clickOutside) return;
handleShadow(el, app => {
if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
const {
onClick,
onMousedown
} = el._clickOutside[binding.instance.$.uid];
app.removeEventListener('click', onClick, true);
app.removeEventListener('mousedown', onMousedown, true);
});
delete el._clickOutside[binding.instance.$.uid];
}
};
export default ClickOutside;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
+8
View File
@@ -0,0 +1,8 @@
import { VNode, VNodeDirective } from 'vue';
declare function updateColor(el: HTMLElement, binding: VNodeDirective, node: VNode): void;
declare function update(el: HTMLElement, binding: VNodeDirective, node: VNode): void;
export declare const Color: {
bind: typeof updateColor;
update: typeof update;
};
export default Color;
+51
View File
@@ -0,0 +1,51 @@
// @ts-nocheck
/* eslint-disable */
// Utilities
import { classToHex, isCssColor, parseGradient } from "../../util/colorUtils.js";
import colors from "../../util/colors.js"; // Types
function setTextColor(el, color, currentTheme) {
const cssColor = !isCssColor(color) ? classToHex(color, colors, currentTheme) : color;
el.style.color = cssColor;
el.style.caretColor = cssColor;
}
function setBackgroundColor(el, color, currentTheme) {
const cssColor = !isCssColor(color) ? classToHex(color, colors, currentTheme) : color;
el.style.backgroundColor = cssColor;
el.style.borderColor = cssColor;
}
function setBorderColor(el, color, currentTheme, modifiers) {
const cssColor = !isCssColor(color) ? classToHex(color, colors, currentTheme) : color;
if (!modifiers || !Object.keys(modifiers).length) {
el.style.borderColor = cssColor;
return;
}
if (modifiers.top) el.style.borderTopColor = cssColor;
if (modifiers.right) el.style.borderRightColor = cssColor;
if (modifiers.bottom) el.style.borderBottomColor = cssColor;
if (modifiers.left) el.style.borderLeftColor = cssColor;
}
function setGradientColor(el, gradient, currentTheme) {
el.style.backgroundImage = `linear-gradient(${parseGradient(gradient, colors, currentTheme)})`;
}
function updateColor(el, binding, node) {
const currentTheme = node.context.$vuetify.theme.currentTheme;
if (binding.arg === undefined) {
setBackgroundColor(el, binding.value, currentTheme);
} else if (binding.arg === 'text') {
setTextColor(el, binding.value, currentTheme);
} else if (binding.arg === 'border') {
setBorderColor(el, binding.value, currentTheme, binding.modifiers);
} else if (binding.arg === 'gradient') {
setGradientColor(el, binding.value, currentTheme);
}
}
function update(el, binding, node) {
if (binding.value === binding.oldValue) return;
updateColor(el, binding, node);
}
export const Color = {
bind: updateColor,
update
};
export default Color;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
+8
View File
@@ -0,0 +1,8 @@
export { ClickOutside } from './click-outside/index.js';
export { Intersect } from './intersect/index.js';
export { Mutate } from './mutate/index.js';
export { Resize } from './resize/index.js';
export { Ripple } from './ripple/index.js';
export { Scroll } from './scroll/index.js';
export { Touch } from './touch/index.js';
export { Tooltip } from './tooltip/index.js';
+9
View File
@@ -0,0 +1,9 @@
export { ClickOutside } from "./click-outside/index.js"; // export { Color } from './color'
export { Intersect } from "./intersect/index.js";
export { Mutate } from "./mutate/index.js";
export { Resize } from "./resize/index.js";
export { Ripple } from "./ripple/index.js";
export { Scroll } from "./scroll/index.js";
export { Touch } from "./touch/index.js";
export { Tooltip } from "./tooltip/index.js";
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["ClickOutside","Intersect","Mutate","Resize","Ripple","Scroll","Touch","Tooltip"],"sources":["../../src/directives/index.ts"],"sourcesContent":["export { ClickOutside } from './click-outside'\n// export { Color } from './color'\nexport { Intersect } from './intersect'\nexport { Mutate } from './mutate'\nexport { Resize } from './resize'\nexport { Ripple } from './ripple'\nexport { Scroll } from './scroll'\nexport { Touch } from './touch'\nexport { Tooltip } from './tooltip'\n"],"mappings":"SAASA,YAAY,oCACrB;AAAA,SACSC,SAAS;AAAA,SACTC,MAAM;AAAA,SACNC,MAAM;AAAA,SACNC,MAAM;AAAA,SACNC,MAAM;AAAA,SACNC,KAAK;AAAA,SACLC,OAAO","ignoreList":[]}
+20
View File
@@ -0,0 +1,20 @@
import type { DirectiveBinding } from 'vue';
type ObserveHandler = (isIntersecting: boolean, entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void;
export interface ObserveDirectiveBinding extends Omit<DirectiveBinding, 'modifiers' | 'value'> {
value?: ObserveHandler | {
handler: ObserveHandler;
options?: IntersectionObserverInit;
};
modifiers: {
once?: boolean;
quiet?: boolean;
};
}
declare function mounted(el: HTMLElement, binding: ObserveDirectiveBinding): void;
declare function unmounted(el: HTMLElement, binding: ObserveDirectiveBinding): void;
export declare const Intersect: {
mounted: typeof mounted;
unmounted: typeof unmounted;
updated: (el: HTMLElement, binding: ObserveDirectiveBinding) => void;
};
export default Intersect;
+51
View File
@@ -0,0 +1,51 @@
// Utilities
import { SUPPORTS_INTERSECTION } from "../../util/index.js"; // Types
function mounted(el, binding) {
if (!SUPPORTS_INTERSECTION) return;
const modifiers = binding.modifiers || {};
const value = binding.value;
const {
handler,
options
} = typeof value === 'object' ? value : {
handler: value,
options: {}
};
const observer = new IntersectionObserver((entries = [], observer) => {
const _observe = el._observe?.[binding.instance.$.uid];
if (!_observe) return; // Just in case, should never fire
const isIntersecting = entries.some(entry => entry.isIntersecting);
// If is not quiet or has already been
// initted, invoke the user callback
if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
handler(isIntersecting, entries, observer);
}
if (isIntersecting && modifiers.once) unmounted(el, binding);else _observe.init = true;
}, options);
el._observe = Object(el._observe);
el._observe[binding.instance.$.uid] = {
init: false,
observer
};
observer.observe(el);
}
function unmounted(el, binding) {
const observe = el._observe?.[binding.instance.$.uid];
if (!observe) return;
observe.observer.unobserve(el);
delete el._observe[binding.instance.$.uid];
}
export const Intersect = {
mounted,
unmounted,
updated: (el, binding) => {
if (el._observe?.[binding.instance.$.uid]) {
unmounted(el, binding);
mounted(el, binding);
}
}
};
export default Intersect;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["SUPPORTS_INTERSECTION","mounted","el","binding","modifiers","value","handler","options","observer","IntersectionObserver","entries","_observe","instance","$","uid","isIntersecting","some","entry","quiet","init","once","unmounted","Object","observe","unobserve","Intersect","updated"],"sources":["../../../src/directives/intersect/index.ts"],"sourcesContent":["// Utilities\nimport { SUPPORTS_INTERSECTION } from '@/util'\n\n// Types\nimport type {\n DirectiveBinding,\n} from 'vue'\n\ntype ObserveHandler = (\n isIntersecting: boolean,\n entries: IntersectionObserverEntry[],\n observer: IntersectionObserver,\n) => void\n\nexport interface ObserveDirectiveBinding extends Omit<DirectiveBinding, 'modifiers' | 'value'> {\n value?: ObserveHandler | { handler: ObserveHandler, options?: IntersectionObserverInit }\n modifiers: {\n once?: boolean\n quiet?: boolean\n }\n}\n\nfunction mounted (el: HTMLElement, binding: ObserveDirectiveBinding) {\n if (!SUPPORTS_INTERSECTION) return\n\n const modifiers = binding.modifiers || {}\n const value = binding.value\n const { handler, options } = typeof value === 'object'\n ? value\n : { handler: value, options: {} }\n\n const observer = new IntersectionObserver((\n entries: IntersectionObserverEntry[] = [],\n observer: IntersectionObserver\n ) => {\n const _observe = el._observe?.[binding.instance!.$.uid]\n if (!_observe) return // Just in case, should never fire\n\n const isIntersecting = entries.some(entry => entry.isIntersecting)\n\n // If is not quiet or has already been\n // initted, invoke the user callback\n if (\n handler && (\n !modifiers.quiet ||\n _observe.init\n ) && (\n !modifiers.once ||\n isIntersecting ||\n _observe.init\n )\n ) {\n handler(isIntersecting, entries, observer)\n }\n\n if (isIntersecting && modifiers.once) unmounted(el, binding)\n else _observe.init = true\n }, options)\n\n el._observe = Object(el._observe)\n el._observe![binding.instance!.$.uid] = { init: false, observer }\n\n observer.observe(el)\n}\n\nfunction unmounted (el: HTMLElement, binding: ObserveDirectiveBinding) {\n const observe = el._observe?.[binding.instance!.$.uid]\n if (!observe) return\n\n observe.observer.unobserve(el)\n delete el._observe![binding.instance!.$.uid]\n}\n\nexport const Intersect = {\n mounted,\n unmounted,\n updated: (el: HTMLElement, binding: ObserveDirectiveBinding) => {\n if (el._observe?.[binding.instance!.$.uid]) {\n unmounted(el, binding)\n mounted(el, binding)\n }\n },\n}\n\nexport default Intersect\n"],"mappings":"AAAA;AAAA,SACSA,qBAAqB,+BAE9B;AAmBA,SAASC,OAAOA,CAAEC,EAAe,EAAEC,OAAgC,EAAE;EACnE,IAAI,CAACH,qBAAqB,EAAE;EAE5B,MAAMI,SAAS,GAAGD,OAAO,CAACC,SAAS,IAAI,CAAC,CAAC;EACzC,MAAMC,KAAK,GAAGF,OAAO,CAACE,KAAK;EAC3B,MAAM;IAAEC,OAAO;IAAEC;EAAQ,CAAC,GAAG,OAAOF,KAAK,KAAK,QAAQ,GAClDA,KAAK,GACL;IAAEC,OAAO,EAAED,KAAK;IAAEE,OAAO,EAAE,CAAC;EAAE,CAAC;EAEnC,MAAMC,QAAQ,GAAG,IAAIC,oBAAoB,CAAC,CACxCC,OAAoC,GAAG,EAAE,EACzCF,QAA8B,KAC3B;IACH,MAAMG,QAAQ,GAAGT,EAAE,CAACS,QAAQ,GAAGR,OAAO,CAACS,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;IACvD,IAAI,CAACH,QAAQ,EAAE,OAAM,CAAC;;IAEtB,MAAMI,cAAc,GAAGL,OAAO,CAACM,IAAI,CAACC,KAAK,IAAIA,KAAK,CAACF,cAAc,CAAC;;IAElE;IACA;IACA,IACET,OAAO,KACL,CAACF,SAAS,CAACc,KAAK,IAChBP,QAAQ,CAACQ,IAAI,CACd,KACC,CAACf,SAAS,CAACgB,IAAI,IACfL,cAAc,IACdJ,QAAQ,CAACQ,IAAI,CACd,EACD;MACAb,OAAO,CAACS,cAAc,EAAEL,OAAO,EAAEF,QAAQ,CAAC;IAC5C;IAEA,IAAIO,cAAc,IAAIX,SAAS,CAACgB,IAAI,EAAEC,SAAS,CAACnB,EAAE,EAAEC,OAAO,CAAC,MACvDQ,QAAQ,CAACQ,IAAI,GAAG,IAAI;EAC3B,CAAC,EAAEZ,OAAO,CAAC;EAEXL,EAAE,CAACS,QAAQ,GAAGW,MAAM,CAACpB,EAAE,CAACS,QAAQ,CAAC;EACjCT,EAAE,CAACS,QAAQ,CAAER,OAAO,CAACS,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,GAAG;IAAEK,IAAI,EAAE,KAAK;IAAEX;EAAS,CAAC;EAEjEA,QAAQ,CAACe,OAAO,CAACrB,EAAE,CAAC;AACtB;AAEA,SAASmB,SAASA,CAAEnB,EAAe,EAAEC,OAAgC,EAAE;EACrE,MAAMoB,OAAO,GAAGrB,EAAE,CAACS,QAAQ,GAAGR,OAAO,CAACS,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;EACtD,IAAI,CAACS,OAAO,EAAE;EAEdA,OAAO,CAACf,QAAQ,CAACgB,SAAS,CAACtB,EAAE,CAAC;EAC9B,OAAOA,EAAE,CAACS,QAAQ,CAAER,OAAO,CAACS,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;AAC9C;AAEA,OAAO,MAAMW,SAAS,GAAG;EACvBxB,OAAO;EACPoB,SAAS;EACTK,OAAO,EAAEA,CAACxB,EAAe,EAAEC,OAAgC,KAAK;IAC9D,IAAID,EAAE,CAACS,QAAQ,GAAGR,OAAO,CAACS,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,EAAE;MAC1CO,SAAS,CAACnB,EAAE,EAAEC,OAAO,CAAC;MACtBF,OAAO,CAACC,EAAE,EAAEC,OAAO,CAAC;IACtB;EACF;AACF,CAAC;AAED,eAAesB,SAAS","ignoreList":[]}
+16
View File
@@ -0,0 +1,16 @@
import type { DirectiveBinding } from 'vue';
import type { MutationOptions } from '../../composables/mutationObserver.js';
export interface MutationDirectiveBinding extends Omit<DirectiveBinding, 'modifiers' | 'value'> {
value: MutationCallback | {
handler: MutationCallback;
options?: MutationObserverInit;
};
modifiers: MutationOptions;
}
declare function mounted(el: HTMLElement, binding: MutationDirectiveBinding): void;
declare function unmounted(el: HTMLElement, binding: MutationDirectiveBinding): void;
export declare const Mutate: {
mounted: typeof mounted;
unmounted: typeof unmounted;
};
export default Mutate;
+45
View File
@@ -0,0 +1,45 @@
// Types
function mounted(el, binding) {
const modifiers = binding.modifiers || {};
const value = binding.value;
const {
once,
immediate,
...modifierKeys
} = modifiers;
const defaultValue = !Object.keys(modifierKeys).length;
const {
handler,
options
} = typeof value === 'object' ? value : {
handler: value,
options: {
attributes: modifierKeys?.attr ?? defaultValue,
characterData: modifierKeys?.char ?? defaultValue,
childList: modifierKeys?.child ?? defaultValue,
subtree: modifierKeys?.sub ?? defaultValue
}
};
const observer = new MutationObserver((mutations = [], observer) => {
handler?.(mutations, observer);
if (once) unmounted(el, binding);
});
if (immediate) handler?.([], observer);
el._mutate = Object(el._mutate);
el._mutate[binding.instance.$.uid] = {
observer
};
observer.observe(el, options);
}
function unmounted(el, binding) {
if (!el._mutate?.[binding.instance.$.uid]) return;
el._mutate[binding.instance.$.uid].observer.disconnect();
delete el._mutate[binding.instance.$.uid];
}
export const Mutate = {
mounted,
unmounted
};
export default Mutate;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["mounted","el","binding","modifiers","value","once","immediate","modifierKeys","defaultValue","Object","keys","length","handler","options","attributes","attr","characterData","char","childList","child","subtree","sub","observer","MutationObserver","mutations","unmounted","_mutate","instance","$","uid","observe","disconnect","Mutate"],"sources":["../../../src/directives/mutate/index.ts"],"sourcesContent":["// Types\nimport type { DirectiveBinding } from 'vue'\nimport type { MutationOptions } from '@/composables/mutationObserver'\n\nexport interface MutationDirectiveBinding extends Omit<DirectiveBinding, 'modifiers' | 'value'> {\n value: MutationCallback | { handler: MutationCallback, options?: MutationObserverInit }\n modifiers: MutationOptions\n}\n\nfunction mounted (el: HTMLElement, binding: MutationDirectiveBinding) {\n const modifiers = binding.modifiers || {}\n const value = binding.value\n const { once, immediate, ...modifierKeys } = modifiers\n const defaultValue = !Object.keys(modifierKeys).length\n\n const { handler, options } = typeof value === 'object'\n ? value\n : {\n handler: value,\n options: {\n attributes: modifierKeys?.attr ?? defaultValue,\n characterData: modifierKeys?.char ?? defaultValue,\n childList: modifierKeys?.child ?? defaultValue,\n subtree: modifierKeys?.sub ?? defaultValue,\n },\n }\n\n const observer = new MutationObserver((\n mutations: MutationRecord[] = [],\n observer: MutationObserver\n ) => {\n handler?.(mutations, observer)\n\n if (once) unmounted(el, binding)\n })\n\n if (immediate) handler?.([], observer)\n\n el._mutate = Object(el._mutate)\n el._mutate![binding.instance!.$.uid] = { observer }\n\n observer.observe(el, options)\n}\n\nfunction unmounted (el: HTMLElement, binding: MutationDirectiveBinding) {\n if (!el._mutate?.[binding.instance!.$.uid]) return\n\n el._mutate[binding.instance!.$.uid]!.observer.disconnect()\n delete el._mutate[binding.instance!.$.uid]\n}\n\nexport const Mutate = {\n mounted,\n unmounted,\n}\n\nexport default Mutate\n"],"mappings":"AAAA;;AASA,SAASA,OAAOA,CAAEC,EAAe,EAAEC,OAAiC,EAAE;EACpE,MAAMC,SAAS,GAAGD,OAAO,CAACC,SAAS,IAAI,CAAC,CAAC;EACzC,MAAMC,KAAK,GAAGF,OAAO,CAACE,KAAK;EAC3B,MAAM;IAAEC,IAAI;IAAEC,SAAS;IAAE,GAAGC;EAAa,CAAC,GAAGJ,SAAS;EACtD,MAAMK,YAAY,GAAG,CAACC,MAAM,CAACC,IAAI,CAACH,YAAY,CAAC,CAACI,MAAM;EAEtD,MAAM;IAAEC,OAAO;IAAEC;EAAQ,CAAC,GAAG,OAAOT,KAAK,KAAK,QAAQ,GAClDA,KAAK,GACL;IACAQ,OAAO,EAAER,KAAK;IACdS,OAAO,EAAE;MACPC,UAAU,EAAEP,YAAY,EAAEQ,IAAI,IAAIP,YAAY;MAC9CQ,aAAa,EAAET,YAAY,EAAEU,IAAI,IAAIT,YAAY;MACjDU,SAAS,EAAEX,YAAY,EAAEY,KAAK,IAAIX,YAAY;MAC9CY,OAAO,EAAEb,YAAY,EAAEc,GAAG,IAAIb;IAChC;EACF,CAAC;EAEH,MAAMc,QAAQ,GAAG,IAAIC,gBAAgB,CAAC,CACpCC,SAA2B,GAAG,EAAE,EAChCF,QAA0B,KACvB;IACHV,OAAO,GAAGY,SAAS,EAAEF,QAAQ,CAAC;IAE9B,IAAIjB,IAAI,EAAEoB,SAAS,CAACxB,EAAE,EAAEC,OAAO,CAAC;EAClC,CAAC,CAAC;EAEF,IAAII,SAAS,EAAEM,OAAO,GAAG,EAAE,EAAEU,QAAQ,CAAC;EAEtCrB,EAAE,CAACyB,OAAO,GAAGjB,MAAM,CAACR,EAAE,CAACyB,OAAO,CAAC;EAC/BzB,EAAE,CAACyB,OAAO,CAAExB,OAAO,CAACyB,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,GAAG;IAAEP;EAAS,CAAC;EAEnDA,QAAQ,CAACQ,OAAO,CAAC7B,EAAE,EAAEY,OAAO,CAAC;AAC/B;AAEA,SAASY,SAASA,CAAExB,EAAe,EAAEC,OAAiC,EAAE;EACtE,IAAI,CAACD,EAAE,CAACyB,OAAO,GAAGxB,OAAO,CAACyB,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,EAAE;EAE5C5B,EAAE,CAACyB,OAAO,CAACxB,OAAO,CAACyB,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,CAAEP,QAAQ,CAACS,UAAU,CAAC,CAAC;EAC1D,OAAO9B,EAAE,CAACyB,OAAO,CAACxB,OAAO,CAACyB,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;AAC5C;AAEA,OAAO,MAAMG,MAAM,GAAG;EACpBhC,OAAO;EACPyB;AACF,CAAC;AAED,eAAeO,MAAM","ignoreList":[]}
+15
View File
@@ -0,0 +1,15 @@
import type { DirectiveBinding } from 'vue';
interface ResizeDirectiveBinding extends Omit<DirectiveBinding, 'modifiers'> {
value: () => void;
modifiers?: {
active?: boolean;
quiet?: boolean;
};
}
declare function mounted(el: HTMLElement, binding: ResizeDirectiveBinding): void;
declare function unmounted(el: HTMLElement, binding: ResizeDirectiveBinding): void;
export declare const Resize: {
mounted: typeof mounted;
unmounted: typeof unmounted;
};
export default Resize;
+32
View File
@@ -0,0 +1,32 @@
// Types
function mounted(el, binding) {
const handler = binding.value;
const options = {
passive: !binding.modifiers?.active
};
window.addEventListener('resize', handler, options);
el._onResize = Object(el._onResize);
el._onResize[binding.instance.$.uid] = {
handler,
options
};
if (!binding.modifiers?.quiet) {
handler();
}
}
function unmounted(el, binding) {
if (!el._onResize?.[binding.instance.$.uid]) return;
const {
handler,
options
} = el._onResize[binding.instance.$.uid];
window.removeEventListener('resize', handler, options);
delete el._onResize[binding.instance.$.uid];
}
export const Resize = {
mounted,
unmounted
};
export default Resize;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["mounted","el","binding","handler","value","options","passive","modifiers","active","window","addEventListener","_onResize","Object","instance","$","uid","quiet","unmounted","removeEventListener","Resize"],"sources":["../../../src/directives/resize/index.ts"],"sourcesContent":["// Types\nimport type { DirectiveBinding } from 'vue'\n\ninterface ResizeDirectiveBinding extends Omit<DirectiveBinding, 'modifiers'> {\n value: () => void\n modifiers?: {\n active?: boolean\n quiet?: boolean\n }\n}\n\nfunction mounted (el: HTMLElement, binding: ResizeDirectiveBinding) {\n const handler = binding.value\n const options: AddEventListenerOptions = {\n passive: !binding.modifiers?.active,\n }\n\n window.addEventListener('resize', handler, options)\n\n el._onResize = Object(el._onResize)\n el._onResize![binding.instance!.$.uid] = {\n handler,\n options,\n }\n\n if (!binding.modifiers?.quiet) {\n handler()\n }\n}\n\nfunction unmounted (el: HTMLElement, binding: ResizeDirectiveBinding) {\n if (!el._onResize?.[binding.instance!.$.uid]) return\n\n const { handler, options } = el._onResize[binding.instance!.$.uid]!\n\n window.removeEventListener('resize', handler, options)\n\n delete el._onResize[binding.instance!.$.uid]\n}\n\nexport const Resize = {\n mounted,\n unmounted,\n}\n\nexport default Resize\n"],"mappings":"AAAA;;AAWA,SAASA,OAAOA,CAAEC,EAAe,EAAEC,OAA+B,EAAE;EAClE,MAAMC,OAAO,GAAGD,OAAO,CAACE,KAAK;EAC7B,MAAMC,OAAgC,GAAG;IACvCC,OAAO,EAAE,CAACJ,OAAO,CAACK,SAAS,EAAEC;EAC/B,CAAC;EAEDC,MAAM,CAACC,gBAAgB,CAAC,QAAQ,EAAEP,OAAO,EAAEE,OAAO,CAAC;EAEnDJ,EAAE,CAACU,SAAS,GAAGC,MAAM,CAACX,EAAE,CAACU,SAAS,CAAC;EACnCV,EAAE,CAACU,SAAS,CAAET,OAAO,CAACW,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,GAAG;IACvCZ,OAAO;IACPE;EACF,CAAC;EAED,IAAI,CAACH,OAAO,CAACK,SAAS,EAAES,KAAK,EAAE;IAC7Bb,OAAO,CAAC,CAAC;EACX;AACF;AAEA,SAASc,SAASA,CAAEhB,EAAe,EAAEC,OAA+B,EAAE;EACpE,IAAI,CAACD,EAAE,CAACU,SAAS,GAAGT,OAAO,CAACW,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,EAAE;EAE9C,MAAM;IAAEZ,OAAO;IAAEE;EAAQ,CAAC,GAAGJ,EAAE,CAACU,SAAS,CAACT,OAAO,CAACW,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAE;EAEnEN,MAAM,CAACS,mBAAmB,CAAC,QAAQ,EAAEf,OAAO,EAAEE,OAAO,CAAC;EAEtD,OAAOJ,EAAE,CAACU,SAAS,CAACT,OAAO,CAACW,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;AAC9C;AAEA,OAAO,MAAMI,MAAM,GAAG;EACpBnB,OAAO;EACPiB;AACF,CAAC;AAED,eAAeE,MAAM","ignoreList":[]}
+45
View File
@@ -0,0 +1,45 @@
@layer vuetify-components {
.v-ripple__container {
color: inherit;
border-radius: inherit;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
overflow: hidden;
z-index: 0;
pointer-events: none;
contain: strict;
}
.v-ripple__animation {
color: inherit;
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
background: currentColor;
opacity: 0;
pointer-events: none;
overflow: hidden;
will-change: transform, opacity;
}
.v-ripple__animation--enter {
transition: none;
opacity: 0;
}
.v-ripple__animation--in {
transition: transform 0.25s cubic-bezier(0, 0, 0.2, 1), opacity 0.1s cubic-bezier(0, 0, 0.2, 1);
opacity: calc(0.25 * var(--v-theme-overlay-multiplier));
}
@media (prefers-reduced-motion: reduce) {
.v-ripple__animation--in {
transition-property: opacity;
transition-duration: 0.1s;
}
}
.v-ripple__animation--out {
transition: opacity 0.3s cubic-bezier(0, 0, 0.2, 1);
opacity: 0;
}
}
+45
View File
@@ -0,0 +1,45 @@
@use '../../styles/tools'
@use './variables' as *
@include tools.layer('components')
.v-ripple
&__container
color: inherit
border-radius: inherit
position: absolute
width: 100%
height: 100%
left: 0
top: 0
overflow: hidden
z-index: 0
pointer-events: none
contain: strict
&__animation
color: inherit
position: absolute
top: 0
left: 0
border-radius: 50%
background: currentColor
opacity: 0
pointer-events: none
overflow: hidden
will-change: transform, opacity
&--enter
transition: none
opacity: 0
&--in
transition: $ripple-animation-transition-in
opacity: $ripple-animation-visible-opacity
@media (prefers-reduced-motion: reduce)
transition-property: opacity
transition-duration: 0.1s
&--out
transition: $ripple-animation-transition-out
opacity: 0
+6
View File
@@ -0,0 +1,6 @@
@use '../../styles/settings';
$ripple-animation-transition-in: transform .25s settings.$decelerated-easing,
opacity .1s settings.$decelerated-easing !default;
$ripple-animation-transition-out: opacity .3s settings.$decelerated-easing !default;
$ripple-animation-visible-opacity: calc(.25 * var(--v-theme-overlay-multiplier)) !default;
+22
View File
@@ -0,0 +1,22 @@
import type { DirectiveBinding } from 'vue';
export interface RippleDirectiveBinding extends Omit<DirectiveBinding, 'modifiers' | 'value'> {
value?: boolean | {
class?: string;
keys?: string[];
};
modifiers: {
center?: boolean;
circle?: boolean;
stop?: boolean;
};
}
declare function mounted(el: HTMLElement, binding: RippleDirectiveBinding): void;
declare function unmounted(el: HTMLElement): void;
declare function updated(el: HTMLElement, binding: RippleDirectiveBinding): void;
export declare const Ripple: {
mounted: typeof mounted;
unmounted: typeof unmounted;
updated: typeof updated;
};
export default Ripple;
+297
View File
@@ -0,0 +1,297 @@
// Styles
import "./VRipple.css";
// Utilities
import { isObject } from "../../util/index.js";
import { Box, getTargetBox } from "../../util/box.js"; // Types
const stopSymbol = Symbol('rippleStop');
const DELAY_RIPPLE = 80;
function transform(el, value) {
el.style.transform = value;
el.style.webkitTransform = value;
}
function isTouchEvent(e) {
return e.constructor.name === 'TouchEvent';
}
function isKeyboardEvent(e) {
return e.constructor.name === 'KeyboardEvent';
}
const calculate = (e, el, value = {}) => {
let localX = 0;
let localY = 0;
if (!isKeyboardEvent(e)) {
const offset = new Box(el);
const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
const point = getTargetBox([target.clientX, target.clientY]);
localX = point.x - offset.left;
localY = point.y - offset.top;
}
let radius = 0;
let scale = 0.3;
if (el._ripple?.circle) {
scale = 0.15;
radius = el.clientWidth / 2;
radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
} else {
radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
}
const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
const x = value.center ? centerX : `${localX - radius}px`;
const y = value.center ? centerY : `${localY - radius}px`;
return {
radius,
scale,
x,
y,
centerX,
centerY
};
};
const ripples = {
/* eslint-disable max-statements */
show(e, el, value = {}) {
if (!el?._ripple?.enabled) {
return;
}
const container = document.createElement('span');
const animation = document.createElement('span');
container.appendChild(animation);
container.className = 'v-ripple__container';
if (value.class) {
container.className += ` ${value.class}`;
}
const {
radius,
scale,
x,
y,
centerX,
centerY
} = calculate(e, el, value);
const size = `${radius * 2}px`;
animation.className = 'v-ripple__animation';
animation.style.width = size;
animation.style.height = size;
el.appendChild(container);
const computed = window.getComputedStyle(el);
if (computed && computed.position === 'static') {
el.style.position = 'relative';
el.dataset.previousPosition = 'static';
}
animation.classList.add('v-ripple__animation--enter');
animation.classList.add('v-ripple__animation--visible');
transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
animation.dataset.activated = String(performance.now());
requestAnimationFrame(() => {
requestAnimationFrame(() => {
animation.classList.remove('v-ripple__animation--enter');
animation.classList.add('v-ripple__animation--in');
transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
});
});
},
hide(el) {
if (!el?._ripple?.enabled) return;
const ripples = el.getElementsByClassName('v-ripple__animation');
if (ripples.length === 0) return;
const animation = Array.from(ripples).findLast(ripple => !ripple.dataset.isHiding);
if (!animation) return;else animation.dataset.isHiding = 'true';
const diff = performance.now() - Number(animation.dataset.activated);
const delay = Math.max(250 - diff, 0);
setTimeout(() => {
animation.classList.remove('v-ripple__animation--in');
animation.classList.add('v-ripple__animation--out');
setTimeout(() => {
const ripples = el.getElementsByClassName('v-ripple__animation');
if (ripples.length === 1 && el.dataset.previousPosition) {
el.style.position = el.dataset.previousPosition;
delete el.dataset.previousPosition;
}
if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
}, 300);
}, delay);
}
};
function isRippleEnabled(value) {
return typeof value === 'undefined' || !!value;
}
function rippleShow(e) {
const value = {};
const element = e.currentTarget;
if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;
// Don't allow the event to trigger ripples on any other elements
e[stopSymbol] = true;
if (isTouchEvent(e)) {
element._ripple.touched = true;
element._ripple.isTouch = true;
} else {
// It's possible for touch events to fire
// as mouse events on Android/iOS, this
// will skip the event call if it has
// already been registered as touch
if (element._ripple.isTouch) return;
}
value.center = element._ripple.centered || isKeyboardEvent(e);
if (element._ripple.class) {
value.class = element._ripple.class;
}
if (isTouchEvent(e)) {
// already queued that shows or hides the ripple
if (element._ripple.showTimerCommit) return;
element._ripple.showTimerCommit = () => {
ripples.show(e, element, value);
};
element._ripple.showTimer = window.setTimeout(() => {
if (element?._ripple?.showTimerCommit) {
element._ripple.showTimerCommit();
element._ripple.showTimerCommit = null;
}
}, DELAY_RIPPLE);
} else {
ripples.show(e, element, value);
}
}
function rippleStop(e) {
e[stopSymbol] = true;
}
function rippleHide(e) {
const element = e.currentTarget;
if (!element?._ripple) return;
window.clearTimeout(element._ripple.showTimer);
// The touch interaction occurs before the show timer is triggered.
// We still want to show ripple effect.
if (e.type === 'touchend' && element._ripple.showTimerCommit) {
element._ripple.showTimerCommit();
element._ripple.showTimerCommit = null;
// re-queue ripple hiding
element._ripple.showTimer = window.setTimeout(() => {
rippleHide(e);
});
return;
}
window.setTimeout(() => {
if (element._ripple) {
element._ripple.touched = false;
}
});
ripples.hide(element);
}
function rippleCancelShow(e) {
const element = e.currentTarget;
if (!element?._ripple) return;
if (element._ripple.showTimerCommit) {
element._ripple.showTimerCommit = null;
}
window.clearTimeout(element._ripple.showTimer);
}
let keyboardRipple = false;
function keyboardRippleShow(e, keys) {
if (!keyboardRipple && keys.includes(e.key)) {
keyboardRipple = true;
rippleShow(e);
}
}
function keyboardRippleHide(e) {
keyboardRipple = false;
rippleHide(e);
}
function focusRippleHide(e) {
if (keyboardRipple) {
keyboardRipple = false;
rippleHide(e);
}
}
function updateRipple(el, binding, wasEnabled) {
const {
value,
modifiers
} = binding;
const enabled = isRippleEnabled(value);
if (!enabled) {
ripples.hide(el);
}
el._ripple = el._ripple ?? {};
el._ripple.enabled = enabled;
el._ripple.centered = modifiers.center;
el._ripple.circle = modifiers.circle;
const bindingValue = isObject(value) ? value : {};
if (bindingValue.class) {
el._ripple.class = bindingValue.class;
}
const allowedKeys = bindingValue.keys ?? ['Enter', 'Space'];
el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
if (enabled && !wasEnabled) {
if (modifiers.stop) {
el.addEventListener('touchstart', rippleStop, {
passive: true
});
el.addEventListener('mousedown', rippleStop);
return;
}
el.addEventListener('touchstart', rippleShow, {
passive: true
});
el.addEventListener('touchend', rippleHide, {
passive: true
});
el.addEventListener('touchmove', rippleCancelShow, {
passive: true
});
el.addEventListener('touchcancel', rippleHide);
el.addEventListener('mousedown', rippleShow);
el.addEventListener('mouseup', rippleHide);
el.addEventListener('mouseleave', rippleHide);
el.addEventListener('keydown', el._ripple.keyDownHandler);
el.addEventListener('keyup', keyboardRippleHide);
el.addEventListener('blur', focusRippleHide);
// Anchor tags can be dragged, causes other hides to fail - #1537
el.addEventListener('dragstart', rippleHide, {
passive: true
});
} else if (!enabled && wasEnabled) {
removeListeners(el);
}
}
function removeListeners(el) {
el.removeEventListener('touchstart', rippleStop);
el.removeEventListener('mousedown', rippleStop);
el.removeEventListener('touchstart', rippleShow);
el.removeEventListener('touchend', rippleHide);
el.removeEventListener('touchmove', rippleCancelShow);
el.removeEventListener('touchcancel', rippleHide);
el.removeEventListener('mousedown', rippleShow);
el.removeEventListener('mouseup', rippleHide);
el.removeEventListener('mouseleave', rippleHide);
if (el._ripple?.keyDownHandler) {
el.removeEventListener('keydown', el._ripple.keyDownHandler);
}
el.removeEventListener('keyup', keyboardRippleHide);
el.removeEventListener('blur', focusRippleHide);
el.removeEventListener('dragstart', rippleHide);
}
function mounted(el, binding) {
updateRipple(el, binding, false);
}
function unmounted(el) {
removeListeners(el);
delete el._ripple;
}
function updated(el, binding) {
if (binding.value === binding.oldValue) {
return;
}
const wasEnabled = isRippleEnabled(binding.oldValue);
updateRipple(el, binding, wasEnabled);
}
export const Ripple = {
mounted,
unmounted,
updated
};
export default Ripple;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
+21
View File
@@ -0,0 +1,21 @@
import type { DirectiveBinding } from 'vue';
interface ScrollDirectiveBinding extends Omit<DirectiveBinding, 'modifiers'> {
value: EventListener | {
handler: EventListener;
options?: AddEventListenerOptions;
} | (EventListenerObject & {
options?: AddEventListenerOptions;
});
modifiers?: {
self?: boolean;
};
}
declare function mounted(el: HTMLElement, binding: ScrollDirectiveBinding): void;
declare function unmounted(el: HTMLElement, binding: ScrollDirectiveBinding): void;
declare function updated(el: HTMLElement, binding: ScrollDirectiveBinding): void;
export declare const Scroll: {
mounted: typeof mounted;
unmounted: typeof unmounted;
updated: typeof updated;
};
export default Scroll;
+44
View File
@@ -0,0 +1,44 @@
// Types
function mounted(el, binding) {
const {
self = false
} = binding.modifiers ?? {};
const value = binding.value;
const options = typeof value === 'object' && value.options || {
passive: true
};
const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
if (!target) return;
target.addEventListener('scroll', handler, options);
el._onScroll = Object(el._onScroll);
el._onScroll[binding.instance.$.uid] = {
handler,
options,
// Don't reference self
target: self ? undefined : target
};
}
function unmounted(el, binding) {
if (!el._onScroll?.[binding.instance.$.uid]) return;
const {
handler,
options,
target = el
} = el._onScroll[binding.instance.$.uid];
target.removeEventListener('scroll', handler, options);
delete el._onScroll[binding.instance.$.uid];
}
function updated(el, binding) {
if (binding.value === binding.oldValue) return;
unmounted(el, binding);
mounted(el, binding);
}
export const Scroll = {
mounted,
unmounted,
updated
};
export default Scroll;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["mounted","el","binding","self","modifiers","value","options","passive","handler","target","arg","document","querySelector","window","addEventListener","_onScroll","Object","instance","$","uid","undefined","unmounted","removeEventListener","updated","oldValue","Scroll"],"sources":["../../../src/directives/scroll/index.ts"],"sourcesContent":["// Types\nimport type { DirectiveBinding } from 'vue'\n\ninterface ScrollDirectiveBinding extends Omit<DirectiveBinding, 'modifiers'> {\n value: EventListener | {\n handler: EventListener\n options?: AddEventListenerOptions\n } | EventListenerObject & { options?: AddEventListenerOptions }\n modifiers?: {\n self?: boolean\n }\n}\n\nfunction mounted (el: HTMLElement, binding: ScrollDirectiveBinding) {\n const { self = false } = binding.modifiers ?? {}\n const value = binding.value\n const options = (typeof value === 'object' && value.options) || { passive: true }\n const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler\n\n const target = self\n ? el\n : binding.arg\n ? document.querySelector(binding.arg)\n : window\n\n if (!target) return\n\n target.addEventListener('scroll', handler, options)\n\n el._onScroll = Object(el._onScroll)\n el._onScroll![binding.instance!.$.uid] = {\n handler,\n options,\n // Don't reference self\n target: self ? undefined : target,\n }\n}\n\nfunction unmounted (el: HTMLElement, binding: ScrollDirectiveBinding) {\n if (!el._onScroll?.[binding.instance!.$.uid]) return\n\n const { handler, options, target = el } = el._onScroll[binding.instance!.$.uid]!\n\n target.removeEventListener('scroll', handler, options)\n delete el._onScroll[binding.instance!.$.uid]\n}\n\nfunction updated (el: HTMLElement, binding: ScrollDirectiveBinding) {\n if (binding.value === binding.oldValue) return\n\n unmounted(el, binding)\n mounted(el, binding)\n}\n\nexport const Scroll = {\n mounted,\n unmounted,\n updated,\n}\n\nexport default Scroll\n"],"mappings":"AAAA;;AAaA,SAASA,OAAOA,CAAEC,EAAe,EAAEC,OAA+B,EAAE;EAClE,MAAM;IAAEC,IAAI,GAAG;EAAM,CAAC,GAAGD,OAAO,CAACE,SAAS,IAAI,CAAC,CAAC;EAChD,MAAMC,KAAK,GAAGH,OAAO,CAACG,KAAK;EAC3B,MAAMC,OAAO,GAAI,OAAOD,KAAK,KAAK,QAAQ,IAAIA,KAAK,CAACC,OAAO,IAAK;IAAEC,OAAO,EAAE;EAAK,CAAC;EACjF,MAAMC,OAAO,GAAG,OAAOH,KAAK,KAAK,UAAU,IAAI,aAAa,IAAIA,KAAK,GAAGA,KAAK,GAAGA,KAAK,CAACG,OAAO;EAE7F,MAAMC,MAAM,GAAGN,IAAI,GACfF,EAAE,GACFC,OAAO,CAACQ,GAAG,GACTC,QAAQ,CAACC,aAAa,CAACV,OAAO,CAACQ,GAAG,CAAC,GACnCG,MAAM;EAEZ,IAAI,CAACJ,MAAM,EAAE;EAEbA,MAAM,CAACK,gBAAgB,CAAC,QAAQ,EAAEN,OAAO,EAAEF,OAAO,CAAC;EAEnDL,EAAE,CAACc,SAAS,GAAGC,MAAM,CAACf,EAAE,CAACc,SAAS,CAAC;EACnCd,EAAE,CAACc,SAAS,CAAEb,OAAO,CAACe,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,GAAG;IACvCX,OAAO;IACPF,OAAO;IACP;IACAG,MAAM,EAAEN,IAAI,GAAGiB,SAAS,GAAGX;EAC7B,CAAC;AACH;AAEA,SAASY,SAASA,CAAEpB,EAAe,EAAEC,OAA+B,EAAE;EACpE,IAAI,CAACD,EAAE,CAACc,SAAS,GAAGb,OAAO,CAACe,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC,EAAE;EAE9C,MAAM;IAAEX,OAAO;IAAEF,OAAO;IAAEG,MAAM,GAAGR;EAAG,CAAC,GAAGA,EAAE,CAACc,SAAS,CAACb,OAAO,CAACe,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAE;EAEhFV,MAAM,CAACa,mBAAmB,CAAC,QAAQ,EAAEd,OAAO,EAAEF,OAAO,CAAC;EACtD,OAAOL,EAAE,CAACc,SAAS,CAACb,OAAO,CAACe,QAAQ,CAAEC,CAAC,CAACC,GAAG,CAAC;AAC9C;AAEA,SAASI,OAAOA,CAAEtB,EAAe,EAAEC,OAA+B,EAAE;EAClE,IAAIA,OAAO,CAACG,KAAK,KAAKH,OAAO,CAACsB,QAAQ,EAAE;EAExCH,SAAS,CAACpB,EAAE,EAAEC,OAAO,CAAC;EACtBF,OAAO,CAACC,EAAE,EAAEC,OAAO,CAAC;AACtB;AAEA,OAAO,MAAMuB,MAAM,GAAG;EACpBzB,OAAO;EACPqB,SAAS;EACTE;AACF,CAAC;AAED,eAAeE,MAAM","ignoreList":[]}
+10
View File
@@ -0,0 +1,10 @@
import type { DirectiveBinding } from 'vue';
import type { Anchor } from '../../util/index.js';
export interface TooltipDirectiveBinding extends Omit<DirectiveBinding<string>, 'arg' | 'value'> {
arg?: {
[T in Anchor]: T extends `${infer A} ${infer B}` ? `${A}-${B}` : T;
}[Anchor];
value: boolean | string | Record<string, any>;
}
export declare const Tooltip: import("../../composables/directiveComponent.js").CustomDirective<TooltipDirectiveBinding>;
export default Tooltip;
+15
View File
@@ -0,0 +1,15 @@
// Components
import { VTooltip } from "../../components/VTooltip/index.js"; // Composables
import { useDirectiveComponent } from "../../composables/directiveComponent.js"; // Utilities
import { isObject } from "../../util/index.js"; // Types
export const Tooltip = useDirectiveComponent(VTooltip, binding => {
const disabled = isObject(binding.value) ? !binding.value.text : ['', false, null].includes(binding.value); // undefined means true
return {
activator: disabled ? null : 'parent',
location: binding.arg?.replace('-', ' '),
text: typeof binding.value === 'boolean' ? undefined : binding.value
};
});
export default Tooltip;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["VTooltip","useDirectiveComponent","isObject","Tooltip","binding","disabled","value","text","includes","activator","location","arg","replace","undefined"],"sources":["../../../src/directives/tooltip/index.ts"],"sourcesContent":["// Components\nimport { VTooltip } from '@/components/VTooltip'\n\n// Composables\nimport { useDirectiveComponent } from '@/composables/directiveComponent'\n\n// Utilities\nimport { isObject } from '@/util'\n\n// Types\nimport type { DirectiveBinding } from 'vue'\nimport type { Anchor } from '@/util'\n\nexport interface TooltipDirectiveBinding extends Omit<DirectiveBinding<string>, 'arg' | 'value'> {\n arg?: { [T in Anchor]: T extends `${infer A} ${infer B}` ? `${A}-${B}` : T }[Anchor]\n value: boolean | string | Record<string, any>\n}\n\nexport const Tooltip = useDirectiveComponent<TooltipDirectiveBinding>(VTooltip, binding => {\n const disabled = isObject(binding.value)\n ? !binding.value.text\n : ['', false, null].includes(binding.value) // undefined means true\n\n return {\n activator: disabled ? null : 'parent',\n location: binding.arg?.replace('-', ' '),\n text: typeof binding.value === 'boolean' ? undefined : binding.value,\n }\n})\n\nexport default Tooltip\n"],"mappings":"AAAA;AAAA,SACSA,QAAQ,8CAEjB;AAAA,SACSC,qBAAqB,mDAE9B;AAAA,SACSC,QAAQ,+BAEjB;AASA,OAAO,MAAMC,OAAO,GAAGF,qBAAqB,CAA0BD,QAAQ,EAAEI,OAAO,IAAI;EACzF,MAAMC,QAAQ,GAAGH,QAAQ,CAACE,OAAO,CAACE,KAAK,CAAC,GACpC,CAACF,OAAO,CAACE,KAAK,CAACC,IAAI,GACnB,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,CAACC,QAAQ,CAACJ,OAAO,CAACE,KAAK,CAAC,EAAC;;EAE9C,OAAO;IACLG,SAAS,EAAEJ,QAAQ,GAAG,IAAI,GAAG,QAAQ;IACrCK,QAAQ,EAAEN,OAAO,CAACO,GAAG,EAAEC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;IACxCL,IAAI,EAAE,OAAOH,OAAO,CAACE,KAAK,KAAK,SAAS,GAAGO,SAAS,GAAGT,OAAO,CAACE;EACjE,CAAC;AACH,CAAC,CAAC;AAEF,eAAeH,OAAO","ignoreList":[]}
+46
View File
@@ -0,0 +1,46 @@
import type { DirectiveBinding } from 'vue';
export interface TouchHandlers {
start?: (wrapperEvent: {
originalEvent: TouchEvent;
} & TouchData) => void;
end?: (wrapperEvent: {
originalEvent: TouchEvent;
} & TouchData) => void;
move?: (wrapperEvent: {
originalEvent: TouchEvent;
} & TouchData) => void;
left?: (wrapper: TouchData) => void;
right?: (wrapper: TouchData) => void;
up?: (wrapper: TouchData) => void;
down?: (wrapper: TouchData) => void;
}
export interface TouchData {
touchstartX: number;
touchstartY: number;
touchmoveX: number;
touchmoveY: number;
touchendX: number;
touchendY: number;
offsetX: number;
offsetY: number;
}
export type TouchWrapper = TouchHandlers & TouchData;
export interface TouchValue extends TouchHandlers {
parent?: boolean;
options?: AddEventListenerOptions;
}
export interface TouchStoredHandlers {
touchstart: (e: TouchEvent) => void;
touchend: (e: TouchEvent) => void;
touchmove: (e: TouchEvent) => void;
}
export interface TouchDirectiveBinding extends Omit<DirectiveBinding, 'value'> {
value?: TouchValue;
}
declare function mounted(el: HTMLElement, binding: TouchDirectiveBinding): void;
declare function unmounted(el: HTMLElement, binding: TouchDirectiveBinding): void;
export declare const Touch: {
mounted: typeof mounted;
unmounted: typeof unmounted;
};
export default Touch;
+106
View File
@@ -0,0 +1,106 @@
// Utilities
import { keys } from "../../util/index.js"; // Types
const handleGesture = wrapper => {
const {
touchstartX,
touchendX,
touchstartY,
touchendY
} = wrapper;
const dirRatio = 0.5;
const minDistance = 16;
wrapper.offsetX = touchendX - touchstartX;
wrapper.offsetY = touchendY - touchstartY;
if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
}
if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
}
};
function touchstart(event, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchstartX = touch.clientX;
wrapper.touchstartY = touch.clientY;
wrapper.start?.({
originalEvent: event,
...wrapper
});
}
function touchend(event, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchendX = touch.clientX;
wrapper.touchendY = touch.clientY;
wrapper.end?.({
originalEvent: event,
...wrapper
});
handleGesture(wrapper);
}
function touchmove(event, wrapper) {
const touch = event.changedTouches[0];
wrapper.touchmoveX = touch.clientX;
wrapper.touchmoveY = touch.clientY;
wrapper.move?.({
originalEvent: event,
...wrapper
});
}
function createHandlers(value = {}) {
const wrapper = {
touchstartX: 0,
touchstartY: 0,
touchendX: 0,
touchendY: 0,
touchmoveX: 0,
touchmoveY: 0,
offsetX: 0,
offsetY: 0,
left: value.left,
right: value.right,
up: value.up,
down: value.down,
start: value.start,
move: value.move,
end: value.end
};
return {
touchstart: e => touchstart(e, wrapper),
touchend: e => touchend(e, wrapper),
touchmove: e => touchmove(e, wrapper)
};
}
function mounted(el, binding) {
const value = binding.value;
const target = value?.parent ? el.parentElement : el;
const options = value?.options ?? {
passive: true
};
const uid = binding.instance?.$.uid; // TODO: use custom uid generator
if (!target || uid === undefined) return;
const handlers = createHandlers(binding.value);
target._touchHandlers = target._touchHandlers ?? Object.create(null);
target._touchHandlers[uid] = handlers;
keys(handlers).forEach(eventName => {
target.addEventListener(eventName, handlers[eventName], options);
});
}
function unmounted(el, binding) {
const target = binding.value?.parent ? el.parentElement : el;
const uid = binding.instance?.$.uid;
if (!target?._touchHandlers || uid === undefined) return;
const handlers = target._touchHandlers[uid];
keys(handlers).forEach(eventName => {
target.removeEventListener(eventName, handlers[eventName]);
});
delete target._touchHandlers[uid];
}
export const Touch = {
mounted,
unmounted
};
export default Touch;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long