@fastkit/vue-utils
Advanced tools
Comparing version 0.1.11 to 0.1.12
@@ -10,2 +10,3 @@ 'use strict'; | ||
var visibility = require('@fastkit/visibility'); | ||
var bodyScrollLock = require('@fastkit/body-scroll-lock'); | ||
@@ -24,2 +25,11 @@ /** | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
}; | ||
} | ||
const navigationableEmits = createEmitDefine({ | ||
@@ -97,9 +107,48 @@ click: (ev) => true, | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
const javaScriptTransitionHookKeys = [ | ||
'onBeforeEnter', | ||
'onEnter', | ||
'onAfterEnter', | ||
'onEnterCancelled', | ||
'onBeforeLeave', | ||
'onLeave', | ||
'onAfterLeave', | ||
'onLeaveCancelled', | ||
'onBeforeAppear', | ||
'onAppear', | ||
'onAfterAppear', | ||
'onAppearCancelled', | ||
]; | ||
function createJavaScriptTransition(opts) { | ||
const { displayName = 'JavaScriptTransition' } = opts; | ||
// const baseProps: TransitionProps = { | ||
// css: false, | ||
// }; | ||
const Component = (props, ctx) => { | ||
const { slots } = ctx; | ||
const resolvedProps = { | ||
css: false, | ||
}; | ||
const listeners = { | ||
...opts.render(props, ctx), | ||
}; | ||
javaScriptTransitionHookKeys.forEach((key) => { | ||
let _key = key.slice(2); | ||
_key = _key.charAt(0).toLowerCase() + _key.slice(1); | ||
resolvedProps[key] = (el, done) => { | ||
const fn = listeners[key]; | ||
fn && fn(el, done); | ||
ctx.emit(_key, el, done); | ||
}; | ||
}); | ||
return vue.h(vue.Transition, resolvedProps, slots); | ||
}; | ||
Component.displayName = displayName; | ||
Component.props = { | ||
...vue.BaseTransition.props, | ||
...opts.props, | ||
}; | ||
// console.log(opts.props, (Component.props as any).onEnter); | ||
return Component; | ||
} | ||
@@ -192,2 +241,99 @@ | ||
const VExpandTransition = createJavaScriptTransition({ | ||
displayName: 'VExpandTransition', | ||
props: { | ||
expand: { | ||
type: String, | ||
default: 'height', | ||
}, | ||
// className: { | ||
// type: String as PropType<string>, | ||
// default: 'v-expand-transition' as const, | ||
// }, | ||
}, | ||
render(props) { | ||
const { expand: sizeProperty } = props; | ||
const offsetProperty = `offset${sizeProperty.charAt(0).toUpperCase() + sizeProperty.slice(1)}`; | ||
function resetStyles(_el) { | ||
const el = _el; | ||
const { _initialStyle } = el; | ||
if (!_initialStyle) | ||
return; | ||
const size = _initialStyle[sizeProperty]; | ||
el.style.overflow = _initialStyle.overflow || ''; | ||
if (size != null) { | ||
el.style[sizeProperty] = size; | ||
} | ||
delete el._initialStyle; | ||
} | ||
function afterLeave(_el) { | ||
const el = _el; | ||
// if (className && el._parent) { | ||
// el._parent.classList.remove(className); | ||
// } | ||
resetStyles(el); | ||
} | ||
return { | ||
onBeforeEnter(_el) { | ||
const el = _el; | ||
el._parent = el.parentNode; | ||
el._initialStyle = { | ||
transition: el.style.transition, | ||
visibility: el.style.visibility, | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
}, | ||
onEnter(_el, done) { | ||
const el = _el; | ||
const initialStyle = el._initialStyle; | ||
if (!initialStyle) | ||
return; | ||
const offset = `${el[offsetProperty]}px`; | ||
el.style.setProperty('transition', 'none', 'important'); | ||
el.style.visibility = 'hidden'; | ||
el.style.visibility = initialStyle.visibility || ''; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = '0'; | ||
// eslint-disable-next-line no-void | ||
void el.offsetHeight; // force reflow | ||
el.style.transition = initialStyle.transition; | ||
// if (className && el._parent) { | ||
// el._parent.classList.add(className); | ||
// } | ||
requestAnimationFrame(() => { | ||
helpers.addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = offset; | ||
}); | ||
}, | ||
onAfterEnter: resetStyles, | ||
onEnterCancelled: resetStyles, | ||
onLeave(_el, done) { | ||
const el = _el; | ||
el._initialStyle = { | ||
transition: '', | ||
visibility: '', | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = `${el[offsetProperty]}px`; | ||
void el.offsetHeight; // force reflow | ||
requestAnimationFrame(() => { | ||
helpers.addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = '0'; | ||
}); | ||
}, | ||
onAfterLeave: afterLeave, | ||
onLeaveCancelled: afterLeave, | ||
}; | ||
}, | ||
}); | ||
function normalizeRawClickOutsideDirectiveBindingValue(value) { | ||
@@ -205,3 +351,3 @@ if (value && typeof value === 'object') { | ||
const { conditional, include, handler } = value; | ||
if (!handler || (conditional && !conditional(ev))) | ||
if (!handler || (conditional && !conditional(ev, true))) | ||
return; | ||
@@ -233,10 +379,158 @@ if (('isTrusted' in ev && !ev.isTrusted) || | ||
}, | ||
// getSSRProps(binding, vnode) { | ||
// return undefined; | ||
// }, | ||
}; | ||
function clickOutsideDirectiveArgument(bindingValue) { | ||
return [clickOutsideDirective, bindingValue]; | ||
} | ||
const BODY_SCROLL_LOCK_ATTRIBUTE = 'data-body-scroll-lock'; | ||
const BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = 'data-scroll-lock-scroller'; | ||
class Stacks { | ||
constructor() { | ||
this.els = []; | ||
this.active = false; | ||
} | ||
check() { | ||
const active = this.els.length > 0; | ||
if (active && !this.active) { | ||
this.activate(); | ||
} | ||
else if (!active && this.active) { | ||
this.deactivate(); | ||
} | ||
} | ||
activate() { | ||
document.documentElement.setAttribute(BODY_SCROLL_LOCK_ATTRIBUTE, ''); | ||
this.active = true; | ||
} | ||
deactivate() { | ||
document.documentElement.removeAttribute(BODY_SCROLL_LOCK_ATTRIBUTE); | ||
this.active = false; | ||
} | ||
push(el) { | ||
if (!this.els.includes(el)) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
bodyScrollLock.disableBodyScroll(lockElement); | ||
this.els.push(el); | ||
this.check(); | ||
} | ||
} | ||
remove(el) { | ||
const index = this.els.indexOf(el); | ||
if (index !== -1) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
bodyScrollLock.enableBodyScroll(lockElement); | ||
this.els.splice(index, 1); | ||
this.check(); | ||
} | ||
} | ||
} | ||
const stacks = new Stacks(); | ||
const bodyScrollLockDirective = { | ||
mounted(el, binding) { | ||
binding.value && stacks.push(el); | ||
}, | ||
updated(el, binding) { | ||
if (binding.value) { | ||
stacks.push(el); | ||
} | ||
else { | ||
stacks.remove(el); | ||
} | ||
}, | ||
unmounted(el) { | ||
stacks.remove(el); | ||
}, | ||
}; | ||
function bodyScrollLockDirectiveArgument(bindingValue) { | ||
return [bodyScrollLockDirective, bindingValue]; | ||
} | ||
const getDefaults = () => { | ||
return { | ||
debounce: 0, | ||
}; | ||
}; | ||
function resolveValue(value) { | ||
const defaults = getDefaults(); | ||
if (typeof value === 'function') { | ||
return { | ||
...defaults, | ||
handler: value, | ||
}; | ||
} | ||
return { | ||
...defaults, | ||
...value, | ||
}; | ||
} | ||
const hook = function hook(el, binding) { | ||
const { __resize_dir } = el; | ||
if (!binding.value) { | ||
__resize_dir && __resize_dir.destroy(); | ||
return; | ||
} | ||
if (__resize_dir) { | ||
return; | ||
} | ||
const bindingValue = resolveValue(binding.value); | ||
const { handler: _handler, debounce: _debounce, rootMode } = bindingValue; | ||
const handler = helpers.debounce(_handler, _debounce); | ||
const ctx = { | ||
bindingValue, | ||
handler, | ||
destroy() { | ||
if (!el.__resize_dir) | ||
return; | ||
handler.clear(); | ||
if (ctx.rootResizeHandler) { | ||
window.removeEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
if (ctx.resizeObserver) { | ||
ctx.resizeObserver.unobserve(el); | ||
ctx.resizeObserver.disconnect(); | ||
delete ctx.resizeObserver; | ||
} | ||
delete el.__resize_dir; | ||
}, | ||
}; | ||
if (rootMode) { | ||
ctx.rootResizeHandler = () => { | ||
handler({ width: window.innerWidth, height: window.innerHeight }); | ||
}; | ||
window.addEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
else { | ||
ctx.resizeObserver = new ResizeObserver((entries) => { | ||
for (const entry of entries) { | ||
const { width, height } = entry.contentRect; | ||
handler({ width, height }); | ||
} | ||
}); | ||
ctx.resizeObserver.observe(el); | ||
} | ||
el.__resize_dir = ctx; | ||
}; | ||
const beforeUnmount = function beforeUnmount(el) { | ||
const { __resize_dir } = el; | ||
__resize_dir && __resize_dir.destroy(); | ||
}; | ||
const resizeDirective = { | ||
mounted: hook, | ||
updated: hook, | ||
beforeUnmount, | ||
}; | ||
function resizeDirectiveArgument(bindingValue) { | ||
return [resizeDirective, bindingValue]; | ||
} | ||
exports.BODY_SCROLL_LOCK_ATTRIBUTE = BODY_SCROLL_LOCK_ATTRIBUTE; | ||
exports.BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE; | ||
exports.ClickOutsideDirectiveElementSymbol = ClickOutsideDirectiveElementSymbol; | ||
exports.VExpandTransition = VExpandTransition; | ||
exports.bodyScrollLockDirective = bodyScrollLockDirective; | ||
exports.bodyScrollLockDirectiveArgument = bodyScrollLockDirectiveArgument; | ||
exports.clickOutsideDirective = clickOutsideDirective; | ||
exports.clickOutsideDirectiveArgument = clickOutsideDirectiveArgument; | ||
exports.createEmitDefine = createEmitDefine; | ||
exports.createJavaScriptTransition = createJavaScriptTransition; | ||
exports.navigationableEmits = navigationableEmits; | ||
@@ -246,2 +540,4 @@ exports.navigationableProps = navigationableProps; | ||
exports.rawNumberPropType = rawNumberPropType; | ||
exports.resizeDirective = resizeDirective; | ||
exports.resizeDirectiveArgument = resizeDirectiveArgument; | ||
exports.state = state$1; | ||
@@ -248,0 +544,0 @@ exports.useKeybord = useKeybord; |
@@ -10,2 +10,3 @@ 'use strict'; | ||
var visibility = require('@fastkit/visibility'); | ||
var bodyScrollLock = require('@fastkit/body-scroll-lock'); | ||
@@ -24,2 +25,11 @@ /** | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
}; | ||
} | ||
const navigationableEmits = createEmitDefine({ | ||
@@ -97,9 +107,48 @@ click: (ev) => true, | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
const javaScriptTransitionHookKeys = [ | ||
'onBeforeEnter', | ||
'onEnter', | ||
'onAfterEnter', | ||
'onEnterCancelled', | ||
'onBeforeLeave', | ||
'onLeave', | ||
'onAfterLeave', | ||
'onLeaveCancelled', | ||
'onBeforeAppear', | ||
'onAppear', | ||
'onAfterAppear', | ||
'onAppearCancelled', | ||
]; | ||
function createJavaScriptTransition(opts) { | ||
const { displayName = 'JavaScriptTransition' } = opts; | ||
// const baseProps: TransitionProps = { | ||
// css: false, | ||
// }; | ||
const Component = (props, ctx) => { | ||
const { slots } = ctx; | ||
const resolvedProps = { | ||
css: false, | ||
}; | ||
const listeners = { | ||
...opts.render(props, ctx), | ||
}; | ||
javaScriptTransitionHookKeys.forEach((key) => { | ||
let _key = key.slice(2); | ||
_key = _key.charAt(0).toLowerCase() + _key.slice(1); | ||
resolvedProps[key] = (el, done) => { | ||
const fn = listeners[key]; | ||
fn && fn(el, done); | ||
ctx.emit(_key, el, done); | ||
}; | ||
}); | ||
return vue.h(vue.Transition, resolvedProps, slots); | ||
}; | ||
Component.displayName = displayName; | ||
Component.props = { | ||
...vue.BaseTransition.props, | ||
...opts.props, | ||
}; | ||
// console.log(opts.props, (Component.props as any).onEnter); | ||
return Component; | ||
} | ||
@@ -192,2 +241,99 @@ | ||
const VExpandTransition = createJavaScriptTransition({ | ||
displayName: 'VExpandTransition', | ||
props: { | ||
expand: { | ||
type: String, | ||
default: 'height', | ||
}, | ||
// className: { | ||
// type: String as PropType<string>, | ||
// default: 'v-expand-transition' as const, | ||
// }, | ||
}, | ||
render(props) { | ||
const { expand: sizeProperty } = props; | ||
const offsetProperty = `offset${sizeProperty.charAt(0).toUpperCase() + sizeProperty.slice(1)}`; | ||
function resetStyles(_el) { | ||
const el = _el; | ||
const { _initialStyle } = el; | ||
if (!_initialStyle) | ||
return; | ||
const size = _initialStyle[sizeProperty]; | ||
el.style.overflow = _initialStyle.overflow || ''; | ||
if (size != null) { | ||
el.style[sizeProperty] = size; | ||
} | ||
delete el._initialStyle; | ||
} | ||
function afterLeave(_el) { | ||
const el = _el; | ||
// if (className && el._parent) { | ||
// el._parent.classList.remove(className); | ||
// } | ||
resetStyles(el); | ||
} | ||
return { | ||
onBeforeEnter(_el) { | ||
const el = _el; | ||
el._parent = el.parentNode; | ||
el._initialStyle = { | ||
transition: el.style.transition, | ||
visibility: el.style.visibility, | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
}, | ||
onEnter(_el, done) { | ||
const el = _el; | ||
const initialStyle = el._initialStyle; | ||
if (!initialStyle) | ||
return; | ||
const offset = `${el[offsetProperty]}px`; | ||
el.style.setProperty('transition', 'none', 'important'); | ||
el.style.visibility = 'hidden'; | ||
el.style.visibility = initialStyle.visibility || ''; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = '0'; | ||
// eslint-disable-next-line no-void | ||
void el.offsetHeight; // force reflow | ||
el.style.transition = initialStyle.transition; | ||
// if (className && el._parent) { | ||
// el._parent.classList.add(className); | ||
// } | ||
requestAnimationFrame(() => { | ||
helpers.addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = offset; | ||
}); | ||
}, | ||
onAfterEnter: resetStyles, | ||
onEnterCancelled: resetStyles, | ||
onLeave(_el, done) { | ||
const el = _el; | ||
el._initialStyle = { | ||
transition: '', | ||
visibility: '', | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = `${el[offsetProperty]}px`; | ||
void el.offsetHeight; // force reflow | ||
requestAnimationFrame(() => { | ||
helpers.addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = '0'; | ||
}); | ||
}, | ||
onAfterLeave: afterLeave, | ||
onLeaveCancelled: afterLeave, | ||
}; | ||
}, | ||
}); | ||
function normalizeRawClickOutsideDirectiveBindingValue(value) { | ||
@@ -205,3 +351,3 @@ if (value && typeof value === 'object') { | ||
const { conditional, include, handler } = value; | ||
if (!handler || (conditional && !conditional(ev))) | ||
if (!handler || (conditional && !conditional(ev, true))) | ||
return; | ||
@@ -233,10 +379,158 @@ if (('isTrusted' in ev && !ev.isTrusted) || | ||
}, | ||
// getSSRProps(binding, vnode) { | ||
// return undefined; | ||
// }, | ||
}; | ||
function clickOutsideDirectiveArgument(bindingValue) { | ||
return [clickOutsideDirective, bindingValue]; | ||
} | ||
const BODY_SCROLL_LOCK_ATTRIBUTE = 'data-body-scroll-lock'; | ||
const BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = 'data-scroll-lock-scroller'; | ||
class Stacks { | ||
constructor() { | ||
this.els = []; | ||
this.active = false; | ||
} | ||
check() { | ||
const active = this.els.length > 0; | ||
if (active && !this.active) { | ||
this.activate(); | ||
} | ||
else if (!active && this.active) { | ||
this.deactivate(); | ||
} | ||
} | ||
activate() { | ||
document.documentElement.setAttribute(BODY_SCROLL_LOCK_ATTRIBUTE, ''); | ||
this.active = true; | ||
} | ||
deactivate() { | ||
document.documentElement.removeAttribute(BODY_SCROLL_LOCK_ATTRIBUTE); | ||
this.active = false; | ||
} | ||
push(el) { | ||
if (!this.els.includes(el)) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
bodyScrollLock.disableBodyScroll(lockElement); | ||
this.els.push(el); | ||
this.check(); | ||
} | ||
} | ||
remove(el) { | ||
const index = this.els.indexOf(el); | ||
if (index !== -1) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
bodyScrollLock.enableBodyScroll(lockElement); | ||
this.els.splice(index, 1); | ||
this.check(); | ||
} | ||
} | ||
} | ||
const stacks = new Stacks(); | ||
const bodyScrollLockDirective = { | ||
mounted(el, binding) { | ||
binding.value && stacks.push(el); | ||
}, | ||
updated(el, binding) { | ||
if (binding.value) { | ||
stacks.push(el); | ||
} | ||
else { | ||
stacks.remove(el); | ||
} | ||
}, | ||
unmounted(el) { | ||
stacks.remove(el); | ||
}, | ||
}; | ||
function bodyScrollLockDirectiveArgument(bindingValue) { | ||
return [bodyScrollLockDirective, bindingValue]; | ||
} | ||
const getDefaults = () => { | ||
return { | ||
debounce: 0, | ||
}; | ||
}; | ||
function resolveValue(value) { | ||
const defaults = getDefaults(); | ||
if (typeof value === 'function') { | ||
return { | ||
...defaults, | ||
handler: value, | ||
}; | ||
} | ||
return { | ||
...defaults, | ||
...value, | ||
}; | ||
} | ||
const hook = function hook(el, binding) { | ||
const { __resize_dir } = el; | ||
if (!binding.value) { | ||
__resize_dir && __resize_dir.destroy(); | ||
return; | ||
} | ||
if (__resize_dir) { | ||
return; | ||
} | ||
const bindingValue = resolveValue(binding.value); | ||
const { handler: _handler, debounce: _debounce, rootMode } = bindingValue; | ||
const handler = helpers.debounce(_handler, _debounce); | ||
const ctx = { | ||
bindingValue, | ||
handler, | ||
destroy() { | ||
if (!el.__resize_dir) | ||
return; | ||
handler.clear(); | ||
if (ctx.rootResizeHandler) { | ||
window.removeEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
if (ctx.resizeObserver) { | ||
ctx.resizeObserver.unobserve(el); | ||
ctx.resizeObserver.disconnect(); | ||
delete ctx.resizeObserver; | ||
} | ||
delete el.__resize_dir; | ||
}, | ||
}; | ||
if (rootMode) { | ||
ctx.rootResizeHandler = () => { | ||
handler({ width: window.innerWidth, height: window.innerHeight }); | ||
}; | ||
window.addEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
else { | ||
ctx.resizeObserver = new ResizeObserver((entries) => { | ||
for (const entry of entries) { | ||
const { width, height } = entry.contentRect; | ||
handler({ width, height }); | ||
} | ||
}); | ||
ctx.resizeObserver.observe(el); | ||
} | ||
el.__resize_dir = ctx; | ||
}; | ||
const beforeUnmount = function beforeUnmount(el) { | ||
const { __resize_dir } = el; | ||
__resize_dir && __resize_dir.destroy(); | ||
}; | ||
const resizeDirective = { | ||
mounted: hook, | ||
updated: hook, | ||
beforeUnmount, | ||
}; | ||
function resizeDirectiveArgument(bindingValue) { | ||
return [resizeDirective, bindingValue]; | ||
} | ||
exports.BODY_SCROLL_LOCK_ATTRIBUTE = BODY_SCROLL_LOCK_ATTRIBUTE; | ||
exports.BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE; | ||
exports.ClickOutsideDirectiveElementSymbol = ClickOutsideDirectiveElementSymbol; | ||
exports.VExpandTransition = VExpandTransition; | ||
exports.bodyScrollLockDirective = bodyScrollLockDirective; | ||
exports.bodyScrollLockDirectiveArgument = bodyScrollLockDirectiveArgument; | ||
exports.clickOutsideDirective = clickOutsideDirective; | ||
exports.clickOutsideDirectiveArgument = clickOutsideDirectiveArgument; | ||
exports.createEmitDefine = createEmitDefine; | ||
exports.createJavaScriptTransition = createJavaScriptTransition; | ||
exports.navigationableEmits = navigationableEmits; | ||
@@ -246,2 +540,4 @@ exports.navigationableProps = navigationableProps; | ||
exports.rawNumberPropType = rawNumberPropType; | ||
exports.resizeDirective = resizeDirective; | ||
exports.resizeDirectiveArgument = resizeDirectiveArgument; | ||
exports.state = state$1; | ||
@@ -248,0 +544,0 @@ exports.useKeybord = useKeybord; |
@@ -0,12 +1,22 @@ | ||
import { BaseTransitionProps } from 'vue'; | ||
import { ButtonHTMLAttributes } from '@vue/runtime-dom'; | ||
import { ComponentPropsOptions } from 'vue'; | ||
import { ComputedRef } from 'vue'; | ||
import { CSSProperties } from '@vue/runtime-dom'; | ||
import { Debounced } from '@fastkit/helpers'; | ||
import { DirectiveBinding } from 'vue'; | ||
import { DirectiveHook } from 'vue'; | ||
import { ExtractDefaultPropTypes } from 'vue'; | ||
import { ExtractPropTypes } from 'vue'; | ||
import { FunctionalComponent } from 'vue'; | ||
import { HTMLAttributes } from '@vue/runtime-dom'; | ||
import { Key } from '@fastkit/keybord'; | ||
import { ObjectDirective } from 'vue'; | ||
import { Prop } from '@vue/runtime-core'; | ||
import { PropType } from 'vue'; | ||
import { PropType as PropType_2 } from '@vue/runtime-core'; | ||
import { RawKBSettings } from '@fastkit/keybord'; | ||
import { RouteLocationRaw } from 'vue-router'; | ||
import { RouterLinkProps } from 'vue-router'; | ||
import { SetupContext } from 'vue'; | ||
import { VisibilityState as VisibilityState_3 } from '@fastkit/visibility'; | ||
@@ -17,2 +27,16 @@ import { VisibilityStateListener } from '@fastkit/visibility'; | ||
export declare const BODY_SCROLL_LOCK_ATTRIBUTE = "data-body-scroll-lock"; | ||
export declare const BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = "data-scroll-lock-scroller"; | ||
export declare type BodyScrollLockDirective = ObjectDirective<HTMLElement, boolean | undefined | void>; | ||
export declare const bodyScrollLockDirective: BodyScrollLockDirective; | ||
export declare function bodyScrollLockDirectiveArgument(bindingValue?: BodyScrollLockDirectiveBindingValue): [BodyScrollLockDirective, BodyScrollLockDirectiveBindingValue]; | ||
export declare type BodyScrollLockDirectiveBinding = DirectiveBinding<BodyScrollLockDirectiveBindingValue>; | ||
export declare type BodyScrollLockDirectiveBindingValue = boolean | undefined | void; | ||
export declare type ClickOutsideDirective = ObjectDirective<ClickOutsideDirectiveElement, RawClickOutsideDirectiveBindingValue>; | ||
@@ -22,2 +46,4 @@ | ||
export declare function clickOutsideDirectiveArgument(bindingValue: RawClickOutsideDirectiveBindingValue): [ClickOutsideDirective, RawClickOutsideDirectiveBindingValue]; | ||
export declare type ClickOutsideDirectiveBinding = DirectiveBinding<RawClickOutsideDirectiveBindingValue>; | ||
@@ -27,3 +53,3 @@ | ||
handler?: ClickOutsideDirectiveHandler; | ||
conditional?: (ev: MouseEvent | PointerEvent) => boolean; | ||
conditional?: (ev: MouseEvent | PointerEvent, pre?: boolean) => boolean; | ||
include?: () => HTMLElement[]; | ||
@@ -54,2 +80,5 @@ } | ||
export declare function createJavaScriptTransition<CustomProps extends Readonly<ComponentPropsOptions> = {}>(opts: JavaScriptTransitionOptions<CustomProps>): JavaScriptTransition<CustomProps>; | ||
export { CSSProperties } | ||
declare type EmitsOptions = ObjectEmitsOptions | string[]; | ||
@@ -65,2 +94,57 @@ | ||
export declare type ExtractPropInput<O> = O extends object ? { | ||
[K in RequiredKeys<O>]: InferPropType<O[K]>; | ||
} & { | ||
[K in OptionalKeys<O>]?: InferPropType<O[K]>; | ||
} : { | ||
[K in string]: any; | ||
}; | ||
declare type InferPropType<T> = [T] extends [null] ? any : [T] extends [ | ||
{ | ||
type: null | true; | ||
} | ||
] ? any : [T] extends [ | ||
ObjectConstructor | { | ||
type: ObjectConstructor; | ||
} | ||
] ? Record<string, any> : [T] extends [ | ||
BooleanConstructor | { | ||
type: BooleanConstructor; | ||
} | ||
] ? boolean : [T] extends [ | ||
DateConstructor | { | ||
type: DateConstructor; | ||
} | ||
] ? Date : [T] extends [Prop<infer V, infer D>] ? unknown extends V ? D : V : T; | ||
export declare type JavaScriptTransition<CustomProps extends Readonly<ComponentPropsOptions> = {}> = FunctionalComponent<BaseTransitionProps & ExtractPropInput<CustomProps>, {}> & { | ||
__defaults?: ExtractDefaultPropTypes<CustomProps>; | ||
}; | ||
export declare type JavaScriptTransitionHookKey = typeof javaScriptTransitionHookKeys[number]; | ||
declare const javaScriptTransitionHookKeys: readonly ["onBeforeEnter", "onEnter", "onAfterEnter", "onEnterCancelled", "onBeforeLeave", "onLeave", "onAfterLeave", "onLeaveCancelled", "onBeforeAppear", "onAppear", "onAfterAppear", "onAppearCancelled"]; | ||
export declare type JavaScriptTransitionHooks<HostElement = HTMLElement> = { | ||
onBeforeEnter?: (el: HostElement) => void; | ||
onEnter?: (el: HostElement, done: () => void) => void; | ||
onAfterEnter?: (el: HostElement) => void; | ||
onEnterCancelled?: (el: HostElement) => void; | ||
onBeforeLeave?: (el: HostElement) => void; | ||
onLeave?: (el: HostElement, done: () => void) => void; | ||
onAfterLeave?: (el: HostElement) => void; | ||
onLeaveCancelled?: (el: HostElement) => void; | ||
onBeforeAppear?: (el: HostElement) => void; | ||
onAppear?: (el: HostElement, done: () => void) => void; | ||
onAfterAppear?: (el: HostElement) => void; | ||
onAppearCancelled?: (el: HostElement) => void; | ||
}; | ||
export declare interface JavaScriptTransitionOptions<CustomProps extends Readonly<ComponentPropsOptions> = {}, Props = BaseTransitionProps & ExtractPropTypes<CustomProps>> { | ||
props?: CustomProps; | ||
displayName?: string; | ||
render: (props: Props, ctx: SetupContext) => JavaScriptTransitionHooks; | ||
} | ||
export declare interface NavigationableAttrs { | ||
@@ -132,9 +216,11 @@ to?: RouteLocationRaw; | ||
declare type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>; | ||
export declare type RawClickOutsideDirectiveBindingValue = ClickOutsideDirectiveHandler | ClickOutsideDirectiveBindingValue; | ||
export declare type RawNumberProp<D extends number | string | undefined = undefined> = D extends undefined ? { | ||
type: PropType<string | number>; | ||
type: PropType_2<string | number>; | ||
required: true; | ||
} : { | ||
type: PropType<string | number>; | ||
type: PropType_2<string | number>; | ||
default: string | number; | ||
@@ -145,4 +231,45 @@ }; | ||
export declare const rawNumberPropType: PropType<string | number>; | ||
export declare const rawNumberPropType: PropType_2<string | number>; | ||
export declare type RawResizeDirectiveBindingValue = ResizeDirectiveHandler | ResizeDirectiveBindingValue; | ||
declare type RequiredKeys<T> = { | ||
[K in keyof T]: T[K] extends { | ||
required: true; | ||
} ? K : never; | ||
}[keyof T]; | ||
declare interface ResizableElement extends HTMLElement { | ||
__resize_dir?: ResizeDirectiveContext; | ||
} | ||
export declare type ResizeDirective = ObjectDirective<ResizableElement, RawResizeDirectiveBindingValue>; | ||
export declare const resizeDirective: ResizeDirective; | ||
export declare function resizeDirectiveArgument(bindingValue: RawResizeDirectiveBindingValue): [ResizeDirective, RawResizeDirectiveBindingValue]; | ||
export declare interface ResizeDirectiveBindingValue { | ||
handler: ResizeDirectiveHandler; | ||
debounce?: number; | ||
rootMode?: boolean; | ||
} | ||
export declare interface ResizeDirectiveContext { | ||
bindingValue: ResizeDirectiveBindingValue; | ||
handler: Debounced<ResizeDirectiveHandler>; | ||
resizeObserver?: ResizeObserver; | ||
rootResizeHandler?: () => void; | ||
destroy(): void; | ||
} | ||
export declare type ResizeDirectiveHandler = (payload: ResizeDirectivePayload) => any; | ||
export declare type ResizeDirectiveHook = DirectiveHook<ResizableElement, VNode<any, ResizableElement> | null, RawResizeDirectiveBindingValue>; | ||
export declare interface ResizeDirectivePayload { | ||
width: number; | ||
height: number; | ||
} | ||
export declare const state: { | ||
@@ -154,4 +281,6 @@ avairable: boolean; | ||
export declare type StyleValue = NonNullable<HTMLAttributes['style']>; | ||
export declare interface UseKeybord { | ||
(settings: UseKeybordSettings): UseKeybordRef; | ||
(settings: UseKeybordSettings, options?: UseKeybordOptions): UseKeybordRef; | ||
Key: typeof Key; | ||
@@ -197,2 +326,9 @@ } | ||
export declare const VExpandTransition: JavaScriptTransition<{ | ||
expand: { | ||
type: PropType<"width" | "height">; | ||
default: "height"; | ||
}; | ||
}>; | ||
declare interface VisibilityState_2 { | ||
@@ -205,2 +341,4 @@ state: VisibilityState_3; | ||
export declare type WindowResizeHandler = (state: WindowState) => any; | ||
export declare interface WindowState { | ||
@@ -207,0 +345,0 @@ avairable: boolean; |
@@ -1,6 +0,7 @@ | ||
import { computed, onBeforeMount, onBeforeUnmount, reactive } from 'vue'; | ||
import { computed, BaseTransition, h, Transition, onBeforeMount, onBeforeUnmount, reactive } from 'vue'; | ||
import { RouterLink } from 'vue-router'; | ||
import { KeybordService, Key } from '@fastkit/keybord'; | ||
import { IN_WINDOW } from '@fastkit/helpers'; | ||
import { IN_WINDOW, addTransitionendEvent, pushDynamicStyle, debounce } from '@fastkit/helpers'; | ||
import { visibilityManager } from '@fastkit/visibility'; | ||
import { disableBodyScroll, enableBodyScroll } from '@fastkit/body-scroll-lock'; | ||
@@ -19,2 +20,11 @@ /** | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
}; | ||
} | ||
const navigationableEmits = createEmitDefine({ | ||
@@ -92,9 +102,48 @@ click: (ev) => true, | ||
const rawNumberPropType = [String, Number]; | ||
function rawNumberProp(defaultValue) { | ||
return { | ||
type: rawNumberPropType, | ||
required: defaultValue == null ? true : undefined, | ||
default: defaultValue, | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
const javaScriptTransitionHookKeys = [ | ||
'onBeforeEnter', | ||
'onEnter', | ||
'onAfterEnter', | ||
'onEnterCancelled', | ||
'onBeforeLeave', | ||
'onLeave', | ||
'onAfterLeave', | ||
'onLeaveCancelled', | ||
'onBeforeAppear', | ||
'onAppear', | ||
'onAfterAppear', | ||
'onAppearCancelled', | ||
]; | ||
function createJavaScriptTransition(opts) { | ||
const { displayName = 'JavaScriptTransition' } = opts; | ||
// const baseProps: TransitionProps = { | ||
// css: false, | ||
// }; | ||
const Component = (props, ctx) => { | ||
const { slots } = ctx; | ||
const resolvedProps = { | ||
css: false, | ||
}; | ||
const listeners = { | ||
...opts.render(props, ctx), | ||
}; | ||
javaScriptTransitionHookKeys.forEach((key) => { | ||
let _key = key.slice(2); | ||
_key = _key.charAt(0).toLowerCase() + _key.slice(1); | ||
resolvedProps[key] = (el, done) => { | ||
const fn = listeners[key]; | ||
fn && fn(el, done); | ||
ctx.emit(_key, el, done); | ||
}; | ||
}); | ||
return h(Transition, resolvedProps, slots); | ||
}; | ||
Component.displayName = displayName; | ||
Component.props = { | ||
...BaseTransition.props, | ||
...opts.props, | ||
}; | ||
// console.log(opts.props, (Component.props as any).onEnter); | ||
return Component; | ||
} | ||
@@ -187,2 +236,99 @@ | ||
const VExpandTransition = createJavaScriptTransition({ | ||
displayName: 'VExpandTransition', | ||
props: { | ||
expand: { | ||
type: String, | ||
default: 'height', | ||
}, | ||
// className: { | ||
// type: String as PropType<string>, | ||
// default: 'v-expand-transition' as const, | ||
// }, | ||
}, | ||
render(props) { | ||
const { expand: sizeProperty } = props; | ||
const offsetProperty = `offset${sizeProperty.charAt(0).toUpperCase() + sizeProperty.slice(1)}`; | ||
function resetStyles(_el) { | ||
const el = _el; | ||
const { _initialStyle } = el; | ||
if (!_initialStyle) | ||
return; | ||
const size = _initialStyle[sizeProperty]; | ||
el.style.overflow = _initialStyle.overflow || ''; | ||
if (size != null) { | ||
el.style[sizeProperty] = size; | ||
} | ||
delete el._initialStyle; | ||
} | ||
function afterLeave(_el) { | ||
const el = _el; | ||
// if (className && el._parent) { | ||
// el._parent.classList.remove(className); | ||
// } | ||
resetStyles(el); | ||
} | ||
return { | ||
onBeforeEnter(_el) { | ||
const el = _el; | ||
el._parent = el.parentNode; | ||
el._initialStyle = { | ||
transition: el.style.transition, | ||
visibility: el.style.visibility, | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
}, | ||
onEnter(_el, done) { | ||
const el = _el; | ||
const initialStyle = el._initialStyle; | ||
if (!initialStyle) | ||
return; | ||
const offset = `${el[offsetProperty]}px`; | ||
el.style.setProperty('transition', 'none', 'important'); | ||
el.style.visibility = 'hidden'; | ||
el.style.visibility = initialStyle.visibility || ''; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = '0'; | ||
// eslint-disable-next-line no-void | ||
void el.offsetHeight; // force reflow | ||
el.style.transition = initialStyle.transition; | ||
// if (className && el._parent) { | ||
// el._parent.classList.add(className); | ||
// } | ||
requestAnimationFrame(() => { | ||
addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = offset; | ||
}); | ||
}, | ||
onAfterEnter: resetStyles, | ||
onEnterCancelled: resetStyles, | ||
onLeave(_el, done) { | ||
const el = _el; | ||
el._initialStyle = { | ||
transition: '', | ||
visibility: '', | ||
overflow: el.style.overflow, | ||
[sizeProperty]: el.style[sizeProperty], | ||
}; | ||
el.style.overflow = 'hidden'; | ||
el.style[sizeProperty] = `${el[offsetProperty]}px`; | ||
void el.offsetHeight; // force reflow | ||
requestAnimationFrame(() => { | ||
addTransitionendEvent(el, done, { | ||
once: true, | ||
properties: sizeProperty, | ||
}); | ||
el.style[sizeProperty] = '0'; | ||
}); | ||
}, | ||
onAfterLeave: afterLeave, | ||
onLeaveCancelled: afterLeave, | ||
}; | ||
}, | ||
}); | ||
function normalizeRawClickOutsideDirectiveBindingValue(value) { | ||
@@ -200,3 +346,3 @@ if (value && typeof value === 'object') { | ||
const { conditional, include, handler } = value; | ||
if (!handler || (conditional && !conditional(ev))) | ||
if (!handler || (conditional && !conditional(ev, true))) | ||
return; | ||
@@ -228,7 +374,151 @@ if (('isTrusted' in ev && !ev.isTrusted) || | ||
}, | ||
// getSSRProps(binding, vnode) { | ||
// return undefined; | ||
// }, | ||
}; | ||
function clickOutsideDirectiveArgument(bindingValue) { | ||
return [clickOutsideDirective, bindingValue]; | ||
} | ||
export { ClickOutsideDirectiveElementSymbol, clickOutsideDirective, createEmitDefine, navigationableEmits, navigationableProps, rawNumberProp, rawNumberPropType, state$1 as state, useKeybord, useNavigationable, useVisibility, useWindow }; | ||
const BODY_SCROLL_LOCK_ATTRIBUTE = 'data-body-scroll-lock'; | ||
const BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE = 'data-scroll-lock-scroller'; | ||
{ | ||
pushDynamicStyle(`[${BODY_SCROLL_LOCK_ATTRIBUTE}] { overflow: hidden; }`); | ||
} | ||
class Stacks { | ||
constructor() { | ||
this.els = []; | ||
this.active = false; | ||
} | ||
check() { | ||
const active = this.els.length > 0; | ||
if (active && !this.active) { | ||
this.activate(); | ||
} | ||
else if (!active && this.active) { | ||
this.deactivate(); | ||
} | ||
} | ||
activate() { | ||
document.documentElement.setAttribute(BODY_SCROLL_LOCK_ATTRIBUTE, ''); | ||
this.active = true; | ||
} | ||
deactivate() { | ||
document.documentElement.removeAttribute(BODY_SCROLL_LOCK_ATTRIBUTE); | ||
this.active = false; | ||
} | ||
push(el) { | ||
if (!this.els.includes(el)) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
disableBodyScroll(lockElement); | ||
this.els.push(el); | ||
this.check(); | ||
} | ||
} | ||
remove(el) { | ||
const index = this.els.indexOf(el); | ||
if (index !== -1) { | ||
const lockElement = el.querySelector(`[${BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE}]`) || el; | ||
enableBodyScroll(lockElement); | ||
this.els.splice(index, 1); | ||
this.check(); | ||
} | ||
} | ||
} | ||
const stacks = new Stacks(); | ||
const bodyScrollLockDirective = { | ||
mounted(el, binding) { | ||
binding.value && stacks.push(el); | ||
}, | ||
updated(el, binding) { | ||
if (binding.value) { | ||
stacks.push(el); | ||
} | ||
else { | ||
stacks.remove(el); | ||
} | ||
}, | ||
unmounted(el) { | ||
stacks.remove(el); | ||
}, | ||
}; | ||
function bodyScrollLockDirectiveArgument(bindingValue) { | ||
return [bodyScrollLockDirective, bindingValue]; | ||
} | ||
const getDefaults = () => { | ||
return { | ||
debounce: 0, | ||
}; | ||
}; | ||
function resolveValue(value) { | ||
const defaults = getDefaults(); | ||
if (typeof value === 'function') { | ||
return { | ||
...defaults, | ||
handler: value, | ||
}; | ||
} | ||
return { | ||
...defaults, | ||
...value, | ||
}; | ||
} | ||
const hook = function hook(el, binding) { | ||
const { __resize_dir } = el; | ||
if (!binding.value) { | ||
__resize_dir && __resize_dir.destroy(); | ||
return; | ||
} | ||
if (__resize_dir) { | ||
return; | ||
} | ||
const bindingValue = resolveValue(binding.value); | ||
const { handler: _handler, debounce: _debounce, rootMode } = bindingValue; | ||
const handler = debounce(_handler, _debounce); | ||
const ctx = { | ||
bindingValue, | ||
handler, | ||
destroy() { | ||
if (!el.__resize_dir) | ||
return; | ||
handler.clear(); | ||
if (ctx.rootResizeHandler) { | ||
window.removeEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
if (ctx.resizeObserver) { | ||
ctx.resizeObserver.unobserve(el); | ||
ctx.resizeObserver.disconnect(); | ||
delete ctx.resizeObserver; | ||
} | ||
delete el.__resize_dir; | ||
}, | ||
}; | ||
if (rootMode) { | ||
ctx.rootResizeHandler = () => { | ||
handler({ width: window.innerWidth, height: window.innerHeight }); | ||
}; | ||
window.addEventListener('resize', ctx.rootResizeHandler, false); | ||
} | ||
else { | ||
ctx.resizeObserver = new ResizeObserver((entries) => { | ||
for (const entry of entries) { | ||
const { width, height } = entry.contentRect; | ||
handler({ width, height }); | ||
} | ||
}); | ||
ctx.resizeObserver.observe(el); | ||
} | ||
el.__resize_dir = ctx; | ||
}; | ||
const beforeUnmount = function beforeUnmount(el) { | ||
const { __resize_dir } = el; | ||
__resize_dir && __resize_dir.destroy(); | ||
}; | ||
const resizeDirective = { | ||
mounted: hook, | ||
updated: hook, | ||
beforeUnmount, | ||
}; | ||
function resizeDirectiveArgument(bindingValue) { | ||
return [resizeDirective, bindingValue]; | ||
} | ||
export { BODY_SCROLL_LOCK_ATTRIBUTE, BODY_SCROLL_LOCK_SCROLLER_ATTRIBUTE, ClickOutsideDirectiveElementSymbol, VExpandTransition, bodyScrollLockDirective, bodyScrollLockDirectiveArgument, clickOutsideDirective, clickOutsideDirectiveArgument, createEmitDefine, createJavaScriptTransition, navigationableEmits, navigationableProps, rawNumberProp, rawNumberPropType, resizeDirective, resizeDirectiveArgument, state$1 as state, useKeybord, useNavigationable, useVisibility, useWindow }; |
{ | ||
"name": "@fastkit/vue-utils", | ||
"version": "0.1.11", | ||
"version": "0.1.12", | ||
"description": "@fastkit/vue-utils", | ||
@@ -34,8 +34,8 @@ "buildOptions": { | ||
"dependencies": { | ||
"@fastkit/body-scroll-lock": "0.1.11", | ||
"@fastkit/visibility": "0.1.11", | ||
"@fastkit/keybord": "0.1.11", | ||
"@fastkit/helpers": "0.1.11", | ||
"@fastkit/tiny-logger": "0.1.11" | ||
"@fastkit/body-scroll-lock": "0.1.12", | ||
"@fastkit/visibility": "0.1.12", | ||
"@fastkit/keybord": "0.1.12", | ||
"@fastkit/helpers": "0.1.12", | ||
"@fastkit/tiny-logger": "0.1.12" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
64236
1838
+ Added@fastkit/body-scroll-lock@0.1.12(transitive)
+ Added@fastkit/helpers@0.1.12(transitive)
+ Added@fastkit/keybord@0.1.12(transitive)
+ Added@fastkit/tiny-logger@0.1.12(transitive)
+ Added@fastkit/visibility@0.1.12(transitive)
- Removed@fastkit/body-scroll-lock@0.1.11(transitive)
- Removed@fastkit/helpers@0.1.11(transitive)
- Removed@fastkit/keybord@0.1.11(transitive)
- Removed@fastkit/tiny-logger@0.1.11(transitive)
- Removed@fastkit/visibility@0.1.11(transitive)
Updated@fastkit/helpers@0.1.12
Updated@fastkit/keybord@0.1.12
Updated@fastkit/tiny-logger@0.1.12
Updated@fastkit/visibility@0.1.12