UNPKG

@agnos-ui/core

Version:

Framework-agnostic headless component library.

133 lines (132 loc) 4.59 kB
import { computed, derived } from "@amadeus-it-group/tansu"; import { arrow, autoUpdate, computePosition } from "@floating-ui/dom"; import { j as createBrowserStoreDirective, k as mergeDirectives, d as directiveSubscribe } from "../dom-gfxqXJpK.js"; import { p as promiseStoreToValueStore } from "../promise-XSP94FjG.js"; import { writablesForProps, stateStores } from "../utils/stores.js"; const defaultConfig = { computePositionOptions: {}, autoUpdateOptions: {}, arrowOptions: {} }; const createFloatingUI = (propsConfig) => { const [{ autoUpdateOptions$, computePositionOptions$: computePositionInputOptions$, arrowOptions$: arrowInputOptions$ }, patch] = writablesForProps( defaultConfig, propsConfig ); const { directive: floatingDirective, element$: floatingElement$ } = createBrowserStoreDirective(); const { directive: referenceDirective, element$: referenceElement$ } = createBrowserStoreDirective(); const { directive: arrowDirective, element$: arrowElement$ } = createBrowserStoreDirective(); const arrowOptions$ = computed(() => { const arrowElement = arrowElement$(); if (!arrowElement) { return null; } const arrowInputOptions = arrowInputOptions$(); return typeof arrowInputOptions === "function" ? (state) => ({ ...arrowInputOptions(state), element: arrowElement }) : { ...arrowInputOptions, element: arrowElement }; }); const computePositionOptions$ = computed(() => { let options = computePositionInputOptions$(); const arrowOptions = arrowOptions$(); if (arrowOptions) { options = { ...options, middleware: [...options.middleware ?? [], arrow(arrowOptions)] }; } return options; }); const promisePosition$ = derived( [floatingElement$, referenceElement$, computePositionOptions$, autoUpdateOptions$], ([floatingElement, referenceElement, computePositionOptions, autoUpdateOptions], set) => { if (floatingElement && referenceElement) { const clean = autoUpdate( referenceElement, floatingElement, () => { set(computePosition(referenceElement, floatingElement, computePositionOptions)); }, autoUpdateOptions ); return () => { set(null); clean(); }; } return void 0; }, null ); const position$ = promiseStoreToValueStore(promisePosition$, null); const placement$ = computed(() => { var _a; return (_a = position$()) == null ? void 0 : _a.placement; }); const middlewareData$ = computed(() => { var _a; return (_a = position$()) == null ? void 0 : _a.middlewareData; }); const x$ = computed(() => { var _a; return (_a = position$()) == null ? void 0 : _a.x; }); const y$ = computed(() => { var _a; return (_a = position$()) == null ? void 0 : _a.y; }); const strategy$ = computed(() => { var _a; return (_a = position$()) == null ? void 0 : _a.strategy; }); const arrowX$ = computed(() => { var _a, _b; return (_b = (_a = middlewareData$()) == null ? void 0 : _a.arrow) == null ? void 0 : _b.x; }); const arrowY$ = computed(() => { var _a, _b; return (_b = (_a = middlewareData$()) == null ? void 0 : _a.arrow) == null ? void 0 : _b.y; }); const floatingStyleApplyAction$ = computed(() => { const floatingElement = floatingElement$(); if (floatingElement) { floatingElement.style.left = `${x$() ?? 0}px`; floatingElement.style.top = `${y$() ?? 0}px`; } }); const arrowStyleApplyAction$ = computed(() => { const arrowElement = arrowElement$(); if (arrowElement) { const arrowX = arrowX$(); const arrowY = arrowY$(); arrowElement.style.left = arrowX != null ? `${arrowX}px` : ""; arrowElement.style.top = arrowY != null ? `${arrowY}px` : ""; } }); return { patch, ...stateStores({ x$, y$, strategy$, placement$, middlewareData$ }), directives: { /** * Directive to be used on the reference element from where the floating element will be positioned */ referenceDirective, /** * Directive to be used on the floating element */ floatingDirective: mergeDirectives(floatingDirective, directiveSubscribe(floatingStyleApplyAction$)), /** * Directive to be used on the arrow element, if any */ arrowDirective: mergeDirectives(arrowDirective, directiveSubscribe(arrowStyleApplyAction$)) }, api: {} }; }; export { createFloatingUI };