@vielzeug/floatit 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/floatit.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e={bottom:`top`,left:`right`,right:`left`,top:`bottom`};function t(e){return e.split(`-`)[0]}function n(e){return e.split(`-`)[1]??null}function r({height:e,width:t,x:n,y:r}){return{height:e,width:t,x:n,y:r}}function i(e,t,n,r){return e===`start`?t:e===`end`?t+n-r:t+(n-r)/2}function a(e,r,a){let o=t(e),s=n(e);return o===`top`?{x:i(s,r.x,r.width,a.width),y:r.y-a.height}:o===`bottom`?{x:i(s,r.x,r.width,a.width),y:r.y+r.height}:o===`left`?{x:r.x-a.width,y:i(s,r.y,r.height,a.height)}:{x:r.x+r.width,y:i(s,r.y,r.height,a.height)}}function o(e,t,n={}){let{middleware:i=[],placement:o=`bottom`}=n,s=i.filter(Boolean),c=o,l=0,u=()=>{let n=r(e.getBoundingClientRect()),i=r(t.getBoundingClientRect()),o={...a(c,n,i),elements:{floating:t,reference:e},placement:c,rects:{floating:i,reference:n}};for(let e of s)o=e.fn(o);return o.placement!==c&&l<1?(c=o.placement,l++,u()):{placement:o.placement,x:o.x,y:o.y}};return Promise.resolve(u())}function s(e){return{fn(n){let r=t(n.placement);return{...n,x:n.x+(r===`right`?e:r===`left`?-e:0),y:n.y+(r===`bottom`?e:r===`top`?-e:0)}},name:`offset`}}function c(r={}){let{padding:i=0}=r;return{fn(r){let{placement:a,rects:{floating:o},x:s,y:c}=r,l=t(a),u=window.innerWidth,d=window.innerHeight;if(!(l===`top`&&c<i||l===`bottom`&&c+o.height>d-i||l===`left`&&s<i||l===`right`&&s+o.width>u-i))return r;let f=n(a),p=e[l],m=f?`${p}-${f}`:p;return{...r,placement:m}},name:`flip`}}function l(e={}){let{padding:t=0}=e;return{fn(e){let{rects:{floating:n},x:r,y:i}=e,a=window.innerWidth,o=window.innerHeight;return{...e,x:Math.min(Math.max(r,t),a-n.width-t),y:Math.min(Math.max(i,t),o-n.height-t)}},name:`shift`}}function u(e={}){let{apply:t,padding:n=0}=e;return{fn(e){return t?.({availableHeight:window.innerHeight-n*2,availableWidth:window.innerWidth-n*2,elements:e.elements}),e},name:`size`}}function d(e,t,n,{observeFloating:r=!0,observeVisualViewport:i=!0}={}){let a=e=>{e.composedPath().includes(t)||n()};window.addEventListener(`scroll`,a,{capture:!0,passive:!0}),window.addEventListener(`resize`,n,{passive:!0});let o=i?window.visualViewport:null;o?.addEventListener(`resize`,n,{passive:!0}),o?.addEventListener(`scroll`,n,{passive:!0});let s=new ResizeObserver(n);return s.observe(e),r&&s.observe(t),()=>{window.removeEventListener(`scroll`,a,{capture:!0}),window.removeEventListener(`resize`,n),o?.removeEventListener(`resize`,n),o?.removeEventListener(`scroll`,n),s.disconnect()}}function f(e,t,n={}){return o(e,t,{strategy:`fixed`,...n}).then(({placement:e,x:n,y:r})=>(t.style.left=`${n}px`,t.style.top=`${r}px`,e))}exports.autoUpdate=d,exports.computePosition=o,exports.flip=c,exports.offset=s,exports.positionFloat=f,exports.shift=l,exports.size=u;
1
+ var e={bottom:`top`,left:`right`,right:`left`,top:`bottom`};function t(e){return e.split(`-`)[0]}function n(e){return e.split(`-`)[1]??null}function r({height:e,width:t,x:n,y:r}){return{height:e,width:t,x:n,y:r}}function i(e,t,n,r){return e===`start`?t:e===`end`?t+n-r:t+(n-r)/2}function a(e,r,a){let o=t(e),s=n(e);return o===`top`?{x:i(s,r.x,r.width,a.width),y:r.y-a.height}:o===`bottom`?{x:i(s,r.x,r.width,a.width),y:r.y+r.height}:o===`left`?{x:r.x-a.width,y:i(s,r.y,r.height,a.height)}:{x:r.x+r.width,y:i(s,r.y,r.height,a.height)}}function o(e,t,n,i){let s=r(n.getBoundingClientRect()),c=r(i.getBoundingClientRect()),l={...a(t,s,c),elements:{floating:i,reference:n},placement:t,rects:{floating:c,reference:s}};for(let t of e)l=t.fn(l);return l.placement===t?{placement:l.placement,x:l.x,y:l.y}:o(e,l.placement,n,i)}function s(e,t,n={}){let{middleware:r=[],placement:i=`bottom`}=n;return o(r.filter(Boolean),i,e,t)}function c(e){return{fn(n){let r=t(n.placement);return{...n,x:n.x+(r===`right`?e:r===`left`?-e:0),y:n.y+(r===`bottom`?e:r===`top`?-e:0)}},name:`offset`}}function l(r={}){let{padding:i=0}=r;return{fn(r){let{placement:a,rects:{floating:o},x:s,y:c}=r,l=t(a),u=window.innerWidth,d=window.innerHeight;if(!(l===`top`&&c<i||l===`bottom`&&c+o.height>d-i||l===`left`&&s<i||l===`right`&&s+o.width>u-i))return r;let f=n(a),p=e[l],m=f?`${p}-${f}`:p;return{...r,placement:m}},name:`flip`}}function u(e={}){let{padding:t=0}=e;return{fn(e){let{rects:{floating:n},x:r,y:i}=e,a=window.innerWidth,o=window.innerHeight;return{...e,x:Math.min(Math.max(r,t),a-n.width-t),y:Math.min(Math.max(i,t),o-n.height-t)}},name:`shift`}}function d(e={}){let{apply:n,padding:r=0}=e;return{fn(e){let{placement:i,rects:{floating:a},x:o,y:s}=e,c=t(i),l=window.innerWidth,u=window.innerHeight,d=c===`bottom`?u-s-r:c===`top`?s+a.height-r:u-r*2,f=c===`right`?l-o-r:c===`left`?o+a.width-r:l-r*2;return n?.({availableHeight:d,availableWidth:f,elements:e.elements}),e},name:`size`}}function f(e,t,n,{observeFloating:r=!0,observeVisualViewport:i=!0}={}){n();let a=e=>{e.composedPath().includes(t)||n()};window.addEventListener(`scroll`,a,{capture:!0,passive:!0}),window.addEventListener(`resize`,n,{passive:!0});let o=i?window.visualViewport:null;o?.addEventListener(`resize`,n,{passive:!0}),o?.addEventListener(`scroll`,n,{passive:!0});let s=new ResizeObserver(n);return s.observe(e),r&&s.observe(t),()=>{window.removeEventListener(`scroll`,a,{capture:!0}),window.removeEventListener(`resize`,n),o?.removeEventListener(`resize`,n),o?.removeEventListener(`scroll`,n),s.disconnect()}}function p(e,t,n={}){let{placement:r,x:i,y:a}=s(e,t,n);return t.style.left=`${i}px`,t.style.top=`${a}px`,r}function m(e,t,n={}){return f(e,t,()=>p(e,t,n))}exports.autoUpdate=f,exports.computePosition=s,exports.flip=l,exports.float=m,exports.offset=c,exports.positionFloat=p,exports.shift=u,exports.size=d;
2
2
  //# sourceMappingURL=floatit.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"floatit.cjs","names":[],"sources":["../src/floatit.ts"],"sourcesContent":["/** @vielzeug/floatit — Lightweight floating element positioning. */\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type Side = 'top' | 'bottom' | 'left' | 'right';\nexport type Alignment = 'start' | 'end';\nexport type Placement = Side | `${Side}-${Alignment}`;\nexport type Strategy = 'fixed' | 'absolute';\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface MiddlewareState {\n x: number;\n y: number;\n placement: Placement;\n rects: { floating: Rect; reference: Rect };\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface Middleware {\n name: string;\n fn: (state: MiddlewareState) => MiddlewareState;\n}\n\nexport interface ComputePositionConfig {\n placement?: Placement;\n strategy?: Strategy;\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\nexport interface ComputePositionResult {\n x: number;\n y: number;\n placement: Placement;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst OPPOSITE: Record<Side, Side> = { bottom: 'top', left: 'right', right: 'left', top: 'bottom' };\n\nfunction getSide(p: Placement): Side {\n return p.split('-')[0] as Side;\n}\n\nfunction getAlign(p: Placement): Alignment | null {\n return (p.split('-')[1] as Alignment) ?? null;\n}\n\nfunction toRect({ height, width, x, y }: DOMRect): Rect {\n return { height, width, x, y };\n}\n\nfunction crossCoord(align: Alignment | null, start: number, span: number, floatSpan: number): number {\n return align === 'start' ? start : align === 'end' ? start + span - floatSpan : start + (span - floatSpan) / 2;\n}\n\n/** Compute the base x/y for a floating element relative to a reference element. */\nfunction baseCoords(placement: Placement, ref: Rect, float: Rect): { x: number; y: number } {\n const side = getSide(placement);\n const align = getAlign(placement);\n\n if (side === 'top') return { x: crossCoord(align, ref.x, ref.width, float.width), y: ref.y - float.height };\n\n if (side === 'bottom') return { x: crossCoord(align, ref.x, ref.width, float.width), y: ref.y + ref.height };\n\n if (side === 'left') return { x: ref.x - float.width, y: crossCoord(align, ref.y, ref.height, float.height) };\n\n /* right */ return { x: ref.x + ref.width, y: crossCoord(align, ref.y, ref.height, float.height) };\n}\n\n// ─── computePosition ──────────────────────────────────────────────────────────\n\n/**\n * Computes the position of a floating element relative to a reference element.\n * Returns a Promise for API compatibility.\n */\nexport function computePosition(\n reference: Element,\n floating: HTMLElement,\n config: ComputePositionConfig = {},\n): Promise<ComputePositionResult> {\n const { middleware = [], placement: initial = 'bottom' } = config;\n const mws = middleware.filter(Boolean) as Middleware[];\n\n let activePlacement = initial;\n let resets = 0;\n\n const run = (): ComputePositionResult => {\n const refRect = toRect(reference.getBoundingClientRect());\n const floatRect = toRect(floating.getBoundingClientRect());\n const base = baseCoords(activePlacement, refRect, floatRect);\n\n let state: MiddlewareState = {\n ...base,\n elements: { floating, reference },\n placement: activePlacement,\n rects: { floating: floatRect, reference: refRect },\n };\n\n for (const mw of mws) state = mw.fn(state);\n\n // If a middleware (e.g. flip) changed the placement, restart once with the new one.\n if (state.placement !== activePlacement && resets < 1) {\n activePlacement = state.placement;\n resets++;\n\n return run();\n }\n\n return { placement: state.placement, x: state.x, y: state.y };\n };\n\n return Promise.resolve(run());\n}\n\n// ─── Middlewares ──────────────────────────────────────────────────────────────\n\n/** Adds a gap (in px) between the reference and the floating element. */\nexport function offset(value: number): Middleware {\n return {\n fn(state) {\n const side = getSide(state.placement);\n\n return {\n ...state,\n x: state.x + (side === 'right' ? value : side === 'left' ? -value : 0),\n y: state.y + (side === 'bottom' ? value : side === 'top' ? -value : 0),\n };\n },\n name: 'offset',\n };\n}\n\nexport interface FlipOptions {\n /** Minimum distance from the viewport edge before flipping (px). */\n padding?: number;\n}\n\n/** Flips the floating element to the opposite side when it would overflow the viewport. */\nexport function flip(options: FlipOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const overflows =\n (side === 'top' && y < padding) ||\n (side === 'bottom' && y + floating.height > vh - padding) ||\n (side === 'left' && x < padding) ||\n (side === 'right' && x + floating.width > vw - padding);\n\n if (!overflows) return state;\n\n const align = getAlign(placement);\n const opp = OPPOSITE[side];\n const flipped = (align ? `${opp}-${align}` : opp) as Placement;\n\n return { ...state, placement: flipped };\n },\n name: 'flip',\n };\n}\n\nexport interface ShiftOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n}\n\n/** Shifts the floating element along its axis to keep it within the viewport. */\nexport function shift(options: ShiftOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n rects: { floating },\n x,\n y,\n } = state;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n return {\n ...state,\n x: Math.min(Math.max(x, padding), vw - floating.width - padding),\n y: Math.min(Math.max(y, padding), vh - floating.height - padding),\n };\n },\n name: 'shift',\n };\n}\n\nexport interface SizeApplyArgs {\n availableWidth: number;\n availableHeight: number;\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface SizeOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n /** Called with available dimensions — use to resize the floating element. */\n apply?: (args: SizeApplyArgs) => void;\n}\n\n/** Provides available width/height and optionally resizes the floating element. */\nexport function size(options: SizeOptions = {}): Middleware {\n const { apply, padding = 0 } = options;\n\n return {\n fn(state) {\n apply?.({\n availableHeight: window.innerHeight - padding * 2,\n availableWidth: window.innerWidth - padding * 2,\n elements: state.elements,\n });\n\n return state;\n },\n name: 'size',\n };\n}\n\n// ─── autoUpdate ───────────────────────────────────────────────────────────────\n\nexport interface AutoUpdateOptions {\n /**\n * Whether to observe size changes on the floating element itself.\n * Set to `false` for virtual-scroll dropdowns whose outer dimensions are\n * managed entirely by the caller (e.g. width set via `size()` middleware),\n * to avoid a ResizeObserver feedback loop.\n * Defaults to `true`.\n */\n observeFloating?: boolean;\n /**\n * Whether to observe `window.visualViewport` resize/scroll changes.\n * Helps keep floating UI aligned during pinch-zoom and virtual keyboard changes.\n * Defaults to `true`.\n */\n observeVisualViewport?: boolean;\n}\n\n/**\n * Automatically calls `update` whenever the floating element's position may have\n * changed (viewport resize, scroll events, or reference / floating element resize).\n * Returns a cleanup function.\n */\nexport function autoUpdate(\n reference: Element,\n floating: HTMLElement,\n update: () => void,\n { observeFloating = true, observeVisualViewport = true }: AutoUpdateOptions = {},\n): () => void {\n // Scroll events inside the floating element itself (e.g. a dropdown scrolling\n // its own options list) must never trigger repositioning.\n // Use composedPath() instead of e.target — shadow DOM retargets e.target to\n // the shadow host at the window listener boundary, so contains(e.target) would\n // miss scrolls that originated inside a shadow root.\n const scrollHandler = (e: Event) => {\n if (e.composedPath().includes(floating)) return;\n\n update();\n };\n\n window.addEventListener('scroll', scrollHandler, { capture: true, passive: true });\n window.addEventListener('resize', update, { passive: true });\n\n const vv = observeVisualViewport ? window.visualViewport : null;\n\n vv?.addEventListener('resize', update, { passive: true });\n vv?.addEventListener('scroll', update, { passive: true });\n\n const ro = new ResizeObserver(update);\n\n ro.observe(reference);\n\n if (observeFloating) ro.observe(floating);\n\n return () => {\n window.removeEventListener('scroll', scrollHandler, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', update);\n vv?.removeEventListener('resize', update);\n vv?.removeEventListener('scroll', update);\n ro.disconnect();\n };\n}\n\n// ─── positionFloat ────────────────────────────────────────────────────────────\n\nexport interface FloatOptions {\n /** Preferred placement relative to the reference element. */\n placement?: Placement;\n /** Positioning strategy. Defaults to `'fixed'`. */\n strategy?: Strategy;\n /** Middleware to modify positioning behavior. */\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\n/**\n * Computes and applies the floating position to a floating element.\n * Sets `left`/`top` inline styles and returns the resolved placement.\n *\n * @example\n * ```ts\n * positionFloat(reference, floating, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * }).then(placement => el.dataset.placement = placement);\n * ```\n */\nexport function positionFloat(\n reference: Element,\n floating: HTMLElement,\n options: FloatOptions = {},\n): Promise<Placement> {\n return computePosition(reference, floating, {\n strategy: 'fixed',\n ...options,\n }).then(({ placement, x, y }) => {\n floating.style.left = `${x}px`;\n floating.style.top = `${y}px`;\n\n return placement;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"floatit.cjs","names":[],"sources":["../src/floatit.ts"],"sourcesContent":["/** @vielzeug/floatit — Lightweight floating element positioning. */\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type Side = 'top' | 'bottom' | 'left' | 'right';\nexport type Alignment = 'start' | 'end';\nexport type Placement = Side | `${Side}-${Alignment}`;\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface MiddlewareState {\n x: number;\n y: number;\n placement: Placement;\n rects: { floating: Rect; reference: Rect };\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface Middleware {\n name: string;\n fn: (state: MiddlewareState) => MiddlewareState;\n}\n\nexport interface ComputePositionConfig {\n placement?: Placement;\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\nexport interface ComputePositionResult {\n x: number;\n y: number;\n placement: Placement;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst OPPOSITE: Record<Side, Side> = { bottom: 'top', left: 'right', right: 'left', top: 'bottom' };\n\nfunction getSide(p: Placement): Side {\n return p.split('-')[0] as Side;\n}\n\nfunction getAlign(p: Placement): Alignment | null {\n return (p.split('-')[1] as Alignment) ?? null;\n}\n\nfunction toRect({ height, width, x, y }: DOMRect): Rect {\n return { height, width, x, y };\n}\n\nfunction alignedOffset(align: Alignment | null, refStart: number, refSize: number, floatSize: number): number {\n if (align === 'start') return refStart;\n\n if (align === 'end') return refStart + refSize - floatSize;\n\n return refStart + (refSize - floatSize) / 2;\n}\n\nfunction baseCoords(placement: Placement, ref: Rect, float: Rect): { x: number; y: number } {\n const side = getSide(placement);\n const align = getAlign(placement);\n\n if (side === 'top') return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y - float.height };\n\n if (side === 'bottom') return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y + ref.height };\n\n if (side === 'left') return { x: ref.x - float.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n\n /* right */ return { x: ref.x + ref.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n}\n\n// ─── Pipeline ─────────────────────────────────────────────────────────────────\n\nfunction runPipeline(\n mws: Middleware[],\n placement: Placement,\n reference: Element,\n floating: HTMLElement,\n): ComputePositionResult {\n const refRect = toRect(reference.getBoundingClientRect());\n const floatRect = toRect(floating.getBoundingClientRect());\n let state: MiddlewareState = {\n ...baseCoords(placement, refRect, floatRect),\n elements: { floating, reference },\n placement,\n rects: { floating: floatRect, reference: refRect },\n };\n\n for (const mw of mws) state = mw.fn(state);\n\n // If a middleware (e.g. flip) changed the placement, restart once with the new one.\n if (state.placement !== placement) {\n return runPipeline(mws, state.placement, reference, floating);\n }\n\n return { placement: state.placement, x: state.x, y: state.y };\n}\n\n// ─── computePosition ──────────────────────────────────────────────────────────\n\n/** Computes the position of a floating element relative to a reference element. */\nexport function computePosition(\n reference: Element,\n floating: HTMLElement,\n config: ComputePositionConfig = {},\n): ComputePositionResult {\n const { middleware = [], placement = 'bottom' } = config;\n\n return runPipeline(middleware.filter(Boolean) as Middleware[], placement, reference, floating);\n}\n\n// ─── Middlewares ──────────────────────────────────────────────────────────────\n\n/** Adds a gap (in px) between the reference and the floating element. */\nexport function offset(value: number): Middleware {\n return {\n fn(state) {\n const side = getSide(state.placement);\n\n return {\n ...state,\n x: state.x + (side === 'right' ? value : side === 'left' ? -value : 0),\n y: state.y + (side === 'bottom' ? value : side === 'top' ? -value : 0),\n };\n },\n name: 'offset',\n };\n}\n\nexport interface FlipOptions {\n /** Minimum distance from the viewport edge before flipping (px). */\n padding?: number;\n}\n\n/** Flips the floating element to the opposite side when it would overflow the viewport. */\nexport function flip(options: FlipOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const overflows =\n (side === 'top' && y < padding) ||\n (side === 'bottom' && y + floating.height > vh - padding) ||\n (side === 'left' && x < padding) ||\n (side === 'right' && x + floating.width > vw - padding);\n\n if (!overflows) return state;\n\n const align = getAlign(placement);\n const opp = OPPOSITE[side];\n const flipped = (align ? `${opp}-${align}` : opp) as Placement;\n\n return { ...state, placement: flipped };\n },\n name: 'flip',\n };\n}\n\nexport interface ShiftOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n}\n\n/** Shifts the floating element along its axis to keep it within the viewport. */\nexport function shift(options: ShiftOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n rects: { floating },\n x,\n y,\n } = state;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n return {\n ...state,\n x: Math.min(Math.max(x, padding), vw - floating.width - padding),\n y: Math.min(Math.max(y, padding), vh - floating.height - padding),\n };\n },\n name: 'shift',\n };\n}\n\nexport interface SizeApplyArgs {\n availableWidth: number;\n availableHeight: number;\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface SizeOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n /** Called with available dimensions — use to resize the floating element. */\n apply?: (args: SizeApplyArgs) => void;\n}\n\n/** Provides available width/height based on actual float position and optionally resizes the floating element. */\nexport function size(options: SizeOptions = {}): Middleware {\n const { apply, padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n const availableHeight =\n side === 'bottom' ? vh - y - padding : side === 'top' ? y + floating.height - padding : vh - padding * 2;\n\n const availableWidth =\n side === 'right' ? vw - x - padding : side === 'left' ? x + floating.width - padding : vw - padding * 2;\n\n apply?.({ availableHeight, availableWidth, elements: state.elements });\n\n return state;\n },\n name: 'size',\n };\n}\n\n// ─── autoUpdate ───────────────────────────────────────────────────────────────\n\nexport interface AutoUpdateOptions {\n /**\n * Whether to observe size changes on the floating element itself.\n * Set to `false` for virtual-scroll dropdowns whose outer dimensions are\n * managed entirely by the caller (e.g. width set via `size()` middleware),\n * to avoid a ResizeObserver feedback loop.\n * Defaults to `true`.\n */\n observeFloating?: boolean;\n /**\n * Whether to observe `window.visualViewport` resize/scroll changes.\n * Helps keep floating UI aligned during pinch-zoom and virtual keyboard changes.\n * Defaults to `true`.\n */\n observeVisualViewport?: boolean;\n}\n\n/**\n * Automatically calls `update` whenever the floating element's position may have\n * changed (viewport resize, scroll events, or reference / floating element resize).\n * Calls `update` once immediately on registration.\n * Returns a cleanup function.\n */\nexport function autoUpdate(\n reference: Element,\n floating: HTMLElement,\n update: () => void,\n { observeFloating = true, observeVisualViewport = true }: AutoUpdateOptions = {},\n): () => void {\n update();\n\n // Use composedPath() instead of e.target — shadow DOM retargets e.target to\n // the shadow host at the window listener boundary.\n const scrollHandler = (e: Event) => {\n if (e.composedPath().includes(floating)) return;\n\n update();\n };\n\n window.addEventListener('scroll', scrollHandler, { capture: true, passive: true });\n window.addEventListener('resize', update, { passive: true });\n\n const vv = observeVisualViewport ? window.visualViewport : null;\n\n vv?.addEventListener('resize', update, { passive: true });\n vv?.addEventListener('scroll', update, { passive: true });\n\n const ro = new ResizeObserver(update);\n\n ro.observe(reference);\n\n if (observeFloating) ro.observe(floating);\n\n return () => {\n window.removeEventListener('scroll', scrollHandler, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', update);\n vv?.removeEventListener('resize', update);\n vv?.removeEventListener('scroll', update);\n ro.disconnect();\n };\n}\n\n// ─── positionFloat / float ────────────────────────────────────────────────────\n\nexport interface FloatOptions {\n /** Preferred placement relative to the reference element. */\n placement?: Placement;\n /** Middleware to modify positioning behavior. */\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\n/**\n * Computes and applies the floating position to a floating element.\n * Sets `left`/`top` inline styles and returns the resolved placement.\n */\nexport function positionFloat(reference: Element, floating: HTMLElement, options: FloatOptions = {}): Placement {\n const { placement, x, y } = computePosition(reference, floating, options);\n\n floating.style.left = `${x}px`;\n floating.style.top = `${y}px`;\n\n return placement;\n}\n\n/**\n * Positions a floating element relative to a reference element and keeps it in\n * sync as the viewport or elements change. Returns a cleanup function.\n *\n * @example\n * ```ts\n * const cleanup = float(trigger, tooltip, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * });\n *\n * // When done:\n * cleanup();\n * ```\n */\nexport function float(reference: Element, floating: HTMLElement, options: FloatOptions = {}): () => void {\n return autoUpdate(reference, floating, () => positionFloat(reference, floating, options));\n}\n"],"mappings":"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"}
