@melt-ui/svelte
Advanced tools
Comparing version 0.85.0 to 0.86.0
@@ -160,3 +160,4 @@ /// <reference types="svelte" /> | ||
highlightOnHover: boolean; | ||
rootElement: ParentNode | undefined; | ||
}>; | ||
}; |
/// <reference types="svelte" /> | ||
import { type InteractOutsideEvent } from '../../internal/actions/index.js'; | ||
import type { MeltActionReturn } from '../../internal/types.js'; | ||
@@ -128,3 +129,3 @@ import { type Readable } from 'svelte/store'; | ||
escapeBehavior: import("../../internal/actions/index.js").EscapeBehaviorType; | ||
onOutsideClick: ((event: import("../../internal/actions/index.js").InteractOutsideEvent) => void) | undefined; | ||
onOutsideClick: ((event: InteractOutsideEvent) => void) | undefined; | ||
preventScroll: boolean; | ||
@@ -134,3 +135,4 @@ preventTextSelectionOverflow: boolean; | ||
highlightOnHover: boolean; | ||
rootElement: ParentNode | undefined; | ||
}>; | ||
}; |
import { usePopper } from '../../internal/actions/index.js'; | ||
import { FIRST_LAST_KEYS, addHighlight, addMeltEventListener, back, createClickOutsideIgnore, createElHelpers, createTypeaheadSearch, derivedVisible, disabledAttr, effect, executeCallbacks, forward, generateId, getOptions, getPortalDestination, isBrowser, isElement, isElementDisabled, isHTMLButtonElement, isHTMLElement, isHTMLInputElement, isObject, kbd, last, makeElement, next, noop, omit, overridable, prev, removeHighlight, removeScroll, stripValues, styleToString, toWritableStores, toggle, withGet, } from '../../internal/helpers/index.js'; | ||
import { FIRST_LAST_KEYS, addHighlight, addMeltEventListener, back, createClickOutsideIgnore, createElHelpers, createTypeaheadSearch, derivedVisible, disabledAttr, effect, executeCallbacks, forward, generateId, getOptions, getPortalDestination, isBrowser, isElement, isElementDisabled, isHTMLButtonElement, isHTMLElement, isHTMLInputElement, isObject, kbd, last, makeElement, next, noop, omit, overridable, prev, removeHighlight, removeScroll, stripValues, styleToString, toWritableStores, toggle, withGet, getElementById, } from '../../internal/helpers/index.js'; | ||
import { dequal as deepEqual } from 'dequal'; | ||
@@ -32,2 +32,3 @@ import { tick } from 'svelte'; | ||
preventTextSelectionOverflow: true, | ||
rootElement: undefined, | ||
}; | ||
@@ -57,3 +58,12 @@ export const listboxIdParts = ['trigger', 'menu', 'label']; | ||
}); | ||
const { scrollAlignment, loop, closeOnOutsideClick, escapeBehavior, preventScroll, portal, forceVisible, positioning, multiple, arrowSize, disabled, required, typeahead, name: nameProp, highlightOnHover, onOutsideClick, preventTextSelectionOverflow, } = options; | ||
const { scrollAlignment, loop, closeOnOutsideClick, escapeBehavior, preventScroll, portal, forceVisible, positioning, multiple, arrowSize, disabled, required, typeahead, name: nameProp, highlightOnHover, onOutsideClick, preventTextSelectionOverflow, rootElement, } = options; | ||
const $rootElement = rootElement.get(); | ||
if (isBrowser && $rootElement === undefined) { | ||
rootElement.set(document); | ||
} | ||
else { | ||
if (props?.portal === undefined) { | ||
portal.set($rootElement); | ||
} | ||
} | ||
const { name, selector } = createElHelpers(withDefaults.builder); | ||
@@ -110,3 +120,3 @@ const ids = toWritableStores({ ...generateIds(listboxIdParts), ...withDefaults.ids }); | ||
await tick(); | ||
const menuElement = document.getElementById(ids.menu.get()); | ||
const menuElement = getElementById(ids.menu.get(), rootElement.get()); | ||
if (!isHTMLElement(menuElement)) | ||
@@ -221,3 +231,3 @@ return; | ||
return; | ||
const menuEl = document.getElementById(ids.menu.get()); | ||
const menuEl = getElementById(ids.menu.get(), rootElement.get()); | ||
if (!isHTMLElement(menuEl)) | ||
@@ -266,3 +276,3 @@ return; | ||
// Get all the menu items. | ||
const menuElement = document.getElementById(ids.menu.get()); | ||
const menuElement = getElementById(ids.menu.get(), rootElement.get()); | ||
if (!isHTMLElement(menuElement)) | ||
@@ -309,3 +319,3 @@ return; | ||
else if (typeahead.get()) { | ||
const menuEl = document.getElementById(ids.menu.get()); | ||
const menuEl = getElementById(ids.menu.get(), rootElement.get()); | ||
if (!isHTMLElement(menuEl)) | ||
@@ -486,3 +496,3 @@ return; | ||
return; | ||
const menuElement = document.getElementById(ids.menu.get()); | ||
const menuElement = getElementById(ids.menu.get(), rootElement.get()); | ||
if (!isHTMLElement(menuElement)) | ||
@@ -489,0 +499,0 @@ return; |
@@ -115,3 +115,3 @@ import type { EscapeBehaviorType, FloatingConfig, InteractOutsideEvent, PortalConfig } from '../../internal/actions/index.js'; | ||
* If not undefined, the listbox menu will be rendered within the provided element or selector. | ||
* | ||
* Otherwise, the `rootElement`, if provided, will be used. | ||
* @default 'body' | ||
@@ -152,2 +152,8 @@ */ | ||
ids?: Partial<IdObj<ListboxIdParts>>; | ||
/** | ||
* By default, MeltUI uses the `document` as the root element to find your components, if you are using a shadow-dom or want to specify you own root element you should provide it here. | ||
* | ||
* @default document | ||
*/ | ||
rootElement?: ParentNode; | ||
}; | ||
@@ -154,0 +160,0 @@ export type ListboxOptionProps<Value = unknown> = ListboxOption<Value> & { |
@@ -123,3 +123,4 @@ /// <reference types="svelte" /> | ||
highlightOnHover: boolean; | ||
rootElement: ParentNode | undefined; | ||
}>; | ||
}; |
@@ -5,3 +5,3 @@ // Modified from Grail UI v0.9.6 (2023-06-10) | ||
import { flip, offset, arrow, shift, size, computePosition, autoUpdate, } from '@floating-ui/dom'; | ||
import { isHTMLElement, isObject, noop } from '../../helpers/index.js'; | ||
import { isAttachedToDocument, isHTMLElement, isObject, noop, } from '../../helpers/index.js'; | ||
const defaultConfig = { | ||
@@ -74,4 +74,3 @@ strategy: 'absolute', | ||
return; | ||
// if the reference is no longer in the document (e.g. it was removed), ignore it | ||
if (isHTMLElement(reference) && !reference.ownerDocument.documentElement.contains(reference)) | ||
if (!isAttachedToDocument(reference)) | ||
return; | ||
@@ -78,0 +77,0 @@ const { placement, strategy } = options; |
import { getOwnerDocument, isOrContainsTarget } from '../../helpers/elements.js'; | ||
import { addEventListener, isElement, executeCallbacks, noop, debounce, } from '../../helpers/index.js'; | ||
import { addEventListener, isElement, executeCallbacks, noop, debounce, isShadowRoot, isHTMLElement, } from '../../helpers/index.js'; | ||
const layers = new Set(); | ||
@@ -50,3 +50,7 @@ export const useInteractOutside = ((node, config = {}) => { | ||
interceptedEvents[eventType] = false; | ||
handler?.(e); | ||
const computedData = {}; | ||
if (isHTMLElement(e.target) && isShadowRoot(e.target.shadowRoot)) { | ||
computedData.shadowTarget = e.composedPath()[0]; | ||
} | ||
handler?.(e, computedData); | ||
}); | ||
@@ -68,3 +72,3 @@ }; | ||
*/ | ||
const onPointerDownDebounced = debounce((e) => { | ||
const onPointerDownDebounced = debounce((e, computedEventData) => { | ||
if (!wasTopLayerInPointerDownCapture || isAnyEventIntercepted()) | ||
@@ -74,3 +78,3 @@ return; | ||
onInteractOutsideStart?.(e); | ||
const target = e.target; | ||
const target = computedEventData?.shadowTarget ? computedEventData.shadowTarget : e.target; | ||
if (isElement(target) && isOrContainsTarget(node, target)) { | ||
@@ -77,0 +81,0 @@ isPointerDownInside = true; |
export type InteractOutsideEvent = PointerEvent | MouseEvent | TouchEvent; | ||
export type InteractOutsideInterceptEventType = 'pointerdown' | 'pointerup' | 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' | 'click'; | ||
export type InteractOutsideInterceptHandler<E extends InteractOutsideInterceptEventType> = (ev: HTMLElementEventMap[E]) => void; | ||
export type InteractOutsideInterceptHandler<E extends InteractOutsideInterceptEventType> = (ev: HTMLElementEventMap[E], computedEventData?: ComputedEventData) => void; | ||
/** | ||
* Some event data is lost when the event is delayed, debounced or throttled | ||
* as described in the dom-spec - https://dom.spec.whatwg.org/#event-path | ||
* For this reason we can pre-save any needed data and store | ||
* it here before being passed on the related events | ||
* */ | ||
export type ComputedEventData = { | ||
shadowTarget?: EventTarget; | ||
}; | ||
export type InteractOutsideConfig = { | ||
@@ -10,3 +19,3 @@ /** | ||
*/ | ||
onInteractOutside?: (e: InteractOutsideEvent) => void; | ||
onInteractOutside?: (e: InteractOutsideEvent, computedEventData?: ComputedEventData) => void; | ||
/** | ||
@@ -13,0 +22,0 @@ * Callback fired when an outside interaction event starts, |
@@ -6,2 +6,3 @@ import type { Readable, Writable } from 'svelte/store'; | ||
export declare function isDocument(element: unknown): element is Document; | ||
export declare function isShadowRoot(element: unknown): element is ShadowRoot; | ||
export declare function isElement(element: unknown): element is Element; | ||
@@ -22,1 +23,2 @@ export declare function isHTMLElement(element: unknown): element is HTMLElement; | ||
export declare function isWritable(value: unknown): value is Writable<unknown>; | ||
export declare function isAttachedToDocument(element: unknown): boolean; |
@@ -8,2 +8,5 @@ export const isBrowser = typeof document !== 'undefined'; | ||
} | ||
export function isShadowRoot(element) { | ||
return element instanceof ShadowRoot; | ||
} | ||
export function isElement(element) { | ||
@@ -64,1 +67,12 @@ return element instanceof Element; | ||
} | ||
export function isAttachedToDocument(element) { | ||
if (!isHTMLElement(element)) | ||
return false; | ||
const rootNode = element.getRootNode(); | ||
if (rootNode === document) | ||
return true; | ||
if (isShadowRoot(rootNode)) { | ||
return rootNode.ownerDocument === document; | ||
} | ||
return false; | ||
} |
import type { Action } from 'svelte/action'; | ||
import { type Readable, type Stores, type StoresValues } from 'svelte/store'; | ||
export declare function getElementByMeltId(id: string, rootElement?: ParentNode): HTMLElement | null; | ||
export declare function getElementById(id: string, rootElement?: ParentNode): HTMLElement | null; | ||
export declare const hiddenAction: <T extends Record<string, unknown>>(obj: T) => T; | ||
@@ -5,0 +6,0 @@ type ElementCallback<S extends Stores | undefined> = S extends Stores ? (values: StoresValues<S>) => Record<string, any> | ((...args: any[]) => Record<string, any>) : () => Record<string, any> | ((...args: any[]) => Record<string, any>); |
@@ -5,2 +5,5 @@ import { derived } from 'svelte/store'; | ||
import { lightable } from './store/lightable.js'; | ||
/* @deprecated | ||
* We need to stop using `data-melt-id` and use normal ids for a11y compatibility. | ||
* Use the `id` and use `getElementById` */ | ||
export function getElementByMeltId(id, rootElement) { | ||
@@ -12,2 +15,8 @@ if (!isBrowser) | ||
} | ||
export function getElementById(id, rootElement) { | ||
if (!isBrowser) | ||
return null; | ||
const el = (rootElement ?? document).querySelector(`[id="${id}"]`); | ||
return isHTMLElement(el) ? el : null; | ||
} | ||
export const hiddenAction = (obj) => { | ||
@@ -14,0 +23,0 @@ return new Proxy(obj, { |
{ | ||
"name": "@melt-ui/svelte", | ||
"version": "0.85.0", | ||
"version": "0.86.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "repository": "github:melt-ui/melt-ui", |
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
1164428
25748