github quasarframework/quasar quasar-v2.34.0

latest release: @quasar/app-vite-v3.10.1
4 hours ago

New

  • feat(ui): useElementSize() composable -> reactive elementSize ({ width, height }) of an element or component ref, with an onResize hook, a debounce window and a disabled switch; QResizeObserver is now built on it
  • feat(ui): v-resize directive -> the template-side form of useElementSize(): reports an element's size without adding a node (the initial size, then only on change), debounce as the argument (v-resize:100), once modifier, a handler returning false stops it
  • feat(ui): useScroll() composable -> reactive scroll position, direction, delta and inflection point of the page or of a scrollable container, with an onScroll hook, axis, debounce and disabled; QScrollObserver is now built on it
  • feat(ui): useFilePicker() composable -> opens the native file dialog from setup code without rendering a file input; openFilePicker() resolves with the accepted files (null when dismissed) and the files get validated by the same rules as QFile (accept, maxFileSize, maxTotalSize, maxFiles, filter...)
  • feat(ui): useDropZone() composable and v-drop-zone directive -> turn any element or component into a drop target for files, with the QFile validation rules, a reactive isOverDropZone (the directive sets a q-drop-zone--over class instead) and rejected-file reporting. QFile and QUploader now handle drops through it
  • feat(ui): useObjectUrl() composable -> a reactive object URL for a Blob, File or MediaSource, revoked for you when the source changes and when the component is destroyed
  • feat(ui): useEventListener() composable -> attaches a listener to an element, window, document or component, following reactive targets, event names and options; removed on unmount
  • feat(ui): useMutation() composable -> the setup-code counterpart of v-mutation, with the latest mutationRecords as reactive state
  • feat(ui): useSoftFullscreen() composable -> the in-page fullscreen behind the fullscreen prop of QTable, QCarousel and QEditor (back button, route-change exit, scroll restore, popups kept on top), now usable on any element or component
  • feat(ui): useIdle() composable -> isIdle flips after timeout ms with no user activity, plus lastActive and resetIdle(); hidden-page time counts as inactivity
  • feat(ui): useKeyboardShortcut() composable -> runs a handler for a "Mod+K" style shortcut (Mod is Meta on macOS, Ctrl elsewhere), matching either the layout-aware key or the physical key code; unmodified printable shortcuts stay quiet while typing in a field
  • feat(ui): useWebSocket() composable -> a WebSocket connection kept alive from a component: status, last message, send queue flushed on open, auto reconnect with backoff (paused while offline), optional heartbeat, closed on unmount
  • feat(ui): useEventSource() composable -> Server-Sent Events from a component: named events, last event id, and a reconnect where the browser gives up; closed on unmount
  • feat(ui): useBroadcastChannel() composable -> message the other tabs, windows, iframes and workers of the same origin; closed on unmount
  • feat(ui): useWebWorker() composable -> connects a component to a Web Worker script of your own (a URL, a Worker or a factory such as a Vite ?worker import): status, last message and error, postWorkerMessage(), a terminateWorker() that frees the thread until the next message, and onCreate/onMessage/onError/onTerminate(reason) hooks
  • feat(ui): useWebWorkerFn() composable -> runs a function off the main thread: runWorkerFn(...args) resolves with its result, with timeout, Transferables, script dependencies, one hook per outcome (onSuccess/onError/onTimeout/onTerminate) and an inline run on the SSR server
  • feat(ui): useDebounce() and useThrottle() composables -> the debounce()/throttle() utils applied to a function, with the waiting call cancelled on deactivation and unmount; fn.isPending is reactive on the useDebounce() one
  • feat(ui): debounce() and throttle() utils -> debounce() takes { leading, trailing, maxWait } as its third param (a boolean still means "immediate") and gains flush() plus an isPending property; throttle() gains cancel(), flush() and an opt-in trailing call (throttle(fn, limit, true)) so a burst no longer ends on a stale state
  • feat(ui): useTimeout() and useInterval() -> also return isTimeoutPending / isIntervalActive reactive flags
  • feat(ui): useTimeout(), useInterval(), useAnimationFrame() and useTick() -> work outside of a component (they used to warn and then throw when the timer fired); call the remove method when done
  • feat(ui): useIntersection() -> returns refreshIntersection() and stopIntersection(), named after the composable like the new ones; refresh()/stop() keep working
  • feat(ui): LocalStorage/SessionStorage useStorage() -> binds a stored item to a Vue ref: an assignment persists right away, nested changes of an Object or Array persist too, and the ref follows setItem()/removeItem()/clear(), its other refs and other tabs. Default from a function, disabled, onError, typed keys through the augmentable LocalStorageItems/SessionStorageItems interfaces, SSR-safe
  • feat(ui): Cookies useCookie() -> binds a cookie to a Vue ref with the cookie options of set(); follows set()/remove(), its other refs and (where the browser has the Cookie Store API) cookies set by the server, another tab or natively. Default from a function, typed names through the augmentable CookieValues interface; on the server it reads the request cookie and writes a Set-Cookie header
  • feat(ui): AppNetwork plugin -> reactive $q.network with the online state and, where the browser has the Network Information API, effectiveType/downlink/rtt/saveData
  • feat(ui): AppWakeLock plugin -> $q.wakeLock wraps the Screen Wake Lock API (isCapable, isActive, request/release/toggle) and re-acquires the lock when the page becomes visible again
  • feat(Screen): $q.screen.orientation -> reactive { type, angle, portrait, landscape } of the device screen
  • feat(QBtnGroup/QBtnToggle): vertical prop -> stacks the buttons in a column, with the corners and seams drawn for that direction (#7766)
  • feat(QBtnToggle): align prop -> aligns the content of every option button (overridable per option), so the icons of a vertical toggle line up
  • feat(QInfiniteScroll): horizontal prop -> loads more when the row is scrolled to its inline end (the left one in RTL), reverse included (#6709)
  • feat(QTable): body-expand slot -> an expansion row declared after each body row while QTable keeps rendering the row itself (and its body-cell-[name] slots); no more taking over the whole row through the body slot (#4380)
  • feat(QTr): expandable prop -> an expansion row that can slide open and closed with a QSlideTransition inside its cell (#4380)
  • feat(QTable): a column's field is optional -> a column rendered entirely through its body-cell-[name] slot needs none
  • feat(ui): TypeScript -> Quasar directives are type-checked in templates (value, modifiers and argument) through Vue's GlobalDirectives

Fixes

  • fix(QTooltip): a closing QDialog or QMenu returns focus to its opener -> the opener's tooltip no longer shows as if it had been tabbed onto (#18556)
  • fix(QMenu/QTooltip): a target that resolves after the model turns on (v-model written before :target) -> the popup is anchored to it instead of rendering at its static position in Chromium (#18559)
  • fix(QItem): side, overline, caption and header labels -> they follow a dark mode switch and an active item's color in Chrome instead of keeping the previous color
  • fix(ui): useIntersection(), QIntersection and v-intersection -> a once observation that fired resumes observing when once goes away
  • fix(ui): v-intersection -> a null value disables it instead of throwing; the v-intersection/v-mutation/v-resize/v-drop-zone disable values are typed as false | null instead of Boolean, which invited true
  • fix(QScrollObserver): with axis="both" -> no longer emits an unchanged position (on mount, on an RTL flip); getPosition() returns a snapshot instead of the live internal object
  • fix(Screen): setDebounce() -> the pending update of the previous listener is applied right away instead of running late on a target it was removed from
  • fix(LocalStorage/SessionStorage): setItem(key, null | undefined) removes the item, so a null read always means a missing item (older versions stored the strings the browser made of them); a stored RegExp keeps its flags (what older versions stored still decodes); an item stored natively as an empty String reads as '' instead of null
  • fix(Cookies): getAll() decodes and parses the values as get() does; on the server, set() replaces the request cookie so getAll() no longer returns the previous value; remove() is typed to accept the same attributes as set() (a __Secure-/__Host- cookie needs secure) and set() the Object/Array/Number values it always stored
  • fix(ui): TypeScript -> template refs to Quasar components carry their instance methods (useTemplateRef('btn').value.click(), .validate()...)
  • fix(ui): TypeScript -> MetaOptions and noop are importable from "quasar"

Other

  • refactor(ui): QLayout, QHeader, QFooter, QTabs and QScrollArea observe through useElementSize()/useScroll() instead of mounting hidden QResizeObserver/QScrollObserver children, so layout pages carry fewer component instances and re-render less on scroll

Donations

Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:

Don't miss a new quasar release

NewReleases is sending notifications on new releases.