diff --git a/docs/src/pages/vue-composables/use-render-cache.md b/docs/src/pages/vue-composables/use-render-cache.md index a6118c880c7..cc01da403cc 100644 --- a/docs/src/pages/vue-composables/use-render-cache.md +++ b/docs/src/pages/vue-composables/use-render-cache.md @@ -31,14 +31,12 @@ setup () { ``` ```js -interface useRenderCacheObject { +function useRenderCache(): { getCache: (key: string, defaultValue?: T | (() => T)) => T | undefined; setCache: (key: string, value: T) => void; hasCache: (key: string) => boolean; clearCache: (key?: string) => void; -} - -function useRenderCache(): useRenderCacheObject; +}; ``` ## Example diff --git a/docs/src/pages/vue-composables/use-split-attrs.md b/docs/src/pages/vue-composables/use-split-attrs.md new file mode 100644 index 00000000000..0ea9f44ff43 --- /dev/null +++ b/docs/src/pages/vue-composables/use-split-attrs.md @@ -0,0 +1,51 @@ +--- +title: useSplitAttrs composable +desc: What is useSplitAttrs() composable and how you can use it +keys: useSplitAttrs +badge: Quasar v2.15+ +--- + +Vue's `attrs` in a component can contain both listeners and real HTML attributes. The `useSplitAttrs()` composable breaks down this Vue attr object into the two categories and keeps them updated. + +## Syntax + +```js +import { useSplitAttrs } from 'quasar' + +setup () { + const { + attributes, + listeners + } = useSplitAttrs() + + // ... +} +``` + +```js +function useSplitAttrs(): { + attributes: Ref>; + listeners: Ref>; +}; +``` + +## Example + +```js +import { useSplitAttrs } from 'quasar' + +setup () { + const { + attributes, // is a Vue ref() + listeners // is a Vue ref() + } = useSplitAttrs() + + console.log(attributes.value) + // prints out a key-value object + + console.log(listeners.value) + // prints out a key-value object + + // ... +} +``` diff --git a/docs/src/pages/vue-composables/use-tick.md b/docs/src/pages/vue-composables/use-tick.md index 16b649212d9..cff287db387 100644 --- a/docs/src/pages/vue-composables/use-tick.md +++ b/docs/src/pages/vue-composables/use-tick.md @@ -27,12 +27,10 @@ setup () { ``` ```js -interface useTickObject { +function useTick(): { registerTick(fn: () => void): void; removeTick(): void; -} - -export function useTick(): useTickObject; +}; ``` ## Example @@ -57,3 +55,17 @@ setup () { // is time for it } ``` + +Should you need more than one useTick() per component, simply rename the functions of the returned object: + +```js +const { + registerTick: registerFirstTick, + removeTick: removeFirstTick +} = useTick() + +const { + registerTick: registerSecondTick, + removeTick: removeSecondTick +} = useTick() +``` diff --git a/docs/src/pages/vue-composables/use-timeout.md b/docs/src/pages/vue-composables/use-timeout.md index ecbac0f03d2..ea1b119f5a7 100644 --- a/docs/src/pages/vue-composables/use-timeout.md +++ b/docs/src/pages/vue-composables/use-timeout.md @@ -27,12 +27,10 @@ setup () { ``` ```js -interface useTimeoutObject { +function useTimeout(): { registerTimeout(fn: () => void, delay?: string | number): void; removeTimeout(): void; -} - -export function useTimeout(): useTimeoutObject; +}; ``` ## Example @@ -60,3 +58,17 @@ setup () { // time you register/override the timeout } ``` + +Should you need more than one useTimeout() per component, simply rename the functions of the returned object: + +```js +const { + registerTimeout: registerFirstTimeout, + removeTimeout: removeFirstTimeout +} = useTimeout() + +const { + registerTimeout: registerSecondTimeout, + removeTimeout: removeSecondTimeout +} = useTimeout() +``` diff --git a/ui/src/components/editor/QEditor.js b/ui/src/components/editor/QEditor.js index c819ceba7cf..264557aacd3 100644 --- a/ui/src/components/editor/QEditor.js +++ b/ui/src/components/editor/QEditor.js @@ -5,7 +5,7 @@ import { getToolbar, getFonts, getLinkEditor } from './editor-utils.js' import useDark, { useDarkProps } from '../../composables/private/use-dark.js' import useFullscreen, { useFullscreenProps, useFullscreenEmits } from '../../composables/private/use-fullscreen.js' -import useSplitAttrs from '../../composables/private/use-split-attrs.js' +import useSplitAttrs from '../../composables/use-split-attrs.js' import { createComponent } from '../../utils/private/create.js' import { stopAndPrevent } from '../../utils/event.js' @@ -85,13 +85,13 @@ export default createComponent({ 'linkHide' ], - setup (props, { slots, emit, attrs }) { - const { proxy, vnode } = getCurrentInstance() + setup (props, { slots, emit }) { + const { proxy } = getCurrentInstance() const { $q } = proxy const isDark = useDark(props, $q) const { inFullscreen, toggleFullscreen } = useFullscreen() - const splitAttrs = useSplitAttrs(attrs, vnode) + const splitAttrs = useSplitAttrs() const rootRef = ref(null) const contentRef = ref(null) diff --git a/ui/src/composables.js b/ui/src/composables.js index b4e59a2dc0b..2220e95d3a9 100644 --- a/ui/src/composables.js +++ b/ui/src/composables.js @@ -1,17 +1,19 @@ -import useRenderCache from './composables/use-render-cache.js' import useDialogPluginComponent from './composables/use-dialog-plugin-component.js' import useFormChild from './composables/use-form-child.js' import useMeta from './composables/use-meta.js' import useQuasar from './composables/use-quasar.js' +import useRenderCache from './composables/use-render-cache.js' +import useSplitAttrs from './composables/use-split-attrs.js' import useTick from './composables/use-tick.js' import useTimeout from './composables/use-timeout.js' export { - useRenderCache, useDialogPluginComponent, useFormChild, useMeta, useQuasar, + useRenderCache, + useSplitAttrs, useTick, useTimeout } diff --git a/ui/src/composables/private/use-field.js b/ui/src/composables/private/use-field.js index c4dec8bba4a..a2400e86d0d 100644 --- a/ui/src/composables/private/use-field.js +++ b/ui/src/composables/private/use-field.js @@ -6,7 +6,7 @@ import QSpinner from '../../components/spinner/QSpinner.js' import useDark, { useDarkProps } from '../../composables/private/use-dark.js' import useId, { getId } from './use-id.js' import useValidate, { useValidateProps } from './use-validate.js' -import useSplitAttrs from './use-split-attrs.js' +import useSplitAttrs from '../use-split-attrs.js' import { hSlot } from '../../utils/private/render.js' import { prevent, stopAndPrevent } from '../../utils/event.js' @@ -69,7 +69,7 @@ export const useFieldProps = { export const useFieldEmits = [ 'update:modelValue', 'clear', 'focus', 'blur', 'popupShow', 'popupHide' ] export function useFieldState ({ requiredForAttr = true, tagProp } = {}) { - const { props, attrs, proxy, vnode } = getCurrentInstance() + const { props, proxy } = getCurrentInstance() const isDark = useDark(props, proxy.$q) const targetUid = useId(props.for, requiredForAttr) @@ -90,7 +90,7 @@ export function useFieldState ({ requiredForAttr = true, tagProp } = {}) { focused: ref(false), hasPopupOpen: false, - splitAttrs: useSplitAttrs(attrs, vnode), + splitAttrs: useSplitAttrs(), targetUid, rootRef: ref(null), diff --git a/ui/src/composables/private/use-split-attrs.js b/ui/src/composables/use-split-attrs.js similarity index 81% rename from ui/src/composables/private/use-split-attrs.js rename to ui/src/composables/use-split-attrs.js index 5d5cb7e075a..26d123c8edc 100644 --- a/ui/src/composables/private/use-split-attrs.js +++ b/ui/src/composables/use-split-attrs.js @@ -1,8 +1,10 @@ -import { ref, onBeforeUpdate } from 'vue' +import { ref, onBeforeUpdate, getCurrentInstance } from 'vue' const listenerRE = /^on[A-Z]/ -export default function (attrs, vnode) { +export default function () { + const { attrs, vnode } = getCurrentInstance() + const acc = { listeners: ref({}), attributes: ref({}) diff --git a/ui/types/composables.d.ts b/ui/types/composables.d.ts index 88822318e7c..34f8ecaaecd 100644 --- a/ui/types/composables.d.ts +++ b/ui/types/composables.d.ts @@ -3,15 +3,6 @@ import { MetaOptions } from "./meta"; import { Ref } from "vue"; import { QVueGlobals } from "./globals"; -interface useRenderCacheObject { - getCache: (key: string, defaultValue?: T | (() => T)) => T | undefined; - setCache: (key: string, value: T) => void; - hasCache: (key: string) => boolean; - clearCache: (key?: string) => void; -} - -export function useRenderCache(): useRenderCacheObject; - interface useDialogPluginComponent { (): { dialogRef: Ref; @@ -40,16 +31,24 @@ export function useMeta(options: MetaOptions | (() => MetaOptions)): void; export function useQuasar(): QVueGlobals; -interface useTickObject { +export function useRenderCache(): { + getCache: (key: string, defaultValue?: T | (() => T)) => T | undefined; + setCache: (key: string, value: T) => void; + hasCache: (key: string) => boolean; + clearCache: (key?: string) => void; +}; + +export function useSplitAttrs(): { + attributes: Ref>; + listeners: Ref>; +}; + +export function useTick(): { registerTick(fn: () => void): void; removeTick(): void; -} - -export function useTick(): useTickObject; +}; -interface useTimeoutObject { +export function useTimeout(): { registerTimeout(fn: () => void, delay?: string | number): void; removeTimeout(): void; -} - -export function useTimeout(): useTimeoutObject; +};