UNPKG

@ark-ui/solid

Version:

A collection of unstyled, accessible UI components for Solid, utilizing state machines for seamless interaction.

1,521 lines (1,516 loc) 56.7 kB
import { createGuards, createMachine } from './PKUUD527.js'; import { usePresenceContext, splitPresenceProps, usePresence, PresenceProvider } from './7S3N5UQH.js'; import { createSplitProps as createSplitProps$1 } from './ZMHI4GDJ.js'; import { ark } from './EPLBB4QN.js'; import { useEnvironmentContext } from './YO2MCGXO.js'; import { useLocaleContext } from './OKZ64GSY.js'; import { createContext } from './TROPIN4C.js'; import { runIfFn } from './DT73WLR4.js'; import { __export } from './ESLJRKWD.js'; import { createComponent } from 'solid-js/web'; import { mergeProps, useMachine, normalizeProps } from '@zag-js/solid'; import { createAnatomy } from '@zag-js/anatomy'; import { raf, isHTMLElement, addDomEvent, trackPointerMove, dataAttr, isLeftClick, getEventTarget, isSelfTarget, getEventStep, getEventKey } from '@zag-js/dom-query'; import { invariant, match, pick, clampValue, ensureProps, createSplitProps, toPx } from '@zag-js/utils'; import { createProps } from '@zag-js/types'; import { createUniqueId, createMemo } from 'solid-js'; // src/components/floating-panel/use-floating-panel-context.ts var [FloatingPanelProvider, useFloatingPanelContext] = createContext({ hookName: "useFloatingPanelContext", providerName: "<FloatingPanelProvider />" }); // src/components/floating-panel/floating-panel-body.tsx var FloatingPanelBody = (props2) => { const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getBodyProps(), props2); return createComponent(ark.div, mergedProps); }; var FloatingPanelCloseTrigger = (props2) => { const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getCloseTriggerProps(), props2); return createComponent(ark.button, mergedProps); }; var FloatingPanelContent = (props2) => { const floatingPanel = useFloatingPanelContext(); const presence = usePresenceContext(); const mergedProps = mergeProps(() => floatingPanel().getContentProps(), () => presence().presenceProps, props2); if (presence().unmounted) { return null; } return createComponent(ark.div, mergedProps); }; // src/components/floating-panel/floating-panel-context.tsx var FloatingPanelContext = (props2) => props2.children(useFloatingPanelContext()); var FloatingPanelDragTrigger = (props2) => { const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getDragTriggerProps(), props2); return createComponent(ark.div, mergedProps); }; var FloatingPanelHeader = (props2) => { const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getHeaderProps(), props2); return createComponent(ark.div, mergedProps); }; var FloatingPanelPositioner = (props2) => { const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getPositionerProps(), props2); const presence = usePresenceContext(); if (presence().unmounted) { return null; } return createComponent(ark.div, mergedProps); }; var FloatingPanelResizeTrigger = (props2) => { const [resizeProps, localProps] = createSplitProps$1()(props2, ["axis"]); const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getResizeTriggerProps(resizeProps), localProps); return createComponent(ark.div, mergedProps); }; var FloatingPanelStageTrigger = (props2) => { const [stage, localProps] = createSplitProps$1()(props2, ["stage"]); const floatingPanel = useFloatingPanelContext(); const mergedProps = mergeProps(() => floatingPanel().getStageTriggerProps(stage), localProps); return createComponent(ark.button, mergedProps); }; // ../../node_modules/@zag-js/rect-utils/dist/index.mjs var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var AffineTransform = class _AffineTransform { constructor([m00, m01, m02, m10, m11, m12] = [0, 0, 0, 0, 0, 0]) { __publicField(this, "m00"); __publicField(this, "m01"); __publicField(this, "m02"); __publicField(this, "m10"); __publicField(this, "m11"); __publicField(this, "m12"); __publicField(this, "rotate", (...args) => { return this.prepend(_AffineTransform.rotate(...args)); }); __publicField(this, "scale", (...args) => { return this.prepend(_AffineTransform.scale(...args)); }); __publicField(this, "translate", (...args) => { return this.prepend(_AffineTransform.translate(...args)); }); this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m10 = m10; this.m11 = m11; this.m12 = m12; } applyTo(point) { const { x, y } = point; const { m00, m01, m02, m10, m11, m12 } = this; return { x: m00 * x + m01 * y + m02, y: m10 * x + m11 * y + m12 }; } prepend(other) { return new _AffineTransform([ this.m00 * other.m00 + this.m01 * other.m10, // m00 this.m00 * other.m01 + this.m01 * other.m11, // m01 this.m00 * other.m02 + this.m01 * other.m12 + this.m02, // m02 this.m10 * other.m00 + this.m11 * other.m10, // m10 this.m10 * other.m01 + this.m11 * other.m11, // m11 this.m10 * other.m02 + this.m11 * other.m12 + this.m12 // m12 ]); } append(other) { return new _AffineTransform([ other.m00 * this.m00 + other.m01 * this.m10, // m00 other.m00 * this.m01 + other.m01 * this.m11, // m01 other.m00 * this.m02 + other.m01 * this.m12 + other.m02, // m02 other.m10 * this.m00 + other.m11 * this.m10, // m10 other.m10 * this.m01 + other.m11 * this.m11, // m11 other.m10 * this.m02 + other.m11 * this.m12 + other.m12 // m12 ]); } get determinant() { return this.m00 * this.m11 - this.m01 * this.m10; } get isInvertible() { const det = this.determinant; return isFinite(det) && isFinite(this.m02) && isFinite(this.m12) && det !== 0; } invert() { const det = this.determinant; return new _AffineTransform([ this.m11 / det, // m00 -this.m01 / det, // m01 (this.m01 * this.m12 - this.m11 * this.m02) / det, // m02 -this.m10 / det, // m10 this.m00 / det, // m11 (this.m10 * this.m02 - this.m00 * this.m12) / det // m12 ]); } get array() { return [this.m00, this.m01, this.m02, this.m10, this.m11, this.m12, 0, 0, 1]; } get float32Array() { return new Float32Array(this.array); } // Static static get identity() { return new _AffineTransform([1, 0, 0, 0, 1, 0]); } static rotate(theta, origin) { const rotation = new _AffineTransform([Math.cos(theta), -Math.sin(theta), 0, Math.sin(theta), Math.cos(theta), 0]); if (origin && (origin.x !== 0 || origin.y !== 0)) { return _AffineTransform.multiply( _AffineTransform.translate(origin.x, origin.y), rotation, _AffineTransform.translate(-origin.x, -origin.y) ); } return rotation; } static scale(sx, sy = sx, origin = { x: 0, y: 0 }) { const scale = new _AffineTransform([sx, 0, 0, 0, sy, 0]); if (origin.x !== 0 || origin.y !== 0) { return _AffineTransform.multiply( _AffineTransform.translate(origin.x, origin.y), scale, _AffineTransform.translate(-origin.x, -origin.y) ); } return scale; } static translate(tx, ty) { return new _AffineTransform([1, 0, tx, 0, 1, ty]); } static multiply(...[first, ...rest]) { if (!first) return _AffineTransform.identity; return rest.reduce((result, item) => result.prepend(item), first); } get a() { return this.m00; } get b() { return this.m10; } get c() { return this.m01; } get d() { return this.m11; } get tx() { return this.m02; } get ty() { return this.m12; } get scaleComponents() { return { x: this.a, y: this.d }; } get translationComponents() { return { x: this.tx, y: this.ty }; } get skewComponents() { return { x: this.c, y: this.b }; } toString() { return `matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.tx}, ${this.ty})`; } }; var clamp = (value, min3, max2) => Math.min(Math.max(value, min3), max2); var clampPoint = (position, size, boundaryRect) => { const x = clamp(position.x, boundaryRect.x, boundaryRect.x + boundaryRect.width - size.width); const y = clamp(position.y, boundaryRect.y, boundaryRect.y + boundaryRect.height - size.height); return { x, y }; }; var defaultMinSize = { width: 0, height: 0 }; var defaultMaxSize = { width: Infinity, height: Infinity }; var clampSize = (size, minSize = defaultMinSize, maxSize = defaultMaxSize) => { return { width: Math.min(Math.max(size.width, minSize.width), maxSize.width), height: Math.min(Math.max(size.height, minSize.height), maxSize.height) }; }; var createPoint = (x, y) => ({ x, y }); var subtractPoints = (a, b) => { if (!b) return a; return createPoint(a.x - b.x, a.y - b.y); }; var addPoints = (a, b) => createPoint(a.x + b.x, a.y + b.y); function createRect(r) { const { x, y, width, height } = r; const midX = x + width / 2; const midY = y + height / 2; return { x, y, width, height, minX: x, minY: y, maxX: x + width, maxY: y + height, midX, midY, center: createPoint(midX, midY) }; } var constrainRect = (rect, boundary) => { const left = Math.max(boundary.x, Math.min(rect.x, boundary.x + boundary.width - rect.width)); const top = Math.max(boundary.y, Math.min(rect.y, boundary.y + boundary.height - rect.height)); return { x: left, y: top, width: Math.min(rect.width, boundary.width), height: Math.min(rect.height, boundary.height) }; }; var isSizeEqual = (a, b) => { return a.width === b?.width && a.height === b?.height; }; var isPointEqual = (a, b) => { return a.x === b?.x && a.y === b?.y; }; var styleCache = /* @__PURE__ */ new WeakMap(); function getCacheComputedStyle(el) { if (!styleCache.has(el)) { const win = el.ownerDocument.defaultView || window; styleCache.set(el, win.getComputedStyle(el)); } return styleCache.get(el); } function getElementRect(el, opts = {}) { return createRect(getClientRect(el, opts)); } function getClientRect(el, opts = {}) { const { excludeScrollbar = false, excludeBorders = false } = opts; const { x, y, width, height } = el.getBoundingClientRect(); const r = { x, y, width, height }; const style = getCacheComputedStyle(el); const { borderLeftWidth, borderTopWidth, borderRightWidth, borderBottomWidth } = style; const borderXWidth = sum(borderLeftWidth, borderRightWidth); const borderYWidth = sum(borderTopWidth, borderBottomWidth); if (excludeBorders) { r.width -= borderXWidth; r.height -= borderYWidth; r.x += px(borderLeftWidth); r.y += px(borderTopWidth); } if (excludeScrollbar) { const scrollbarWidth = el.offsetWidth - el.clientWidth - borderXWidth; const scrollbarHeight = el.offsetHeight - el.clientHeight - borderYWidth; r.width -= scrollbarWidth; r.height -= scrollbarHeight; } return r; } var px = (v) => parseFloat(v.replace("px", "")); var sum = (...vals) => vals.reduce((sum2, v) => sum2 + (v ? px(v) : 0), 0); function getWindowRect(win, opts = {}) { return createRect(getViewportRect(win, opts)); } function getViewportRect(win, opts) { const { excludeScrollbar = false } = opts; const { innerWidth, innerHeight, document: doc, visualViewport } = win; const width = visualViewport?.width || innerWidth; const height = visualViewport?.height || innerHeight; const rect = { x: 0, y: 0, width, height }; if (excludeScrollbar) { const scrollbarWidth = innerWidth - doc.documentElement.clientWidth; const scrollbarHeight = innerHeight - doc.documentElement.clientHeight; rect.width -= scrollbarWidth; rect.height -= scrollbarHeight; } return rect; } var compassDirectionMap = { n: { x: 0.5, y: 0 }, ne: { x: 1, y: 0 }, e: { x: 1, y: 0.5 }, se: { x: 1, y: 1 }, s: { x: 0.5, y: 1 }, sw: { x: 0, y: 1 }, w: { x: 0, y: 0.5 }, nw: { x: 0, y: 0 } }; var oppositeDirectionMap = { n: "s", ne: "sw", e: "w", se: "nw", s: "n", sw: "ne", w: "e", nw: "se" }; var { sign, abs, min: min2 } = Math; function getRectExtentPoint(rect, direction) { const { minX, minY, maxX, maxY, midX, midY } = rect; const x = direction.includes("w") ? minX : direction.includes("e") ? maxX : midX; const y = direction.includes("n") ? minY : direction.includes("s") ? maxY : midY; return { x, y }; } function getOppositeDirection(direction) { return oppositeDirectionMap[direction]; } function resizeRect(rect, offset, direction, opts) { const { scalingOriginMode, lockAspectRatio } = opts; const extent = getRectExtentPoint(rect, direction); const oppositeDirection = getOppositeDirection(direction); const oppositeExtent = getRectExtentPoint(rect, oppositeDirection); if (scalingOriginMode === "center") { offset = { x: offset.x * 2, y: offset.y * 2 }; } const newExtent = { x: extent.x + offset.x, y: extent.y + offset.y }; const multiplier = { x: compassDirectionMap[direction].x * 2 - 1, y: compassDirectionMap[direction].y * 2 - 1 }; const newSize = { width: newExtent.x - oppositeExtent.x, height: newExtent.y - oppositeExtent.y }; const scaleX = multiplier.x * newSize.width / rect.width; const scaleY = multiplier.y * newSize.height / rect.height; const largestMagnitude = abs(scaleX) > abs(scaleY) ? scaleX : scaleY; const scale = lockAspectRatio ? { x: largestMagnitude, y: largestMagnitude } : { x: extent.x === oppositeExtent.x ? 1 : scaleX, y: extent.y === oppositeExtent.y ? 1 : scaleY }; if (extent.y === oppositeExtent.y) { scale.y = abs(scale.y); } else if (sign(scale.y) !== sign(scaleY)) { scale.y *= -1; } if (extent.x === oppositeExtent.x) { scale.x = abs(scale.x); } else if (sign(scale.x) !== sign(scaleX)) { scale.x *= -1; } switch (scalingOriginMode) { case "extent": return transformRect(rect, AffineTransform.scale(scale.x, scale.y, oppositeExtent), false); case "center": return transformRect( rect, AffineTransform.scale(scale.x, scale.y, { x: rect.midX, y: rect.midY }), false ); } } function createRectFromPoints(initialPoint, finalPoint, normalized = true) { if (normalized) { return { x: min2(finalPoint.x, initialPoint.x), y: min2(finalPoint.y, initialPoint.y), width: abs(finalPoint.x - initialPoint.x), height: abs(finalPoint.y - initialPoint.y) }; } return { x: initialPoint.x, y: initialPoint.y, width: finalPoint.x - initialPoint.x, height: finalPoint.y - initialPoint.y }; } function transformRect(rect, transform, normalized = true) { const p1 = transform.applyTo({ x: rect.minX, y: rect.minY }); const p2 = transform.applyTo({ x: rect.maxX, y: rect.maxY }); return createRectFromPoints(p1, p2, normalized); } var GET_ORIGINAL_SYMBOL = Symbol(); var getProto = Object.getPrototypeOf; var objectsToTrack = /* @__PURE__ */ new WeakMap(); var isObjectToTrack = (obj) => obj && (objectsToTrack.has(obj) ? objectsToTrack.get(obj) : getProto(obj) === Object.prototype || getProto(obj) === Array.prototype); var getUntracked = (obj) => { if (isObjectToTrack(obj)) { return obj[GET_ORIGINAL_SYMBOL] || null; } return null; }; var markToTrack = (obj, mark = true) => { objectsToTrack.set(obj, mark); }; // ../../node_modules/@zag-js/store/dist/index.mjs function glob() { if (typeof globalThis !== "undefined") return globalThis; if (typeof self !== "undefined") return self; if (typeof window !== "undefined") return window; if (typeof global !== "undefined") return global; } function globalRef(key, value) { const g = glob(); if (!g) return value(); g[key] || (g[key] = value()); return g[key]; } var refSet = globalRef("__zag__refSet", () => /* @__PURE__ */ new WeakSet()); var isReactElement = (x) => typeof x === "object" && x !== null && "$$typeof" in x && "props" in x; var isVueElement = (x) => typeof x === "object" && x !== null && "__v_isVNode" in x; var isDOMElement = (x) => typeof x === "object" && x !== null && "nodeType" in x && typeof x.nodeName === "string"; var isElement = (x) => isReactElement(x) || isVueElement(x) || isDOMElement(x); var isObject = (x) => x !== null && typeof x === "object"; var canProxy = (x) => isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !isElement(x) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise); var proxyStateMap = globalRef("__zag__proxyStateMap", () => /* @__PURE__ */ new WeakMap()); var buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) => new Proxy(target, handler), snapCache = /* @__PURE__ */ new WeakMap(), createSnapshot = (target, version) => { const cache = snapCache.get(target); if (cache?.[0] === version) { return cache[1]; } const snap = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target)); markToTrack(snap, true); snapCache.set(target, [version, snap]); Reflect.ownKeys(target).forEach((key) => { const value = Reflect.get(target, key); if (refSet.has(value)) { markToTrack(value, false); snap[key] = value; } else if (proxyStateMap.has(value)) { snap[key] = snapshot(value); } else { snap[key] = value; } }); return Object.freeze(snap); }, proxyCache = /* @__PURE__ */ new WeakMap(), versionHolder = [1, 1], proxyFunction2 = (initialObject) => { if (!isObject(initialObject)) { throw new Error("object required"); } const found = proxyCache.get(initialObject); if (found) { return found; } let version = versionHolder[0]; const listeners = /* @__PURE__ */ new Set(); const notifyUpdate = (op, nextVersion = ++versionHolder[0]) => { if (version !== nextVersion) { version = nextVersion; listeners.forEach((listener) => listener(op, nextVersion)); } }; let checkVersion = versionHolder[1]; const ensureVersion = (nextCheckVersion = ++versionHolder[1]) => { if (checkVersion !== nextCheckVersion && !listeners.size) { checkVersion = nextCheckVersion; propProxyStates.forEach(([propProxyState]) => { const propVersion = propProxyState[1](nextCheckVersion); if (propVersion > version) { version = propVersion; } }); } return version; }; const createPropListener = (prop) => (op, nextVersion) => { const newOp = [...op]; newOp[1] = [prop, ...newOp[1]]; notifyUpdate(newOp, nextVersion); }; const propProxyStates = /* @__PURE__ */ new Map(); const addPropListener = (prop, propProxyState) => { if (propProxyStates.has(prop)) { throw new Error("prop listener already exists"); } if (listeners.size) { const remove = propProxyState[3](createPropListener(prop)); propProxyStates.set(prop, [propProxyState, remove]); } else { propProxyStates.set(prop, [propProxyState]); } }; const removePropListener = (prop) => { const entry = propProxyStates.get(prop); if (entry) { propProxyStates.delete(prop); entry[1]?.(); } }; const addListener = (listener) => { listeners.add(listener); if (listeners.size === 1) { propProxyStates.forEach(([propProxyState, prevRemove], prop) => { if (prevRemove) { throw new Error("remove already exists"); } const remove = propProxyState[3](createPropListener(prop)); propProxyStates.set(prop, [propProxyState, remove]); }); } const removeListener = () => { listeners.delete(listener); if (listeners.size === 0) { propProxyStates.forEach(([propProxyState, remove], prop) => { if (remove) { remove(); propProxyStates.set(prop, [propProxyState]); } }); } }; return removeListener; }; const baseObject = Array.isArray(initialObject) ? [] : Object.create(Object.getPrototypeOf(initialObject)); const handler = { deleteProperty(target, prop) { const prevValue = Reflect.get(target, prop); removePropListener(prop); const deleted = Reflect.deleteProperty(target, prop); if (deleted) { notifyUpdate(["delete", [prop], prevValue]); } return deleted; }, set(target, prop, value, receiver) { const hasPrevValue = Reflect.has(target, prop); const prevValue = Reflect.get(target, prop, receiver); if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) { return true; } removePropListener(prop); if (isObject(value)) { value = getUntracked(value) || value; } let nextValue = value; if (Object.getOwnPropertyDescriptor(target, prop)?.set) ; else { if (!proxyStateMap.has(value) && canProxy(value)) { nextValue = proxy(value); } const childProxyState = !refSet.has(nextValue) && proxyStateMap.get(nextValue); if (childProxyState) { addPropListener(prop, childProxyState); } } Reflect.set(target, prop, nextValue, receiver); notifyUpdate(["set", [prop], value, prevValue]); return true; } }; const proxyObject = newProxy(baseObject, handler); proxyCache.set(initialObject, proxyObject); const proxyState = [baseObject, ensureVersion, createSnapshot, addListener]; proxyStateMap.set(proxyObject, proxyState); Reflect.ownKeys(initialObject).forEach((key) => { const desc = Object.getOwnPropertyDescriptor(initialObject, key); if (desc.get || desc.set) { Object.defineProperty(baseObject, key, desc); } else { proxyObject[key] = initialObject[key]; } }); return proxyObject; }) => [ // public functions proxyFunction2, // shared state proxyStateMap, refSet, // internal things objectIs, newProxy, canProxy, snapCache, createSnapshot, proxyCache, versionHolder ]; var [proxyFunction] = buildProxyFunction(); function proxy(initialObject = {}) { return proxyFunction(initialObject); } function subscribe(proxyObject, callback, notifyInSync) { const proxyState = proxyStateMap.get(proxyObject); let promise; const ops = []; const addListener = proxyState[3]; let isListenerActive = false; const listener = (op) => { ops.push(op); if (!promise) { promise = Promise.resolve().then(() => { promise = void 0; if (isListenerActive) { callback(ops.splice(0)); } }); } }; const removeListener = addListener(listener); isListenerActive = true; return () => { isListenerActive = false; removeListener(); }; } function snapshot(proxyObject) { const proxyState = proxyStateMap.get(proxyObject); const [target, ensureVersion, createSnapshot] = proxyState; return createSnapshot(target, ensureVersion()); } var anatomy = createAnatomy("floating-panel").parts( "trigger", "positioner", "content", "header", "body", "title", "resizeTrigger", "dragTrigger", "stageTrigger", "closeTrigger", "control" ); var parts = anatomy.build(); var getTriggerId = (ctx) => ctx.ids?.trigger ?? `float:${ctx.id}:trigger`; var getPositionerId = (ctx) => ctx.ids?.positioner ?? `float:${ctx.id}:positioner`; var getContentId = (ctx) => ctx.ids?.content ?? `float:${ctx.id}:content`; var getTitleId = (ctx) => ctx.ids?.title ?? `float:${ctx.id}:title`; var getHeaderId = (ctx) => ctx.ids?.header ?? `float:${ctx.id}:header`; var getTriggerEl = (ctx) => ctx.getById(getTriggerId(ctx)); var getPositionerEl = (ctx) => ctx.getById(getPositionerId(ctx)); var getContentEl = (ctx) => ctx.getById(getContentId(ctx)); var getHeaderEl = (ctx) => ctx.getById(getHeaderId(ctx)); var getBoundaryRect = (ctx, boundaryEl, allowOverflow) => { let boundaryRect; if (isHTMLElement(boundaryEl)) { boundaryRect = getElementRect(boundaryEl); } else { boundaryRect = getWindowRect(ctx.getWin()); } if (allowOverflow) { boundaryRect = createRect({ x: -boundaryRect.width, // empty(left) y: boundaryRect.minY, width: boundaryRect.width * 3, // empty(left) + win + empty(right) height: boundaryRect.height * 2 // win + empty(bottom) }); } return pick(boundaryRect, ["x", "y", "width", "height"]); }; function getResizeAxisStyle(axis) { switch (axis) { case "n": return { cursor: "n-resize", width: "100%", left: "50%", translate: "-50%" }; case "e": return { cursor: "e-resize", height: "100%", right: 0, top: "50%", translate: "0 -50%" }; case "s": return { cursor: "s-resize", width: "100%", bottom: 0, left: "50%", translate: "-50%" }; case "w": return { cursor: "w-resize", height: "100%", left: 0, top: "50%", translate: "0 -50%" }; case "se": return { cursor: "se-resize", bottom: 0, right: 0 }; case "sw": return { cursor: "sw-resize", bottom: 0, left: 0 }; case "ne": return { cursor: "ne-resize", top: 0, right: 0 }; case "nw": return { cursor: "nw-resize", top: 0, left: 0 }; default: throw new Error(`Invalid axis: ${axis}`); } } var validStages = /* @__PURE__ */ new Set(["minimized", "maximized", "default"]); function connect(service, normalize) { const { state, send, scope, prop, computed, context } = service; const open = state.hasTag("open"); const dragging = state.matches("open.dragging"); const resizing = state.matches("open.resizing"); const isTopmost = context.get("isTopmost"); const size = context.get("size"); const position = context.get("position"); const isMaximized = computed("isMaximized"); const isMinimized = computed("isMinimized"); const isStaged = computed("isStaged"); const canResize = computed("canResize"); const canDrag = computed("canDrag"); return { open, resizable: prop("resizable"), draggable: prop("draggable"), setOpen(nextOpen) { const open2 = state.hasTag("open"); if (open2 === nextOpen) return; send({ type: nextOpen ? "OPEN" : "CLOSE" }); }, dragging, resizing, position, size, setPosition(position2) { send({ type: "SET_POSITION", position: position2 }); }, setSize(size2) { send({ type: "SET_SIZE", size: size2 }); }, minimize() { send({ type: "MINIMIZE" }); }, maximize() { send({ type: "MAXIMIZE" }); }, restore() { send({ type: "RESTORE" }); }, getTriggerProps() { return normalize.button({ ...parts.trigger.attrs, type: "button", disabled: prop("disabled"), id: getTriggerId(scope), "data-state": open ? "open" : "closed", "data-dragging": dataAttr(dragging), "aria-controls": getContentId(scope), onClick(event) { if (event.defaultPrevented) return; if (prop("disabled")) return; const open2 = state.hasTag("open"); send({ type: open2 ? "CLOSE" : "OPEN", src: "trigger" }); } }); }, getPositionerProps() { return normalize.element({ ...parts.positioner.attrs, id: getPositionerId(scope), style: { "--width": toPx(size?.width), "--height": toPx(size?.height), "--x": toPx(position?.x), "--y": toPx(position?.y), position: prop("strategy"), top: "var(--y)", left: "var(--x)" } }); }, getContentProps() { return normalize.element({ ...parts.content.attrs, role: "dialog", tabIndex: 0, hidden: !open, id: getContentId(scope), "aria-labelledby": getTitleId(scope), "data-state": open ? "open" : "closed", "data-dragging": dataAttr(dragging), "data-topmost": dataAttr(isTopmost), "data-behind": dataAttr(!isTopmost), style: { width: "var(--width)", height: "var(--height)", overflow: isMinimized ? "hidden" : void 0 }, onFocus() { send({ type: "CONTENT_FOCUS" }); }, onKeyDown(event) { if (event.defaultPrevented) return; if (!isSelfTarget(event)) return; const step = getEventStep(event) * prop("gridSize"); const keyMap = { Escape() { if (!isTopmost) return; send({ type: "ESCAPE" }); }, ArrowLeft() { send({ type: "MOVE", direction: "left", step }); }, ArrowRight() { send({ type: "MOVE", direction: "right", step }); }, ArrowUp() { send({ type: "MOVE", direction: "up", step }); }, ArrowDown() { send({ type: "MOVE", direction: "down", step }); } }; const handler = keyMap[getEventKey(event, { dir: prop("dir") })]; if (handler) { event.preventDefault(); handler(event); } } }); }, getCloseTriggerProps() { return normalize.button({ ...parts.closeTrigger.attrs, disabled: prop("disabled"), "aria-label": "Close Window", type: "button", onClick(event) { if (event.defaultPrevented) return; send({ type: "CLOSE" }); } }); }, getStageTriggerProps(props2) { if (!validStages.has(props2.stage)) { throw new Error(`[zag-js] Invalid stage: ${props2.stage}. Must be one of: ${Array.from(validStages).join(", ")}`); } const translations = prop("translations"); const actionProps = match(props2.stage, { minimized: () => ({ "aria-label": translations.minimize, hidden: isStaged }), maximized: () => ({ "aria-label": translations.maximize, hidden: isStaged }), default: () => ({ "aria-label": translations.restore, hidden: !isStaged }) }); return normalize.button({ ...parts.stageTrigger.attrs, disabled: prop("disabled"), ...actionProps, type: "button", onClick(event) { if (event.defaultPrevented) return; const type = match(props2.stage, { minimized: () => "MINIMIZE", maximized: () => "MAXIMIZE", default: () => "RESTORE" }); send({ type: type.toUpperCase() }); } }); }, getResizeTriggerProps(props2) { return normalize.element({ ...parts.resizeTrigger.attrs, "data-disabled": dataAttr(!canResize), "data-axis": props2.axis, onPointerDown(event) { if (!canResize) return; if (!isLeftClick(event)) return; event.currentTarget.setPointerCapture(event.pointerId); event.stopPropagation(); send({ type: "RESIZE_START", axis: props2.axis, position: { x: event.clientX, y: event.clientY } }); }, onPointerUp(event) { if (!canResize) return; const node = event.currentTarget; if (node.hasPointerCapture(event.pointerId)) { node.releasePointerCapture(event.pointerId); } }, style: { position: "absolute", touchAction: "none", ...getResizeAxisStyle(props2.axis) } }); }, getDragTriggerProps() { return normalize.element({ ...parts.dragTrigger.attrs, "data-disabled": dataAttr(!canDrag), onPointerDown(event) { if (!canDrag) return; if (!isLeftClick(event)) return; const target = getEventTarget(event); if (target?.closest("button") || target?.closest("[data-no-drag]")) { return; } event.currentTarget.setPointerCapture(event.pointerId); event.stopPropagation(); send({ type: "DRAG_START", pointerId: event.pointerId, position: { x: event.clientX, y: event.clientY } }); }, onPointerUp(event) { if (!canDrag) return; const node = event.currentTarget; if (node.hasPointerCapture(event.pointerId)) { node.releasePointerCapture(event.pointerId); } }, onDoubleClick() { send({ type: isMaximized ? "RESTORE" : "MAXIMIZE" }); }, style: { WebkitUserSelect: "none", userSelect: "none", touchAction: "none", cursor: "move" } }); }, getControlProps() { return normalize.element({ ...parts.control.attrs, "data-disabled": dataAttr(prop("disabled")), "data-stage": context.get("stage") }); }, getTitleProps() { return normalize.element({ ...parts.title.attrs, id: getTitleId(scope) }); }, getHeaderProps() { return normalize.element({ ...parts.header.attrs, id: getHeaderId(scope), "data-dragging": dataAttr(dragging), "data-topmost": dataAttr(isTopmost), "data-behind": dataAttr(!isTopmost) }); }, getBodyProps() { return normalize.element({ ...parts.body.attrs, "data-dragging": dataAttr(dragging), hidden: isMinimized }); } }; } var panelStack = proxy({ stack: [], count() { return this.stack.length; }, add(panelId) { if (this.stack.includes(panelId)) return; this.stack.push(panelId); }, remove(panelId) { const index = this.stack.indexOf(panelId); if (index < 0) return; this.stack.splice(index, 1); }, bringToFront(id) { this.remove(id); this.add(id); }, isTopmost(id) { return this.stack[this.stack.length - 1] === id; }, indexOf(id) { return this.stack.indexOf(id); } }); var { not, and } = createGuards(); var defaultTranslations = { minimize: "Minimize window", maximize: "Maximize window", restore: "Restore window" }; var machine = createMachine({ props({ props: props2 }) { ensureProps(props2, ["id"], "floating-panel"); return { strategy: "fixed", gridSize: 1, defaultSize: { width: 320, height: 240 }, defaultPosition: { x: 300, y: 100 }, allowOverflow: true, resizable: true, draggable: true, ...props2, hasSpecifiedPosition: !!props2.defaultPosition || !!props2.position, translations: { ...defaultTranslations, ...props2.translations } }; }, initialState({ prop }) { const open = prop("open") || prop("defaultOpen"); return open ? "open" : "closed"; }, context({ prop, bindable }) { return { size: bindable(() => ({ defaultValue: prop("defaultSize"), value: prop("size"), isEqual: isSizeEqual, sync: true, hash(v) { return `W:${v.width} H:${v.height}`; }, onChange(value) { prop("onSizeChange")?.({ size: value }); } })), position: bindable(() => ({ defaultValue: prop("defaultPosition"), value: prop("position"), isEqual: isPointEqual, sync: true, hash(v) { return `X:${v.x} Y:${v.y}`; }, onChange(value) { prop("onPositionChange")?.({ position: value }); } })), stage: bindable(() => ({ defaultValue: "default", onChange(value) { prop("onStageChange")?.({ stage: value }); } })), lastEventPosition: bindable(() => ({ defaultValue: null })), prevPosition: bindable(() => ({ defaultValue: null })), prevSize: bindable(() => ({ defaultValue: null })), isTopmost: bindable(() => ({ defaultValue: void 0 })) }; }, computed: { isMaximized: ({ context }) => context.get("stage") === "maximized", isMinimized: ({ context }) => context.get("stage") === "minimized", isStaged: ({ context }) => context.get("stage") !== "default", canResize: ({ context, prop }) => (prop("resizable") || !prop("disabled")) && context.get("stage") === "default", canDrag: ({ prop, computed }) => (prop("draggable") || !prop("disabled")) && !computed("isMaximized") }, watch({ track, context, action, prop }) { track([() => context.hash("position")], () => { action(["setPositionStyle"]); }); track([() => context.hash("size")], () => { action(["setSizeStyle"]); }); track([() => prop("open")], () => { action(["toggleVisibility"]); }); }, effects: ["trackPanelStack"], on: { CONTENT_FOCUS: { actions: ["bringToFrontOfPanelStack"] }, SET_POSITION: { actions: ["setPosition"] }, SET_SIZE: { actions: ["setSize"] } }, states: { closed: { tags: ["closed"], on: { "CONTROLLED.OPEN": { target: "open", actions: ["setAnchorPosition", "setPositionStyle", "setSizeStyle", "focusContentEl"] }, OPEN: [ { guard: "isOpenControlled", actions: ["invokeOnOpen"] }, { target: "open", actions: ["invokeOnOpen", "setAnchorPosition", "setPositionStyle", "setSizeStyle", "focusContentEl"] } ] } }, open: { tags: ["open"], entry: ["bringToFrontOfPanelStack"], effects: ["trackBoundaryRect"], on: { DRAG_START: { guard: not("isMaximized"), target: "open.dragging", actions: ["setPrevPosition"] }, RESIZE_START: { guard: not("isMinimized"), target: "open.resizing", actions: ["setPrevSize"] }, "CONTROLLED.CLOSE": { target: "closed", actions: ["resetRect", "focusTriggerEl"] }, CLOSE: [ { guard: "isOpenControlled", target: "closed", actions: ["invokeOnClose"] }, { target: "closed", actions: ["invokeOnClose", "resetRect", "focusTriggerEl"] } ], ESCAPE: [ { guard: and("isOpenControlled", "closeOnEsc"), actions: ["invokeOnClose"] }, { guard: "closeOnEsc", target: "closed", actions: ["invokeOnClose", "resetRect", "focusTriggerEl"] } ], MINIMIZE: { actions: ["setMinimized"] }, MAXIMIZE: { actions: ["setMaximized"] }, RESTORE: { actions: ["setRestored"] }, MOVE: { actions: ["setPositionFromKeyboard"] } } }, "open.dragging": { tags: ["open"], effects: ["trackPointerMove"], exit: ["clearPrevPosition"], on: { DRAG: { actions: ["setPosition"] }, DRAG_END: { target: "open", actions: ["invokeOnDragEnd"] }, "CONTROLLED.CLOSE": { target: "closed", actions: ["resetRect"] }, CLOSE: [ { guard: "isOpenControlled", target: "closed", actions: ["invokeOnClose"] }, { target: "closed", actions: ["invokeOnClose", "resetRect"] } ], ESCAPE: { target: "open" } } }, "open.resizing": { tags: ["open"], effects: ["trackPointerMove"], exit: ["clearPrevSize"], on: { DRAG: { actions: ["setSize"] }, DRAG_END: { target: "open", actions: ["invokeOnResizeEnd"] }, "CONTROLLED.CLOSE": { target: "closed", actions: ["resetRect"] }, CLOSE: [ { guard: "isOpenControlled", target: "closed", actions: ["invokeOnClose"] }, { target: "closed", actions: ["invokeOnClose", "resetRect"] } ], ESCAPE: { target: "open" } } } }, implementations: { guards: { closeOnEsc: ({ prop }) => !!prop("closeOnEscape"), isMaximized: ({ context }) => context.get("stage") === "maximized", isMinimized: ({ context }) => context.get("stage") === "minimized", isOpenControlled: ({ prop }) => prop("open") != void 0 }, effects: { trackPointerMove({ scope, send, event: evt, prop }) { const doc = scope.getDoc(); const boundaryEl = prop("getBoundaryEl")?.(); const boundaryRect = getBoundaryRect(scope, boundaryEl, false); return trackPointerMove(doc, { onPointerMove({ point, event }) { const { altKey, shiftKey } = event; let x = clampValue(point.x, boundaryRect.x, boundaryRect.x + boundaryRect.width); let y = clampValue(point.y, boundaryRect.y, boundaryRect.y + boundaryRect.height); send({ type: "DRAG", position: { x, y }, axis: evt.axis, altKey, shiftKey }); }, onPointerUp() { send({ type: "DRAG_END" }); } }); }, trackBoundaryRect({ context, scope, prop, computed }) { const win = scope.getWin(); let skip = true; const exec = () => { if (skip) { skip = false; return; } const boundaryEl2 = prop("getBoundaryEl")?.(); let boundaryRect = getBoundaryRect(scope, boundaryEl2, false); if (!computed("isMaximized")) { const rect = { ...context.get("position"), ...context.get("size") }; boundaryRect = constrainRect(rect, boundaryRect); } context.set("size", pick(boundaryRect, ["width", "height"])); context.set("position", pick(boundaryRect, ["x", "y"])); }; const boundaryEl = prop("getBoundaryEl")?.(); if (isHTMLElement(boundaryEl)) { const obs = new win.ResizeObserver(exec); obs.observe(boundaryEl); return () => obs.disconnect(); } return addDomEvent(win, "resize", exec); }, trackPanelStack({ context, scope }) { const unsub = subscribe(panelStack, () => { context.set("isTopmost", panelStack.isTopmost(scope.id)); const contentEl = getContentEl(scope); if (!contentEl) return; const index = panelStack.indexOf(scope.id); if (index === -1) return; contentEl.style.setProperty("--z-index", `${index + 1}`); }); return () => { panelStack.remove(scope.id); unsub(); }; } }, actions: { setAnchorPosition({ context, prop, scope }) { if (prop("hasSpecifiedPosition")) return; const hasPrevRect = context.get("prevPosition") || context.get("prevSize"); if (prop("persistRect") && hasPrevRect) return; raf(() => { const triggerRect = getTriggerEl(scope); const boundaryRect = getBoundaryRect(scope, prop("getBoundaryEl")?.(), false); let anchorPosition = prop("getAnchorPosition")?.({ triggerRect: triggerRect ? DOMRect.fromRect(getElementRect(triggerRect)) : null, boundaryRect: DOMRect.fromRect(boundaryRect) }); if (!anchorPosition) { const size = context.get("size"); anchorPosition = { x: boundaryRect.x + (boundaryRect.width - size.width) / 2, y: boundaryRect.y + (boundaryRect.height - size.height) / 2 }; } if (!anchorPosition) return; context.set("position", anchorPosition); }); }, setPrevPosition({ context, event }) { context.set("prevPosition", { ...context.get("position") }); context.set("lastEventPosition", event.position); }, clearPrevPosition({ context, prop }) { if (!prop("persistRect")) context.set("prevPosition", null); context.set("lastEventPosition", null); }, setPosition({ context, event, prop, scope }) { let diff = subtractPoints(event.position, context.get("lastEventPosition")); diff.x = Math.round(diff.x / prop("gridSize")) * prop("gridSize"); diff.y = Math.round(diff.y / prop("gridSize")) * prop("gridSize"); const prevPosition = context.get("prevPosition"); if (!prevPosition) return; let position = addPoints(prevPosition, diff); const boundaryEl = prop("getBoundaryEl")?.(); const boundaryRect = getBoundaryRect(scope, boundaryEl, prop("allowOverflow")); position = clampPoint(position, context.get("size"), boundaryRect); context.set("position", position); }, setPositionStyle({ scope, context }) { const el = getPositionerEl(scope); const position = context.get("position"); el?.style.setProperty("--x", `${position.x}px`); el?.style.setProperty("--y", `${position.y}px`); }, resetRect({ context, prop }) { context.set("stage", "default"); if (!prop("persistRect")) { context.set("position", context.initial("position")); context.set("size", context.initial("size")); } }, setPrevSize({ context, event }) { context.set("prevSize", { ...context.get("size") }); context.set("prevPosition", { ...context.get("position") }); context.set("lastEventPosition", event.position); }, clearPrevSize({ context }) { context.set("prevSize", null); context.set("prevPosition", null); context.set("lastEventPosition", null); }, setSize({ context, event, scope, prop }) { const prevSize = context.get("prevSize"); const prevPosition = context.get("prevPosition"); const lastEventPosition = context.get("lastEventPosition"); if (!prevSize || !prevPosition || !lastEventPosition) return; const prevRect = createRect({ ...prevPosition, ...prevSize }); const offset = subtractPoints(event.position, lastEventPosition); const nextRect = resizeRect(prevRect, offset, event.axis, { scalingOriginMode: event.altKey ? "center" : "extent", lockAspectRatio: !!prop("lockAspectRatio") || event.shiftKey }); let nextSize = pick(nextRect, ["width", "height"]); let nextPosition = pick(nextRect, ["x", "y"]); const boundaryEl = prop("getBoundaryEl")?.(); const boundaryRect = getBoundaryRect(scope, boundaryEl, false); nextSize = clampSize(nextSize, prop("minSize"), prop("maxSize")); nextSize = clampSize(nextSize, prop("minSize"), boundaryRect); context.set("size", nextSize); if (nextPosition) { const point = clampPoint(nextPosition, nextSize, boundaryRect); context.set("position", point); } }, setSizeStyle({ scope, context }) { queueMicrotask(() => { const el = getPositionerEl(scope); const size = context.get("size"); el?.style.setProperty("--width", `${size.width}px`); el?.style.setProperty("--height", `${size.height}px`); }); }, setMaximized({ context, prop, scope }) { context.set("stage", "maximized"); context.set("prevSize", context.get("size")); context.set("prevPosition", context.get("position")); const boundaryEl = prop("getBoundaryEl")?.(); const boundaryRect = getBoundaryRect(scope, boundaryEl, false); context.set("position", pick(boundaryRect, ["x", "y"])); context.set("size", pick(boundaryRect, ["height", "width"])); }, setMinimized({ context, scope }) { context.set("stage", "minimized"); context.set("prevSize", context.get("size")); context.set("prevPosition", context.get("position")); const headerEl = getHeaderEl(scope); if (!headerEl) return; const size = { ...context.get("size"), height: headerEl?.offsetHeight }; context.set("size", size); }, setRestored({ context, prop, scope }) { const boundaryRect = getBoundaryRect(scope, prop("getBoundaryEl")?.(), false); context.set("stage", "default"); const prevSize = context.get("prevSize"); if (prevSize) { let nextSize = prevSize; nextSize = clampSize(nextSize, prop("minSize"), prop("maxSize")); nextSize = clampSize(nextSize, prop("minSize"), boundaryRect); context.set("size", nextSize); context.set("prevSize", null); } if (context.get("prevPosi