package/dist/floatit.d.ts CHANGED
@@ -2,7 +2,6 @@
2
2
  export type Side = 'top' | 'bottom' | 'left' | 'right';
3
3
  export type Alignment = 'start' | 'end';
4
4
  export type Placement = Side | `${Side}-${Alignment}`;
5
- export type Strategy = 'fixed' | 'absolute';
6
5
  interface Rect {
7
6
  x: number;
8
7
  y: number;
@@ -28,7 +27,6 @@ export interface Middleware {
28
27
  }
29
28
  export interface ComputePositionConfig {
30
29
  placement?: Placement;
31
- strategy?: Strategy;
32
30
  middleware?: Array<Middleware | null | undefined | false>;
33
31
  }
34
32
  export interface ComputePositionResult {
@@ -36,11 +34,8 @@ export interface ComputePositionResult {
36
34
  y: number;
37
35
  placement: Placement;
38
36
  }
39
- /**
40
- * Computes the position of a floating element relative to a reference element.
41
- * Returns a Promise for API compatibility.
42
- */
43
- export declare function computePosition(reference: Element, floating: HTMLElement, config?: ComputePositionConfig): Promise<ComputePositionResult>;
37
+ /** Computes the position of a floating element relative to a reference element. */
38
+ export declare function computePosition(reference: Element, floating: HTMLElement, config?: ComputePositionConfig): ComputePositionResult;
44
39
  /** Adds a gap (in px) between the reference and the floating element. */
45
40
  export declare function offset(value: number): Middleware;
46
41
  export interface FlipOptions {
@@ -69,7 +64,7 @@ export interface SizeOptions {
69
64
  /** Called with available dimensions — use to resize the floating element. */
70
65
  apply?: (args: SizeApplyArgs) => void;
71
66
  }
72
- /** Provides available width/height and optionally resizes the floating element. */
67
+ /** Provides available width/height based on actual float position and optionally resizes the floating element. */
73
68
  export declare function size(options?: SizeOptions): Middleware;
74
69
  export interface AutoUpdateOptions {
75
70
  /**
@@ -90,29 +85,36 @@ export interface AutoUpdateOptions {
90
85
  /**
91
86
  * Automatically calls `update` whenever the floating element's position may have
92
87
  * changed (viewport resize, scroll events, or reference / floating element resize).
88
+ * Calls `update` once immediately on registration.
93
89
  * Returns a cleanup function.
94
90
  */
95
91
  export declare function autoUpdate(reference: Element, floating: HTMLElement, update: () => void, { observeFloating, observeVisualViewport }?: AutoUpdateOptions): () => void;
96
92
  export interface FloatOptions {
97
93
  /** Preferred placement relative to the reference element. */
98
94
  placement?: Placement;
99
- /** Positioning strategy. Defaults to `'fixed'`. */
100
- strategy?: Strategy;
101
95
  /** Middleware to modify positioning behavior. */
102
96
  middleware?: Array<Middleware | null | undefined | false>;
103
97
  }
104
98
  /**
105
99
  * Computes and applies the floating position to a floating element.
106
100
  * Sets `left`/`top` inline styles and returns the resolved placement.
101
+ */
102
+ export declare function positionFloat(reference: Element, floating: HTMLElement, options?: FloatOptions): Placement;
103
+ /**
104
+ * Positions a floating element relative to a reference element and keeps it in
105
+ * sync as the viewport or elements change. Returns a cleanup function.
107
106
  *
108
107
  * @example
109
108
  * ```ts
110
- * positionFloat(reference, floating, {
109
+ * const cleanup = float(trigger, tooltip, {
111
110
  * placement: 'top',
112
111
  * middleware: [offset(8), flip(), shift({ padding: 6 })],
113
- * }).then(placement => el.dataset.placement = placement);
112
+ * });
113
+ *
114
+ * // When done:
115
+ * cleanup();
114
116
  * ```
115
117
  */
116
- export declare function positionFloat(reference: Element, floating: HTMLElement, options?: FloatOptions): Promise<Placement>;
118
+ export declare function float(reference: Element, floating: HTMLElement, options?: FloatOptions): () => void;
117
119
  export {};
118
120
  //# sourceMappingURL=floatit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floatit.d.ts","sourceRoot":"","sources":["../src/floatit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"floatit.d.ts","sourceRoot":"","sources":["../src/floatit.ts"],"names":[],"mappings":"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"}
package/dist/floatit.js CHANGED
@@ -1,2 +1,2 @@
1
- var e={bottom:`top`,left:`right`,right:`left`,top:`bottom`};function t(e){return e.split(`-`)[0]}function n(e){return e.split(`-`)[1]??null}function r({height:e,width:t,x:n,y:r}){return{height:e,width:t,x:n,y:r}}function i(e,t,n,r){return e===`start`?t:e===`end`?t+n-r:t+(n-r)/2}function a(e,r,a){let o=t(e),s=n(e);return o===`top`?{x:i(s,r.x,r.width,a.width),y:r.y-a.height}:o===`bottom`?{x:i(s,r.x,r.width,a.width),y:r.y+r.height}:o===`left`?{x:r.x-a.width,y:i(s,r.y,r.height,a.height)}:{x:r.x+r.width,y:i(s,r.y,r.height,a.height)}}function o(e,t,n={}){let{middleware:i=[],placement:o=`bottom`}=n,s=i.filter(Boolean),c=o,l=0,u=()=>{let n=r(e.getBoundingClientRect()),i=r(t.getBoundingClientRect()),o={...a(c,n,i),elements:{floating:t,reference:e},placement:c,rects:{floating:i,reference:n}};for(let e of s)o=e.fn(o);return o.placement!==c&&l<1?(c=o.placement,l++,u()):{placement:o.placement,x:o.x,y:o.y}};return Promise.resolve(u())}function s(e){return{fn(n){let r=t(n.placement);return{...n,x:n.x+(r===`right`?e:r===`left`?-e:0),y:n.y+(r===`bottom`?e:r===`top`?-e:0)}},name:`offset`}}function c(r={}){let{padding:i=0}=r;return{fn(r){let{placement:a,rects:{floating:o},x:s,y:c}=r,l=t(a),u=window.innerWidth,d=window.innerHeight;if(!(l===`top`&&c<i||l===`bottom`&&c+o.height>d-i||l===`left`&&s<i||l===`right`&&s+o.width>u-i))return r;let f=n(a),p=e[l],m=f?`${p}-${f}`:p;return{...r,placement:m}},name:`flip`}}function l(e={}){let{padding:t=0}=e;return{fn(e){let{rects:{floating:n},x:r,y:i}=e,a=window.innerWidth,o=window.innerHeight;return{...e,x:Math.min(Math.max(r,t),a-n.width-t),y:Math.min(Math.max(i,t),o-n.height-t)}},name:`shift`}}function u(e={}){let{apply:t,padding:n=0}=e;return{fn(e){return t?.({availableHeight:window.innerHeight-n*2,availableWidth:window.innerWidth-n*2,elements:e.elements}),e},name:`size`}}function d(e,t,n,{observeFloating:r=!0,observeVisualViewport:i=!0}={}){let a=e=>{e.composedPath().includes(t)||n()};window.addEventListener(`scroll`,a,{capture:!0,passive:!0}),window.addEventListener(`resize`,n,{passive:!0});let o=i?window.visualViewport:null;o?.addEventListener(`resize`,n,{passive:!0}),o?.addEventListener(`scroll`,n,{passive:!0});let s=new ResizeObserver(n);return s.observe(e),r&&s.observe(t),()=>{window.removeEventListener(`scroll`,a,{capture:!0}),window.removeEventListener(`resize`,n),o?.removeEventListener(`resize`,n),o?.removeEventListener(`scroll`,n),s.disconnect()}}function f(e,t,n={}){return o(e,t,{strategy:`fixed`,...n}).then(({placement:e,x:n,y:r})=>(t.style.left=`${n}px`,t.style.top=`${r}px`,e))}export{d as autoUpdate,o as computePosition,c as flip,s as offset,f as positionFloat,l as shift,u as size};
1
+ var e={bottom:`top`,left:`right`,right:`left`,top:`bottom`};function t(e){return e.split(`-`)[0]}function n(e){return e.split(`-`)[1]??null}function r({height:e,width:t,x:n,y:r}){return{height:e,width:t,x:n,y:r}}function i(e,t,n,r){return e===`start`?t:e===`end`?t+n-r:t+(n-r)/2}function a(e,r,a){let o=t(e),s=n(e);return o===`top`?{x:i(s,r.x,r.width,a.width),y:r.y-a.height}:o===`bottom`?{x:i(s,r.x,r.width,a.width),y:r.y+r.height}:o===`left`?{x:r.x-a.width,y:i(s,r.y,r.height,a.height)}:{x:r.x+r.width,y:i(s,r.y,r.height,a.height)}}function o(e,t,n,i){let s=r(n.getBoundingClientRect()),c=r(i.getBoundingClientRect()),l={...a(t,s,c),elements:{floating:i,reference:n},placement:t,rects:{floating:c,reference:s}};for(let t of e)l=t.fn(l);return l.placement===t?{placement:l.placement,x:l.x,y:l.y}:o(e,l.placement,n,i)}function s(e,t,n={}){let{middleware:r=[],placement:i=`bottom`}=n;return o(r.filter(Boolean),i,e,t)}function c(e){return{fn(n){let r=t(n.placement);return{...n,x:n.x+(r===`right`?e:r===`left`?-e:0),y:n.y+(r===`bottom`?e:r===`top`?-e:0)}},name:`offset`}}function l(r={}){let{padding:i=0}=r;return{fn(r){let{placement:a,rects:{floating:o},x:s,y:c}=r,l=t(a),u=window.innerWidth,d=window.innerHeight;if(!(l===`top`&&c<i||l===`bottom`&&c+o.height>d-i||l===`left`&&s<i||l===`right`&&s+o.width>u-i))return r;let f=n(a),p=e[l],m=f?`${p}-${f}`:p;return{...r,placement:m}},name:`flip`}}function u(e={}){let{padding:t=0}=e;return{fn(e){let{rects:{floating:n},x:r,y:i}=e,a=window.innerWidth,o=window.innerHeight;return{...e,x:Math.min(Math.max(r,t),a-n.width-t),y:Math.min(Math.max(i,t),o-n.height-t)}},name:`shift`}}function d(e={}){let{apply:n,padding:r=0}=e;return{fn(e){let{placement:i,rects:{floating:a},x:o,y:s}=e,c=t(i),l=window.innerWidth,u=window.innerHeight,d=c===`bottom`?u-s-r:c===`top`?s+a.height-r:u-r*2,f=c===`right`?l-o-r:c===`left`?o+a.width-r:l-r*2;return n?.({availableHeight:d,availableWidth:f,elements:e.elements}),e},name:`size`}}function f(e,t,n,{observeFloating:r=!0,observeVisualViewport:i=!0}={}){n();let a=e=>{e.composedPath().includes(t)||n()};window.addEventListener(`scroll`,a,{capture:!0,passive:!0}),window.addEventListener(`resize`,n,{passive:!0});let o=i?window.visualViewport:null;o?.addEventListener(`resize`,n,{passive:!0}),o?.addEventListener(`scroll`,n,{passive:!0});let s=new ResizeObserver(n);return s.observe(e),r&&s.observe(t),()=>{window.removeEventListener(`scroll`,a,{capture:!0}),window.removeEventListener(`resize`,n),o?.removeEventListener(`resize`,n),o?.removeEventListener(`scroll`,n),s.disconnect()}}function p(e,t,n={}){let{placement:r,x:i,y:a}=s(e,t,n);return t.style.left=`${i}px`,t.style.top=`${a}px`,r}function m(e,t,n={}){return f(e,t,()=>p(e,t,n))}export{f as autoUpdate,s as computePosition,l as flip,m as float,c as offset,p as positionFloat,u as shift,d as size};
2
2
  //# sourceMappingURL=floatit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"floatit.js","names":[],"sources":["../src/floatit.ts"],"sourcesContent":["/** @vielzeug/floatit — Lightweight floating element positioning. */\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type Side = 'top' | 'bottom' | 'left' | 'right';\nexport type Alignment = 'start' | 'end';\nexport type Placement = Side | `${Side}-${Alignment}`;\nexport type Strategy = 'fixed' | 'absolute';\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface MiddlewareState {\n x: number;\n y: number;\n placement: Placement;\n rects: { floating: Rect; reference: Rect };\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface Middleware {\n name: string;\n fn: (state: MiddlewareState) => MiddlewareState;\n}\n\nexport interface ComputePositionConfig {\n placement?: Placement;\n strategy?: Strategy;\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\nexport interface ComputePositionResult {\n x: number;\n y: number;\n placement: Placement;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst OPPOSITE: Record<Side, Side> = { bottom: 'top', left: 'right', right: 'left', top: 'bottom' };\n\nfunction getSide(p: Placement): Side {\n return p.split('-')[0] as Side;\n}\n\nfunction getAlign(p: Placement): Alignment | null {\n return (p.split('-')[1] as Alignment) ?? null;\n}\n\nfunction toRect({ height, width, x, y }: DOMRect): Rect {\n return { height, width, x, y };\n}\n\nfunction crossCoord(align: Alignment | null, start: number, span: number, floatSpan: number): number {\n return align === 'start' ? start : align === 'end' ? start + span - floatSpan : start + (span - floatSpan) / 2;\n}\n\n/** Compute the base x/y for a floating element relative to a reference element. */\nfunction baseCoords(placement: Placement, ref: Rect, float: Rect): { x: number; y: number } {\n const side = getSide(placement);\n const align = getAlign(placement);\n\n if (side === 'top') return { x: crossCoord(align, ref.x, ref.width, float.width), y: ref.y - float.height };\n\n if (side === 'bottom') return { x: crossCoord(align, ref.x, ref.width, float.width), y: ref.y + ref.height };\n\n if (side === 'left') return { x: ref.x - float.width, y: crossCoord(align, ref.y, ref.height, float.height) };\n\n /* right */ return { x: ref.x + ref.width, y: crossCoord(align, ref.y, ref.height, float.height) };\n}\n\n// ─── computePosition ──────────────────────────────────────────────────────────\n\n/**\n * Computes the position of a floating element relative to a reference element.\n * Returns a Promise for API compatibility.\n */\nexport function computePosition(\n reference: Element,\n floating: HTMLElement,\n config: ComputePositionConfig = {},\n): Promise<ComputePositionResult> {\n const { middleware = [], placement: initial = 'bottom' } = config;\n const mws = middleware.filter(Boolean) as Middleware[];\n\n let activePlacement = initial;\n let resets = 0;\n\n const run = (): ComputePositionResult => {\n const refRect = toRect(reference.getBoundingClientRect());\n const floatRect = toRect(floating.getBoundingClientRect());\n const base = baseCoords(activePlacement, refRect, floatRect);\n\n let state: MiddlewareState = {\n ...base,\n elements: { floating, reference },\n placement: activePlacement,\n rects: { floating: floatRect, reference: refRect },\n };\n\n for (const mw of mws) state = mw.fn(state);\n\n // If a middleware (e.g. flip) changed the placement, restart once with the new one.\n if (state.placement !== activePlacement && resets < 1) {\n activePlacement = state.placement;\n resets++;\n\n return run();\n }\n\n return { placement: state.placement, x: state.x, y: state.y };\n };\n\n return Promise.resolve(run());\n}\n\n// ─── Middlewares ──────────────────────────────────────────────────────────────\n\n/** Adds a gap (in px) between the reference and the floating element. */\nexport function offset(value: number): Middleware {\n return {\n fn(state) {\n const side = getSide(state.placement);\n\n return {\n ...state,\n x: state.x + (side === 'right' ? value : side === 'left' ? -value : 0),\n y: state.y + (side === 'bottom' ? value : side === 'top' ? -value : 0),\n };\n },\n name: 'offset',\n };\n}\n\nexport interface FlipOptions {\n /** Minimum distance from the viewport edge before flipping (px). */\n padding?: number;\n}\n\n/** Flips the floating element to the opposite side when it would overflow the viewport. */\nexport function flip(options: FlipOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const overflows =\n (side === 'top' && y < padding) ||\n (side === 'bottom' && y + floating.height > vh - padding) ||\n (side === 'left' && x < padding) ||\n (side === 'right' && x + floating.width > vw - padding);\n\n if (!overflows) return state;\n\n const align = getAlign(placement);\n const opp = OPPOSITE[side];\n const flipped = (align ? `${opp}-${align}` : opp) as Placement;\n\n return { ...state, placement: flipped };\n },\n name: 'flip',\n };\n}\n\nexport interface ShiftOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n}\n\n/** Shifts the floating element along its axis to keep it within the viewport. */\nexport function shift(options: ShiftOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n rects: { floating },\n x,\n y,\n } = state;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n return {\n ...state,\n x: Math.min(Math.max(x, padding), vw - floating.width - padding),\n y: Math.min(Math.max(y, padding), vh - floating.height - padding),\n };\n },\n name: 'shift',\n };\n}\n\nexport interface SizeApplyArgs {\n availableWidth: number;\n availableHeight: number;\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface SizeOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n /** Called with available dimensions — use to resize the floating element. */\n apply?: (args: SizeApplyArgs) => void;\n}\n\n/** Provides available width/height and optionally resizes the floating element. */\nexport function size(options: SizeOptions = {}): Middleware {\n const { apply, padding = 0 } = options;\n\n return {\n fn(state) {\n apply?.({\n availableHeight: window.innerHeight - padding * 2,\n availableWidth: window.innerWidth - padding * 2,\n elements: state.elements,\n });\n\n return state;\n },\n name: 'size',\n };\n}\n\n// ─── autoUpdate ───────────────────────────────────────────────────────────────\n\nexport interface AutoUpdateOptions {\n /**\n * Whether to observe size changes on the floating element itself.\n * Set to `false` for virtual-scroll dropdowns whose outer dimensions are\n * managed entirely by the caller (e.g. width set via `size()` middleware),\n * to avoid a ResizeObserver feedback loop.\n * Defaults to `true`.\n */\n observeFloating?: boolean;\n /**\n * Whether to observe `window.visualViewport` resize/scroll changes.\n * Helps keep floating UI aligned during pinch-zoom and virtual keyboard changes.\n * Defaults to `true`.\n */\n observeVisualViewport?: boolean;\n}\n\n/**\n * Automatically calls `update` whenever the floating element's position may have\n * changed (viewport resize, scroll events, or reference / floating element resize).\n * Returns a cleanup function.\n */\nexport function autoUpdate(\n reference: Element,\n floating: HTMLElement,\n update: () => void,\n { observeFloating = true, observeVisualViewport = true }: AutoUpdateOptions = {},\n): () => void {\n // Scroll events inside the floating element itself (e.g. a dropdown scrolling\n // its own options list) must never trigger repositioning.\n // Use composedPath() instead of e.target — shadow DOM retargets e.target to\n // the shadow host at the window listener boundary, so contains(e.target) would\n // miss scrolls that originated inside a shadow root.\n const scrollHandler = (e: Event) => {\n if (e.composedPath().includes(floating)) return;\n\n update();\n };\n\n window.addEventListener('scroll', scrollHandler, { capture: true, passive: true });\n window.addEventListener('resize', update, { passive: true });\n\n const vv = observeVisualViewport ? window.visualViewport : null;\n\n vv?.addEventListener('resize', update, { passive: true });\n vv?.addEventListener('scroll', update, { passive: true });\n\n const ro = new ResizeObserver(update);\n\n ro.observe(reference);\n\n if (observeFloating) ro.observe(floating);\n\n return () => {\n window.removeEventListener('scroll', scrollHandler, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', update);\n vv?.removeEventListener('resize', update);\n vv?.removeEventListener('scroll', update);\n ro.disconnect();\n };\n}\n\n// ─── positionFloat ────────────────────────────────────────────────────────────\n\nexport interface FloatOptions {\n /** Preferred placement relative to the reference element. */\n placement?: Placement;\n /** Positioning strategy. Defaults to `'fixed'`. */\n strategy?: Strategy;\n /** Middleware to modify positioning behavior. */\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\n/**\n * Computes and applies the floating position to a floating element.\n * Sets `left`/`top` inline styles and returns the resolved placement.\n *\n * @example\n * ```ts\n * positionFloat(reference, floating, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * }).then(placement => el.dataset.placement = placement);\n * ```\n */\nexport function positionFloat(\n reference: Element,\n floating: HTMLElement,\n options: FloatOptions = {},\n): Promise<Placement> {\n return computePosition(reference, floating, {\n strategy: 'fixed',\n ...options,\n }).then(({ placement, x, y }) => {\n floating.style.left = `${x}px`;\n floating.style.top = `${y}px`;\n\n return placement;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"floatit.js","names":[],"sources":["../src/floatit.ts"],"sourcesContent":["/** @vielzeug/floatit — Lightweight floating element positioning. */\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type Side = 'top' | 'bottom' | 'left' | 'right';\nexport type Alignment = 'start' | 'end';\nexport type Placement = Side | `${Side}-${Alignment}`;\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface MiddlewareState {\n x: number;\n y: number;\n placement: Placement;\n rects: { floating: Rect; reference: Rect };\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface Middleware {\n name: string;\n fn: (state: MiddlewareState) => MiddlewareState;\n}\n\nexport interface ComputePositionConfig {\n placement?: Placement;\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\nexport interface ComputePositionResult {\n x: number;\n y: number;\n placement: Placement;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst OPPOSITE: Record<Side, Side> = { bottom: 'top', left: 'right', right: 'left', top: 'bottom' };\n\nfunction getSide(p: Placement): Side {\n return p.split('-')[0] as Side;\n}\n\nfunction getAlign(p: Placement): Alignment | null {\n return (p.split('-')[1] as Alignment) ?? null;\n}\n\nfunction toRect({ height, width, x, y }: DOMRect): Rect {\n return { height, width, x, y };\n}\n\nfunction alignedOffset(align: Alignment | null, refStart: number, refSize: number, floatSize: number): number {\n if (align === 'start') return refStart;\n\n if (align === 'end') return refStart + refSize - floatSize;\n\n return refStart + (refSize - floatSize) / 2;\n}\n\nfunction baseCoords(placement: Placement, ref: Rect, float: Rect): { x: number; y: number } {\n const side = getSide(placement);\n const align = getAlign(placement);\n\n if (side === 'top') return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y - float.height };\n\n if (side === 'bottom') return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y + ref.height };\n\n if (side === 'left') return { x: ref.x - float.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n\n /* right */ return { x: ref.x + ref.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n}\n\n// ─── Pipeline ─────────────────────────────────────────────────────────────────\n\nfunction runPipeline(\n mws: Middleware[],\n placement: Placement,\n reference: Element,\n floating: HTMLElement,\n): ComputePositionResult {\n const refRect = toRect(reference.getBoundingClientRect());\n const floatRect = toRect(floating.getBoundingClientRect());\n let state: MiddlewareState = {\n ...baseCoords(placement, refRect, floatRect),\n elements: { floating, reference },\n placement,\n rects: { floating: floatRect, reference: refRect },\n };\n\n for (const mw of mws) state = mw.fn(state);\n\n // If a middleware (e.g. flip) changed the placement, restart once with the new one.\n if (state.placement !== placement) {\n return runPipeline(mws, state.placement, reference, floating);\n }\n\n return { placement: state.placement, x: state.x, y: state.y };\n}\n\n// ─── computePosition ──────────────────────────────────────────────────────────\n\n/** Computes the position of a floating element relative to a reference element. */\nexport function computePosition(\n reference: Element,\n floating: HTMLElement,\n config: ComputePositionConfig = {},\n): ComputePositionResult {\n const { middleware = [], placement = 'bottom' } = config;\n\n return runPipeline(middleware.filter(Boolean) as Middleware[], placement, reference, floating);\n}\n\n// ─── Middlewares ──────────────────────────────────────────────────────────────\n\n/** Adds a gap (in px) between the reference and the floating element. */\nexport function offset(value: number): Middleware {\n return {\n fn(state) {\n const side = getSide(state.placement);\n\n return {\n ...state,\n x: state.x + (side === 'right' ? value : side === 'left' ? -value : 0),\n y: state.y + (side === 'bottom' ? value : side === 'top' ? -value : 0),\n };\n },\n name: 'offset',\n };\n}\n\nexport interface FlipOptions {\n /** Minimum distance from the viewport edge before flipping (px). */\n padding?: number;\n}\n\n/** Flips the floating element to the opposite side when it would overflow the viewport. */\nexport function flip(options: FlipOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const overflows =\n (side === 'top' && y < padding) ||\n (side === 'bottom' && y + floating.height > vh - padding) ||\n (side === 'left' && x < padding) ||\n (side === 'right' && x + floating.width > vw - padding);\n\n if (!overflows) return state;\n\n const align = getAlign(placement);\n const opp = OPPOSITE[side];\n const flipped = (align ? `${opp}-${align}` : opp) as Placement;\n\n return { ...state, placement: flipped };\n },\n name: 'flip',\n };\n}\n\nexport interface ShiftOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n}\n\n/** Shifts the floating element along its axis to keep it within the viewport. */\nexport function shift(options: ShiftOptions = {}): Middleware {\n const { padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n rects: { floating },\n x,\n y,\n } = state;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n return {\n ...state,\n x: Math.min(Math.max(x, padding), vw - floating.width - padding),\n y: Math.min(Math.max(y, padding), vh - floating.height - padding),\n };\n },\n name: 'shift',\n };\n}\n\nexport interface SizeApplyArgs {\n availableWidth: number;\n availableHeight: number;\n elements: { floating: HTMLElement; reference: Element };\n}\n\nexport interface SizeOptions {\n /** Minimum distance to maintain from the viewport edges (px). */\n padding?: number;\n /** Called with available dimensions — use to resize the floating element. */\n apply?: (args: SizeApplyArgs) => void;\n}\n\n/** Provides available width/height based on actual float position and optionally resizes the floating element. */\nexport function size(options: SizeOptions = {}): Middleware {\n const { apply, padding = 0 } = options;\n\n return {\n fn(state) {\n const {\n placement,\n rects: { floating },\n x,\n y,\n } = state;\n const side = getSide(placement);\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n const availableHeight =\n side === 'bottom' ? vh - y - padding : side === 'top' ? y + floating.height - padding : vh - padding * 2;\n\n const availableWidth =\n side === 'right' ? vw - x - padding : side === 'left' ? x + floating.width - padding : vw - padding * 2;\n\n apply?.({ availableHeight, availableWidth, elements: state.elements });\n\n return state;\n },\n name: 'size',\n };\n}\n\n// ─── autoUpdate ───────────────────────────────────────────────────────────────\n\nexport interface AutoUpdateOptions {\n /**\n * Whether to observe size changes on the floating element itself.\n * Set to `false` for virtual-scroll dropdowns whose outer dimensions are\n * managed entirely by the caller (e.g. width set via `size()` middleware),\n * to avoid a ResizeObserver feedback loop.\n * Defaults to `true`.\n */\n observeFloating?: boolean;\n /**\n * Whether to observe `window.visualViewport` resize/scroll changes.\n * Helps keep floating UI aligned during pinch-zoom and virtual keyboard changes.\n * Defaults to `true`.\n */\n observeVisualViewport?: boolean;\n}\n\n/**\n * Automatically calls `update` whenever the floating element's position may have\n * changed (viewport resize, scroll events, or reference / floating element resize).\n * Calls `update` once immediately on registration.\n * Returns a cleanup function.\n */\nexport function autoUpdate(\n reference: Element,\n floating: HTMLElement,\n update: () => void,\n { observeFloating = true, observeVisualViewport = true }: AutoUpdateOptions = {},\n): () => void {\n update();\n\n // Use composedPath() instead of e.target — shadow DOM retargets e.target to\n // the shadow host at the window listener boundary.\n const scrollHandler = (e: Event) => {\n if (e.composedPath().includes(floating)) return;\n\n update();\n };\n\n window.addEventListener('scroll', scrollHandler, { capture: true, passive: true });\n window.addEventListener('resize', update, { passive: true });\n\n const vv = observeVisualViewport ? window.visualViewport : null;\n\n vv?.addEventListener('resize', update, { passive: true });\n vv?.addEventListener('scroll', update, { passive: true });\n\n const ro = new ResizeObserver(update);\n\n ro.observe(reference);\n\n if (observeFloating) ro.observe(floating);\n\n return () => {\n window.removeEventListener('scroll', scrollHandler, { capture: true } as EventListenerOptions);\n window.removeEventListener('resize', update);\n vv?.removeEventListener('resize', update);\n vv?.removeEventListener('scroll', update);\n ro.disconnect();\n };\n}\n\n// ─── positionFloat / float ────────────────────────────────────────────────────\n\nexport interface FloatOptions {\n /** Preferred placement relative to the reference element. */\n placement?: Placement;\n /** Middleware to modify positioning behavior. */\n middleware?: Array<Middleware | null | undefined | false>;\n}\n\n/**\n * Computes and applies the floating position to a floating element.\n * Sets `left`/`top` inline styles and returns the resolved placement.\n */\nexport function positionFloat(reference: Element, floating: HTMLElement, options: FloatOptions = {}): Placement {\n const { placement, x, y } = computePosition(reference, floating, options);\n\n floating.style.left = `${x}px`;\n floating.style.top = `${y}px`;\n\n return placement;\n}\n\n/**\n * Positions a floating element relative to a reference element and keeps it in\n * sync as the viewport or elements change. Returns a cleanup function.\n *\n * @example\n * ```ts\n * const cleanup = float(trigger, tooltip, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * });\n *\n * // When done:\n * cleanup();\n * ```\n */\nexport function float(reference: Element, floating: HTMLElement, options: FloatOptions = {}): () => void {\n return autoUpdate(reference, floating, () => positionFloat(reference, floating, options));\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./floatit.cjs`);exports.autoUpdate=e.autoUpdate,exports.computePosition=e.computePosition,exports.flip=e.flip,exports.offset=e.offset,exports.positionFloat=e.positionFloat,exports.shift=e.shift,exports.size=e.size;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./floatit.cjs`);exports.autoUpdate=e.autoUpdate,exports.computePosition=e.computePosition,exports.flip=e.flip,exports.float=e.float,exports.offset=e.offset,exports.positionFloat=e.positionFloat,exports.shift=e.shift,exports.size=e.size;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{autoUpdate as e,computePosition as t,flip as n,offset as r,positionFloat as i,shift as a,size as o}from"./floatit.js";export{e as autoUpdate,t as computePosition,n as flip,r as offset,i as positionFloat,a as shift,o as size};
1
+ import{autoUpdate as e,computePosition as t,flip as n,float as r,offset as i,positionFloat as a,shift as o,size as s}from"./floatit.js";export{e as autoUpdate,t as computePosition,n as flip,r as float,i as offset,a as positionFloat,o as shift,s as size};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/floatit",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -32,7 +32,7 @@
32
32
  "devDependencies": {
33
33
  "@types/node": "^25.5.0",
34
34
  "typescript": "~6.0.2",
35
- "vite": "^8.0.2",
36
- "vitest": "^4.1.1"
35
+ "vite": "^8.0.3",
36
+ "vitest": "^4.1.2"
37
37
  }
38
38
  }