UNPKG

fluent-svelte-updated

Version:

Forked from https://github.com/vegardlarsen/fluent-svelte. A faithful implementation of Microsoft's Fluent Design System in Svelte.

97 lines (96 loc) 3.84 kB
// Note: bubble and listen are no longer available in Svelte 4+ // These functions need to be replaced with modern alternatives import { tabbable } from "tabbable"; import { createFocusTrap } from "focus-trap"; export { default as ComboBoxItem } from "./ComboBox/ComboBoxItem.svelte"; export { default as FlyoutSurface } from "./Flyout/FlyoutSurface.svelte"; export { default as TooltipSurface } from "./Tooltip/TooltipSurface.svelte"; export { default as MenuFlyoutSurface } from "./MenuFlyout/MenuFlyoutSurface.svelte"; export { default as CalendarViewItem } from "./CalendarView/CalendarViewItem.svelte"; export function externalMouseEvents(node, options = { type: "click", stopPropagation: false }) { const { type, stopPropagation } = options; const handleEvent = (event) => { if (stopPropagation) event.stopPropagation(); if (node && !node.contains(event.target) && !event.defaultPrevented) { node.dispatchEvent(new CustomEvent(`outer${type}`, { detail: event })); } }; document.addEventListener(type, handleEvent, true); return { destroy() { document.removeEventListener(type, handleEvent, true); } }; } // Basic wrapper action around focus-trap export function focusTrap(node, options) { const trap = createFocusTrap(node, (options = { ...options, fallbackFocus: node })); trap.activate(); return { destroy() { trap.deactivate(); } }; } // ID generator for handling WAI-ARIA related attributes export function uid(prefix) { return (prefix + String.fromCharCode(Math.floor(Math.random() * 26) + 97) + Math.random().toString(16).slice(2) + Date.now().toString(16).split(".")[0]); } // Controls the focus of a list of elements by using the arrow keys export function arrowNavigation(node, options = { preventTab: false, stopPropagation: false }) { const handleKeyDown = (event) => { const { key } = event; const { activeElement } = document; let tabOrder = tabbable(node); // if (directChildren) tabOrder = tabOrder.filter(child => child.parentElement === node); const activeIndex = tabOrder.indexOf(document.activeElement); if (tabOrder.length < 0) return; if (key === "ArrowUp" || key === "ArrowDown" || key === "Home" || key === "End" || (key === "Tab" && options.preventTab)) { event.preventDefault(); if (options.stopPropagation) event.stopPropagation(); } if (key === "ArrowUp") { if (tabOrder[0] === activeElement) { tabOrder[tabOrder.length - 1].focus(); } else if (tabOrder.includes(activeElement)) { tabOrder[activeIndex - 1].focus(); } } else if (key === "ArrowDown") { if (tabOrder[tabOrder.length - 1] === activeElement) { tabOrder[0].focus(); } else if (tabOrder.includes(activeElement)) { tabOrder[activeIndex + 1].focus(); } } else if (key === "Home") { tabOrder[0].focus(); } else if (key === "End") { tabOrder[tabOrder.length - 1].focus(); } }; node.addEventListener("keydown", handleKeyDown); return { destroy: () => node.removeEventListener("keydown", handleKeyDown) }; } // Returns a number representing the duration of a specified CSS custom property in ms export function getCSSDuration(property) { const duration = window.getComputedStyle(document.documentElement).getPropertyValue(property); return parseFloat(duration) * (/\ds$/.test(duration) ? 1000 : 1) || 0; }