@exponential_app/eui-solid 0.3.0 → 0.4.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.
@@ -1,11 +1,12 @@
1
- import { createComponent, mergeProps, Dynamic, spread, insert, template, effect, setAttribute, style, use } from "solid-js/web";
2
1
  import { splitProps, createRoot, For, createSignal, createEffect, onCleanup, getOwner, createRenderEffect, Show, children, untrack, on, createContext, useContext, onMount, createMemo, createComputed } from "solid-js";
3
- import { Icon, Loader, CircleDashed, Star, Upload, Search, Calendar, PhoneIncoming, PhoneOff, Ear, Volume2, MicOff, Mic, AudioLines, Hand, QrCode, ScanLine, CheckCheck, Menu, Ellipsis, ArrowLeft, Send, Paperclip, CircleStop, CircleX, TriangleAlert, CircleCheck, Info, Clock, Plus, Minus, File, Copy, X, ChevronsUpDown, ChevronRight, ChevronLeft, ChevronUp, ChevronDown, Check, Play, Square } from "lucide-solid";
4
2
  import { CUSTOM_ICON_NODES, lookupIcon, layoutSize, typeaheadStep, nextEnabledIndex, str, bool } from "@exponential_app/eui/web";
5
- import { OVERLAY_PADDING } from "@exponential_app/eui";
3
+ import { createComponent, mergeProps, Dynamic, spread, insert, template, effect, setAttribute, style, use, memo, className, addEventListener } from "solid-js/web";
4
+ import { Icon, Pause, Play, LoaderCircle, CircleDashed, Star, Upload, Search, Calendar, PhoneIncoming, PhoneOff, Ear, Volume2, MicOff, Mic, AudioLines, Maximize2, Hand, QrCode, ScanLine, CheckCheck, Menu, Ellipsis, ArrowLeft, Send, Paperclip, CircleStop, CircleX, TriangleAlert, CircleCheck, Info, Clock, Plus, Minus, File, Copy, X, ChevronsUpDown, ChevronRight, ChevronLeft, ChevronUp, ChevronDown, Check, Square, Circle } from "lucide-solid";
5
+ import { OVERLAY_PADDING, zoomPercent, zoomBounds, zoomMenu, zoomResize, zoomPanRoom, zoomMomentumActive, zoomMomentum, zoomPinch, zoomDrag, zoomKey, zoomDoubleTap, zoomStep, zoomScroll, zoomWheel, zoomCentre, zoomTo, zoomAtRest, zoomClamp, zoomRestView, zoomIsTall, ZOOM } from "@exponential_app/eui";
6
+ import { cn, buttonVariants, DROPDOWN_MENU_CLASSES, zoomDeclaredSize, ZOOMABLE_IMAGE_TRANSITION, ZOOMABLE_IMAGE_CLASSES, zoomImageStyle, zoomBoxAspect, createZoomController } from "@exponential_app/eui/web/primitives";
6
7
  import { hideOthers } from "aria-hidden";
7
8
  import { offset, shift, limitShift, flip, size, autoUpdate, computePosition } from "@floating-ui/dom";
8
- var _tmpl$$4 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round>`);
9
+ var _tmpl$$7 = /* @__PURE__ */ template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round>`);
9
10
  const CHROME = {
10
11
  check: Check,
11
12
  chevronDown: ChevronDown,
@@ -18,8 +19,9 @@ const CHROME = {
18
19
  send: Send,
19
20
  stop: Square,
20
21
  play: Play,
22
+ pause: Pause,
21
23
  attach: Paperclip,
22
- spinner: Loader,
24
+ spinner: LoaderCircle,
23
25
  placeholder: CircleDashed
24
26
  };
25
27
  const FALLBACK_ICONS = {
@@ -52,6 +54,8 @@ const FALLBACK_ICONS = {
52
54
  "ui-scan": ScanLine,
53
55
  "ui-qr-code": QrCode,
54
56
  "ui-hold": Hand,
57
+ // EXP-1586: the ZoomableImage pill's fit button.
58
+ "ui-fullscreen": Maximize2,
55
59
  "voice-level": AudioLines,
56
60
  "call-mute": Mic,
57
61
  "call-unmute": MicOff,
@@ -109,7 +113,7 @@ function LucideSvg(props) {
109
113
  const size2 = () => local.size ?? 24;
110
114
  const attr = (name, fallback) => name in rest ? rest[name] : fallback;
111
115
  return (() => {
112
- var _el$ = _tmpl$$4();
116
+ var _el$ = _tmpl$$7();
113
117
  spread(_el$, mergeProps({
114
118
  get ["aria-hidden"]() {
115
119
  return hasA11y() ? void 0 : `true`;
@@ -197,7 +201,7 @@ function css(style2) {
197
201
  return out;
198
202
  }
199
203
  const px = (v) => typeof v === `number` ? v === 0 ? `0` : `${v}px` : v;
200
- function createMediaQuery(query, fallback = false) {
204
+ function createMediaQuery$1(query, fallback = false) {
201
205
  if (typeof window === `undefined` || typeof window.matchMedia !== `function`) return () => fallback;
202
206
  const mql = window.matchMedia(query);
203
207
  const [matches, setMatches] = createSignal(mql.matches);
@@ -668,7 +672,7 @@ function useModalEffects(el, lockScroll) {
668
672
  onCleanup(undo);
669
673
  if (lockScroll) useScrollLock();
670
674
  }
671
- var _tmpl$$3 = /* @__PURE__ */ template(`<div data-radix-popper-content-wrapper>`);
675
+ var _tmpl$$6 = /* @__PURE__ */ template(`<div data-radix-popper-content-wrapper>`);
672
676
  const transformOrigin = {
673
677
  name: `transformOrigin`,
674
678
  fn(data) {
@@ -715,7 +719,7 @@ function Popper(props) {
715
719
  let zIndex;
716
720
  let disposed = false;
717
721
  const wrapper = (() => {
718
- var _el$ = _tmpl$$3();
722
+ var _el$ = _tmpl$$6();
719
723
  effect(() => setAttribute(_el$, "dir", props.dir));
720
724
  return _el$;
721
725
  })();
@@ -858,7 +862,7 @@ function popperWrapper(opts) {
858
862
  return css(s);
859
863
  };
860
864
  const wrapper = (() => {
861
- var _el$2 = _tmpl$$3();
865
+ var _el$2 = _tmpl$$6();
862
866
  insert(_el$2, () => opts.content(placed, (el) => contentEl = el));
863
867
  effect((_p$) => {
864
868
  var _v$ = style$1(), _v$2 = opts.dir?.();
@@ -969,10 +973,10 @@ function graceArea(exit, from, to) {
969
973
  const padded = m === left ? [{ x: exit.x + padding, y: exit.y - padding }, { x: exit.x + padding, y: exit.y + padding }] : m === right ? [{ x: exit.x - padding, y: exit.y - padding }, { x: exit.x - padding, y: exit.y + padding }] : m === top ? [{ x: exit.x - padding, y: exit.y + padding }, { x: exit.x + padding, y: exit.y + padding }] : [{ x: exit.x - padding, y: exit.y - padding }, { x: exit.x + padding, y: exit.y - padding }];
970
974
  return hull([...padded, { x: to.left, y: to.top }, { x: to.right, y: to.top }, { x: to.right, y: to.bottom }, { x: to.left, y: to.bottom }]);
971
975
  }
972
- var _tmpl$$2 = /* @__PURE__ */ template(`<span role=tooltip>`);
976
+ var _tmpl$$5 = /* @__PURE__ */ template(`<span role=tooltip>`);
973
977
  function VisuallyHidden(props) {
974
978
  const el = (() => {
975
- var _el$ = _tmpl$$2();
979
+ var _el$ = _tmpl$$5();
976
980
  insert(_el$, () => props.children);
977
981
  effect(() => setAttribute(_el$, "id", props.id));
978
982
  return _el$;
@@ -1034,7 +1038,7 @@ function findNextItem(items, search, current) {
1034
1038
  const next = wrapped.find((item) => item.label.toLowerCase().startsWith(normalized.toLowerCase()));
1035
1039
  return next !== current ? next : void 0;
1036
1040
  }
1037
- var _tmpl$$1 = /* @__PURE__ */ template(`<div role=menu aria-orientation=vertical data-radix-menu-content>`);
1041
+ var _tmpl$$4 = /* @__PURE__ */ template(`<div role=menu aria-orientation=vertical data-radix-menu-content>`);
1038
1042
  let usingKeyboard = false;
1039
1043
  let keyboardListeners = 0;
1040
1044
  function useKeyboardTracking() {
@@ -1163,7 +1167,7 @@ function MenuContent(props) {
1163
1167
  },
1164
1168
  children: (popper) => {
1165
1169
  const el = (() => {
1166
- var _el$ = _tmpl$$1();
1170
+ var _el$ = _tmpl$$4();
1167
1171
  spread(_el$, mergeProps({
1168
1172
  get ["data-side"]() {
1169
1173
  return popper.placedSide();
@@ -1510,7 +1514,7 @@ function createElementSize(el) {
1510
1514
  });
1511
1515
  return size2;
1512
1516
  }
1513
- var _tmpl$ = /* @__PURE__ */ template(`<input aria-hidden=true tabindex=-1>`), _tmpl$2 = /* @__PURE__ */ template(`<input>`), _tmpl$3 = /* @__PURE__ */ template(`<select aria-hidden=true tabindex=-1>`), _tmpl$4 = /* @__PURE__ */ template(`<option value>`), _tmpl$5 = /* @__PURE__ */ template(`<option>`);
1517
+ var _tmpl$$3 = /* @__PURE__ */ template(`<input aria-hidden=true tabindex=-1>`), _tmpl$2$3 = /* @__PURE__ */ template(`<input>`), _tmpl$3$2 = /* @__PURE__ */ template(`<select aria-hidden=true tabindex=-1>`), _tmpl$4$2 = /* @__PURE__ */ template(`<option value>`), _tmpl$5$1 = /* @__PURE__ */ template(`<option>`);
1514
1518
  function createInForm(el) {
1515
1519
  const [inForm, setInForm] = createSignal(false);
1516
1520
  onMount(() => setInForm(Boolean(el()?.closest(`form`))));
@@ -1557,7 +1561,7 @@ function BubbleCheck(props) {
1557
1561
  });
1558
1562
  };
1559
1563
  return (() => {
1560
- var _el$ = _tmpl$();
1564
+ var _el$ = _tmpl$$3();
1561
1565
  var _ref$ = input;
1562
1566
  typeof _ref$ === "function" ? use(_ref$, _el$) : input = _el$;
1563
1567
  setAttribute(_el$, "checked", initial ? `` : void 0);
@@ -1583,7 +1587,7 @@ function SliderBubble(props) {
1583
1587
  const initial = untrack(() => String(props.value));
1584
1588
  bubbleOnChange(() => input, () => props.value, (el, v) => Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, `value`)?.set?.call(el, v), `input`);
1585
1589
  return (() => {
1586
- var _el$2 = _tmpl$2();
1590
+ var _el$2 = _tmpl$2$3();
1587
1591
  var _ref$2 = input;
1588
1592
  typeof _ref$2 === "function" ? use(_ref$2, _el$2) : input = _el$2;
1589
1593
  setAttribute(_el$2, "value", initial);
@@ -1626,17 +1630,17 @@ function NativeSelect(props) {
1626
1630
  wordWrap: `normal`
1627
1631
  });
1628
1632
  return (() => {
1629
- var _el$3 = _tmpl$3();
1633
+ var _el$3 = _tmpl$3$2();
1630
1634
  _el$3.addEventListener("change", (e) => props.onChange(e.currentTarget.value));
1631
1635
  var _ref$3 = el;
1632
1636
  typeof _ref$3 === "function" ? use(_ref$3, _el$3) : el = _el$3;
1633
- insert(_el$3, initial === void 0 ? _tmpl$4() : null, null);
1637
+ insert(_el$3, initial === void 0 ? _tmpl$4$2() : null, null);
1634
1638
  insert(_el$3, createComponent(For, {
1635
1639
  get each() {
1636
1640
  return props.options;
1637
1641
  },
1638
1642
  children: (o) => (() => {
1639
- var _el$5 = _tmpl$5();
1643
+ var _el$5 = _tmpl$5$1();
1640
1644
  insert(_el$5, () => str(o.label));
1641
1645
  effect((_p$) => {
1642
1646
  var _v$0 = bool(o.disabled), _v$1 = initial !== void 0 && o.value === initial ? `` : void 0;
@@ -1687,7 +1691,1323 @@ function createImageLoadingStatus(src) {
1687
1691
  }
1688
1692
  return status;
1689
1693
  }
1694
+ function Button(props) {
1695
+ const [local, rest] = splitProps(props, [`class`, `variant`, `size`, `as`]);
1696
+ const variant = () => local.variant ?? `default`;
1697
+ const size2 = () => local.size ?? `default`;
1698
+ return createComponent(Dynamic, mergeProps({
1699
+ get component() {
1700
+ return local.as ?? `button`;
1701
+ },
1702
+ "data-slot": "button",
1703
+ get ["data-variant"]() {
1704
+ return variant();
1705
+ },
1706
+ get ["data-size"]() {
1707
+ return size2();
1708
+ },
1709
+ get ["class"]() {
1710
+ return cn(buttonVariants({
1711
+ variant: variant(),
1712
+ size: size2(),
1713
+ className: local.class
1714
+ }));
1715
+ }
1716
+ }, rest));
1717
+ }
1718
+ var _tmpl$$2 = /* @__PURE__ */ template(`<div>`), _tmpl$2$2 = /* @__PURE__ */ template(`<div tabindex=-1>`), _tmpl$3$1 = /* @__PURE__ */ template(`<h2>`), _tmpl$4$1 = /* @__PURE__ */ template(`<p>`);
1719
+ function callHandler(handler, event) {
1720
+ if (typeof handler === `function`) handler(event);
1721
+ else if (Array.isArray(handler) && typeof handler[0] === `function`) handler[0](handler[1], event);
1722
+ }
1723
+ function composeHandlers(user, ours, checkForDefaultPrevented = true) {
1724
+ return (event) => {
1725
+ callHandler(user, event);
1726
+ if (!checkForDefaultPrevented || !event.defaultPrevented) ours(event);
1727
+ };
1728
+ }
1729
+ function callRef(ref, el) {
1730
+ if (typeof ref === `function`) ref(el);
1731
+ }
1732
+ function mergeRefs(...refs) {
1733
+ return (el) => {
1734
+ for (const r of refs) if (typeof r === `function`) r(el);
1735
+ };
1736
+ }
1737
+ function styleObject(style2) {
1738
+ if (!style2 || typeof style2 !== `object`) return {};
1739
+ const out = {};
1740
+ for (const [k, v] of Object.entries(style2)) out[k] = v === void 0 || v === null ? void 0 : String(v);
1741
+ return out;
1742
+ }
1743
+ function createOpenState(o) {
1744
+ const [inner, setInner] = createSignal(untrack(() => o.defaultOpen) ?? false);
1745
+ const open = () => o.open() ?? inner();
1746
+ const set = (next) => {
1747
+ const prev = untrack(open);
1748
+ if (next !== prev) untrack(o.onOpenChange)?.(next);
1749
+ if (untrack(o.open) === void 0) setInner(next);
1750
+ };
1751
+ return [open, set];
1752
+ }
1753
+ const stateOf = (open) => open ? `open` : `closed`;
1754
+ let layerMounted = false;
1755
+ function noteLayerMount() {
1756
+ if (layerMounted) return;
1757
+ layerMounted = true;
1758
+ queueMicrotask(() => layerMounted = false);
1759
+ }
1760
+ function layerMountedThisTask() {
1761
+ return layerMounted;
1762
+ }
1763
+ function layerPointerEvents(layer, registered, lag) {
1764
+ return lag && !registered ? void 0 : layer.pointerEvents(registered);
1765
+ }
1766
+ const DialogContext = createContext();
1767
+ function useDialogContext(part) {
1768
+ const ctx = useContext(DialogContext);
1769
+ if (!ctx) throw new Error(`\`${part}\` must be used within \`Dialog\``);
1770
+ return ctx;
1771
+ }
1772
+ function DialogRoot(props) {
1773
+ const [open, setOpen] = createOpenState({
1774
+ open: () => props.open,
1775
+ defaultOpen: props.defaultOpen,
1776
+ onOpenChange: () => props.onOpenChange
1777
+ });
1778
+ const [trigger, setTrigger] = createSignal();
1779
+ const value = {
1780
+ open,
1781
+ setOpen,
1782
+ modal: untrack(() => props.modal) ?? true,
1783
+ contentId: `radix-${createId()}`,
1784
+ titleId: `radix-${createId()}`,
1785
+ descriptionId: `radix-${createId()}`,
1786
+ trigger,
1787
+ setTrigger
1788
+ };
1789
+ return createComponent(DialogContext.Provider, {
1790
+ value,
1791
+ get children() {
1792
+ return props.children;
1793
+ }
1794
+ });
1795
+ }
1796
+ let idCounter = 0;
1797
+ function createId() {
1798
+ return `s${++idCounter}`;
1799
+ }
1800
+ function DialogTriggerPart(props) {
1801
+ const ctx = useDialogContext(`DialogTrigger`);
1802
+ const [local, rest] = splitProps(props, [`as`, `ref`, `onClick`]);
1803
+ return createComponent(Dynamic, mergeProps({
1804
+ get component() {
1805
+ return local.as ?? `button`;
1806
+ },
1807
+ type: "button",
1808
+ "aria-haspopup": "dialog",
1809
+ get ["aria-expanded"]() {
1810
+ return ctx.open() ? `true` : `false`;
1811
+ },
1812
+ get ["aria-controls"]() {
1813
+ return ctx.contentId;
1814
+ },
1815
+ get ["data-state"]() {
1816
+ return stateOf(ctx.open());
1817
+ }
1818
+ }, rest, {
1819
+ ref(r$) {
1820
+ var _ref$ = mergeRefs(local.ref, ctx.setTrigger);
1821
+ typeof _ref$ === "function" && _ref$(r$);
1822
+ },
1823
+ get onClick() {
1824
+ return composeHandlers(local.onClick, () => ctx.setOpen(!untrack(ctx.open)));
1825
+ }
1826
+ }));
1827
+ }
1828
+ function DialogClosePart(props) {
1829
+ const ctx = useDialogContext(`DialogClose`);
1830
+ const [local, rest] = splitProps(props, [`as`, `ref`, `onClick`]);
1831
+ return createComponent(Dynamic, mergeProps({
1832
+ get component() {
1833
+ return local.as ?? `button`;
1834
+ },
1835
+ type: "button"
1836
+ }, rest, {
1837
+ ref(r$) {
1838
+ var _ref$2 = local.ref;
1839
+ typeof _ref$2 === "function" ? _ref$2(r$) : local.ref = r$;
1840
+ },
1841
+ get onClick() {
1842
+ return composeHandlers(local.onClick, () => ctx.setOpen(false));
1843
+ }
1844
+ }));
1845
+ }
1846
+ function DialogPortalPart(props) {
1847
+ const [mounted, setMounted] = createSignal(false);
1848
+ onMount(() => setMounted(true));
1849
+ return createComponent(LayerPortal, {
1850
+ get mount() {
1851
+ return memo(() => props.container !== void 0)() ? props.container : memo(() => !!mounted())() ? document.body : null;
1852
+ },
1853
+ get children() {
1854
+ return props.children;
1855
+ }
1856
+ });
1857
+ }
1858
+ function DialogOverlayPart(props) {
1859
+ const ctx = useDialogContext(`DialogOverlay`);
1860
+ const presence = createPresence(ctx.open);
1861
+ const [local, rest] = splitProps(props, [`style`, `ref`]);
1862
+ const Overlay = () => {
1863
+ const el = (() => {
1864
+ var _el$ = _tmpl$$2();
1865
+ spread(_el$, mergeProps({
1866
+ get ["data-state"]() {
1867
+ return stateOf(ctx.open());
1868
+ }
1869
+ }, rest), false, false);
1870
+ return _el$;
1871
+ })();
1872
+ presence.ref(el);
1873
+ bindStyle(el, () => ({
1874
+ "pointer-events": `auto`,
1875
+ ...styleObject(local.style)
1876
+ }));
1877
+ callRef(local.ref, el);
1878
+ onMount(() => useScrollLock());
1879
+ return el;
1880
+ };
1881
+ return createComponent(Show, {
1882
+ get when() {
1883
+ return memo(() => !!ctx.modal)() && presence.mounted();
1884
+ },
1885
+ get children() {
1886
+ return createComponent(Overlay, {});
1887
+ }
1888
+ });
1889
+ }
1890
+ function DialogContentPart(props) {
1891
+ const ctx = useDialogContext(`DialogContent`);
1892
+ const presence = createPresence(ctx.open);
1893
+ const [local, rest] = splitProps(props, [`role`, `style`, `ref`, `children`, `onOpenAutoFocus`, `onCloseAutoFocus`, `onEscapeKeyDown`, `onPointerDownOutside`, `onFocusOutside`, `onInteractOutside`, `onKeyDown`]);
1894
+ const Content = () => {
1895
+ const modal = ctx.modal;
1896
+ let interactedOutside = false;
1897
+ let pointerDownOutside = false;
1898
+ const layer = createLayer({
1899
+ disableOutsidePointerEvents: () => modal,
1900
+ onEscapeKeyDown: (e) => local.onEscapeKeyDown?.(e),
1901
+ onPointerDownOutside: (e) => {
1902
+ local.onPointerDownOutside?.(e);
1903
+ if (!modal || e.defaultPrevented) return;
1904
+ const original = e.detail.originalEvent;
1905
+ const ctrlLeftClick = original.button === 0 && original.ctrlKey === true;
1906
+ if (original.button === 2 || ctrlLeftClick) e.preventDefault();
1907
+ },
1908
+ onFocusOutside: (e) => {
1909
+ local.onFocusOutside?.(e);
1910
+ if (modal && !e.defaultPrevented) e.preventDefault();
1911
+ },
1912
+ onInteractOutside: (e) => {
1913
+ local.onInteractOutside?.(e);
1914
+ if (modal) return;
1915
+ if (!e.defaultPrevented) {
1916
+ interactedOutside = true;
1917
+ if (e.detail.originalEvent.type === `pointerdown`) pointerDownOutside = true;
1918
+ }
1919
+ const target = e.target;
1920
+ if (target && ctx.trigger()?.contains(target)) e.preventDefault();
1921
+ if (e.detail.originalEvent.type === `focusin` && pointerDownOutside) e.preventDefault();
1922
+ },
1923
+ onDismiss: () => ctx.setOpen(false)
1924
+ });
1925
+ const scope = createFocusScope({
1926
+ trapped: () => modal && ctx.open(),
1927
+ loop: true,
1928
+ onMountAutoFocus: (e) => local.onOpenAutoFocus?.(e),
1929
+ onUnmountAutoFocus: (e) => {
1930
+ if (modal) {
1931
+ local.onCloseAutoFocus?.(e);
1932
+ if (e.defaultPrevented) return;
1933
+ e.preventDefault();
1934
+ ctx.trigger()?.focus();
1935
+ return;
1936
+ }
1937
+ local.onCloseAutoFocus?.(e);
1938
+ if (!e.defaultPrevented) {
1939
+ if (!interactedOutside) ctx.trigger()?.focus();
1940
+ e.preventDefault();
1941
+ }
1942
+ interactedOutside = false;
1943
+ pointerDownOutside = false;
1944
+ }
1945
+ });
1946
+ const [registered, setRegistered] = createSignal(false);
1947
+ const lag = layerMountedThisTask();
1948
+ const el = (() => {
1949
+ var _el$2 = _tmpl$2$2();
1950
+ spread(_el$2, mergeProps({
1951
+ get role() {
1952
+ return local.role ?? `dialog`;
1953
+ },
1954
+ get id() {
1955
+ return ctx.contentId;
1956
+ },
1957
+ get ["aria-describedby"]() {
1958
+ return ctx.descriptionId;
1959
+ },
1960
+ get ["aria-labelledby"]() {
1961
+ return ctx.titleId;
1962
+ },
1963
+ get ["data-state"]() {
1964
+ return stateOf(ctx.open());
1965
+ }
1966
+ }, rest, {
1967
+ "onKeyDown": (e) => {
1968
+ callHandler(local.onKeyDown, e);
1969
+ scope.onKeyDown(e);
1970
+ }
1971
+ }), false, true);
1972
+ insert(_el$2, () => local.children);
1973
+ return _el$2;
1974
+ })();
1975
+ presence.ref(el);
1976
+ bindStyle(el, () => ({
1977
+ "pointer-events": layerPointerEvents(layer, registered(), lag),
1978
+ ...styleObject(local.style)
1979
+ }));
1980
+ callRef(local.ref, el);
1981
+ onMount(() => {
1982
+ layer.attach(el);
1983
+ setRegistered(true);
1984
+ noteLayerMount();
1985
+ scope.attach(el);
1986
+ useFocusGuards();
1987
+ if (modal) useModalEffects(el, false);
1988
+ });
1989
+ return el;
1990
+ };
1991
+ return createComponent(Show, {
1992
+ get when() {
1993
+ return presence.mounted();
1994
+ },
1995
+ get children() {
1996
+ return createComponent(Content, {});
1997
+ }
1998
+ });
1999
+ }
2000
+ function DialogTitlePart(props) {
2001
+ const ctx = useDialogContext(`DialogTitle`);
2002
+ return (() => {
2003
+ var _el$3 = _tmpl$3$1();
2004
+ spread(_el$3, mergeProps({
2005
+ get id() {
2006
+ return ctx.titleId;
2007
+ }
2008
+ }, props), false, false);
2009
+ return _el$3;
2010
+ })();
2011
+ }
2012
+ function DialogDescriptionPart(props) {
2013
+ const ctx = useDialogContext(`DialogDescription`);
2014
+ return (() => {
2015
+ var _el$4 = _tmpl$4$1();
2016
+ spread(_el$4, mergeProps({
2017
+ get id() {
2018
+ return ctx.descriptionId;
2019
+ }
2020
+ }, props), false, false);
2021
+ return _el$4;
2022
+ })();
2023
+ }
2024
+ var _tmpl$$1 = /* @__PURE__ */ template(`<div role=group data-slot=dropdown-menu-group>`), _tmpl$2$1 = /* @__PURE__ */ template(`<div role=menuitem>`), _tmpl$3 = /* @__PURE__ */ template(`<span>`), _tmpl$4 = /* @__PURE__ */ template(`<div role=menuitemcheckbox><span>`), _tmpl$5 = /* @__PURE__ */ template(`<div role=group data-slot=dropdown-menu-radio-group>`), _tmpl$6 = /* @__PURE__ */ template(`<div role=menuitemradio><span>`), _tmpl$7 = /* @__PURE__ */ template(`<div data-slot=dropdown-menu-label>`), _tmpl$8 = /* @__PURE__ */ template(`<div role=separator aria-orientation=horizontal data-slot=dropdown-menu-separator>`), _tmpl$9 = /* @__PURE__ */ template(`<span data-slot=dropdown-menu-shortcut>`), _tmpl$0 = /* @__PURE__ */ template(`<div role=menuitem aria-haspopup=menu>`);
2025
+ const RootContext = createContext();
2026
+ const useRoot = (part) => {
2027
+ const ctx = useContext(RootContext);
2028
+ if (!ctx) throw new Error(`\`${part}\` must be used within \`DropdownMenu\``);
2029
+ return ctx;
2030
+ };
2031
+ const LevelOpenContext = createContext(() => false);
2032
+ function DropdownMenu(props) {
2033
+ const [open, setOpen] = createOpenState({
2034
+ open: () => props.open,
2035
+ defaultOpen: props.defaultOpen,
2036
+ onOpenChange: () => props.onOpenChange
2037
+ });
2038
+ const [trigger, setTrigger] = createSignal();
2039
+ useKeyboardTracking();
2040
+ const value = {
2041
+ open,
2042
+ setOpen,
2043
+ triggerId: `radix-${createId()}`,
2044
+ contentId: `radix-${createId()}`,
2045
+ trigger,
2046
+ setTrigger,
2047
+ dir: () => props.dir ?? `ltr`
2048
+ };
2049
+ return createComponent(RootContext.Provider, {
2050
+ value,
2051
+ get children() {
2052
+ return createComponent(LevelOpenContext.Provider, {
2053
+ value: open,
2054
+ get children() {
2055
+ return props.children;
2056
+ }
2057
+ });
2058
+ }
2059
+ });
2060
+ }
2061
+ function DropdownMenuPortal(props) {
2062
+ return createComponent(DialogPortalPart, props);
2063
+ }
2064
+ function DropdownMenuTrigger(props) {
2065
+ const ctx = useRoot(`DropdownMenuTrigger`);
2066
+ const [local, rest] = splitProps(props, [`as`, `ref`, `disabled`, `onPointerDown`, `onKeyDown`]);
2067
+ const disabled = () => local.disabled ?? false;
2068
+ return createComponent(Dynamic, mergeProps({
2069
+ get component() {
2070
+ return local.as ?? `button`;
2071
+ },
2072
+ "data-slot": "dropdown-menu-trigger",
2073
+ type: "button",
2074
+ get id() {
2075
+ return ctx.triggerId;
2076
+ },
2077
+ "aria-haspopup": "menu",
2078
+ get ["aria-expanded"]() {
2079
+ return ctx.open() ? `true` : `false`;
2080
+ },
2081
+ get ["aria-controls"]() {
2082
+ return memo(() => !!ctx.open())() ? ctx.contentId : void 0;
2083
+ },
2084
+ get ["data-state"]() {
2085
+ return stateOf(ctx.open());
2086
+ },
2087
+ get ["data-disabled"]() {
2088
+ return disabled() ? `` : void 0;
2089
+ },
2090
+ get disabled() {
2091
+ return disabled();
2092
+ }
2093
+ }, rest, {
2094
+ ref(r$) {
2095
+ var _ref$ = mergeRefs(local.ref, ctx.setTrigger);
2096
+ typeof _ref$ === "function" && _ref$(r$);
2097
+ },
2098
+ get onPointerDown() {
2099
+ return composeHandlers(local.onPointerDown, (e) => {
2100
+ if (!untrack(disabled) && e.button === 0 && e.ctrlKey === false) {
2101
+ const was = untrack(ctx.open);
2102
+ ctx.setOpen(!was);
2103
+ if (!was) e.preventDefault();
2104
+ }
2105
+ });
2106
+ },
2107
+ get onKeyDown() {
2108
+ return composeHandlers(local.onKeyDown, (e) => {
2109
+ if (untrack(disabled)) return;
2110
+ if ([`Enter`, ` `].includes(e.key)) ctx.setOpen(!untrack(ctx.open));
2111
+ if (e.key === `ArrowDown`) ctx.setOpen(true);
2112
+ if ([`Enter`, ` `, `ArrowDown`].includes(e.key)) e.preventDefault();
2113
+ });
2114
+ }
2115
+ }));
2116
+ }
2117
+ const CONTENT_KEYS = [`class`, `side`, `align`, `sideOffset`, `alignOffset`, `collisionPadding`, `container`, `children`, `ref`, `onKeyDown`, `onCloseAutoFocus`, `onEscapeKeyDown`, `onFocusOutside`, `onInteractOutside`];
2118
+ function DropdownMenuContent(props) {
2119
+ const ctx = useRoot(`DropdownMenuContent`);
2120
+ const [local, rest] = splitProps(props, CONTENT_KEYS);
2121
+ const presence = createPresence(ctx.open);
2122
+ let interactedOutside = false;
2123
+ return createComponent(DropdownMenuPortal, {
2124
+ get container() {
2125
+ return local.container;
2126
+ },
2127
+ get children() {
2128
+ return createComponent(Show, {
2129
+ get when() {
2130
+ return presence.mounted();
2131
+ },
2132
+ children: (_) => {
2133
+ const lag = layerMountedThisTask();
2134
+ return createComponent(MenuContent, {
2135
+ get anchor() {
2136
+ return ctx.trigger();
2137
+ },
2138
+ get side() {
2139
+ return local.side ?? `bottom`;
2140
+ },
2141
+ get align() {
2142
+ return local.align ?? `center`;
2143
+ },
2144
+ get sideOffset() {
2145
+ return local.sideOffset ?? 4;
2146
+ },
2147
+ get alignOffset() {
2148
+ return local.alignOffset;
2149
+ },
2150
+ get collisionPadding() {
2151
+ return local.collisionPadding ?? 0;
2152
+ },
2153
+ get dir() {
2154
+ return ctx.dir();
2155
+ },
2156
+ kind: "dropdown-menu",
2157
+ lagParentLayer: lag,
2158
+ root: true,
2159
+ get id() {
2160
+ return ctx.contentId;
2161
+ },
2162
+ get labelledBy() {
2163
+ return ctx.triggerId;
2164
+ },
2165
+ state: () => stateOf(ctx.open()),
2166
+ attrs: () => ({
2167
+ "data-slot": `dropdown-menu-content`,
2168
+ class: cn(DROPDOWN_MENU_CLASSES.content, local.class),
2169
+ ...rest
2170
+ }),
2171
+ setContent: (el) => {
2172
+ if (el) {
2173
+ presence.ref(el);
2174
+ noteLayerMount();
2175
+ callRef(local.ref, el);
2176
+ }
2177
+ },
2178
+ onDismiss: () => ctx.setOpen(false),
2179
+ get onKeyDown() {
2180
+ return local.onKeyDown;
2181
+ },
2182
+ get onEscapeKeyDown() {
2183
+ return local.onEscapeKeyDown;
2184
+ },
2185
+ get onFocusOutside() {
2186
+ return local.onFocusOutside;
2187
+ },
2188
+ onInteractOutside: (e) => {
2189
+ local.onInteractOutside?.(e);
2190
+ if (e.defaultPrevented) return;
2191
+ const original = e.detail.originalEvent;
2192
+ const ctrlLeftClick = original.button === 0 && original.ctrlKey === true;
2193
+ if (original.button === 2 || ctrlLeftClick) interactedOutside = true;
2194
+ },
2195
+ onCloseAutoFocus: (e) => {
2196
+ local.onCloseAutoFocus?.(e);
2197
+ if (e.defaultPrevented) return;
2198
+ if (!interactedOutside) ctx.trigger()?.focus();
2199
+ interactedOutside = false;
2200
+ e.preventDefault();
2201
+ },
2202
+ get children() {
2203
+ return local.children;
2204
+ }
2205
+ });
2206
+ }
2207
+ });
2208
+ }
2209
+ });
2210
+ }
2211
+ function DropdownMenuGroup(props) {
2212
+ return (() => {
2213
+ var _el$ = _tmpl$$1();
2214
+ spread(_el$, props, false, false);
2215
+ return _el$;
2216
+ })();
2217
+ }
2218
+ const insetAttr = (inset) => inset === void 0 ? void 0 : String(inset);
2219
+ function createItem(local, onSelect) {
2220
+ const root = useRoot(`DropdownMenuItem`);
2221
+ const row = createSelectable(() => local.disabled ?? false, (e) => onSelect(e), () => root.setOpen(false));
2222
+ const h = row.handlers;
2223
+ return {
2224
+ attrs: row.attrs,
2225
+ ref: mergeRefs(row.ref, local.ref),
2226
+ handlers: {
2227
+ onClick: composeHandlers(local.onClick, h.onClick),
2228
+ onPointerDown: composeHandlers(local.onPointerDown, h.onPointerDown, false),
2229
+ onPointerUp: composeHandlers(local.onPointerUp, h.onPointerUp),
2230
+ onPointerMove: composeHandlers(local.onPointerMove, h.onPointerMove),
2231
+ onPointerLeave: composeHandlers(local.onPointerLeave, h.onPointerLeave),
2232
+ onKeyDown: composeHandlers(local.onKeyDown, h.onKeyDown),
2233
+ onFocus: composeHandlers(local.onFocus, h.onFocus),
2234
+ onBlur: composeHandlers(local.onBlur, h.onBlur)
2235
+ }
2236
+ };
2237
+ }
2238
+ const ITEM_KEYS = [`disabled`, `onSelect`, `ref`, `onClick`, `onPointerDown`, `onPointerUp`, `onPointerMove`, `onPointerLeave`, `onKeyDown`, `onFocus`, `onBlur`];
2239
+ function DropdownMenuItem(props) {
2240
+ const [local, handlers, rest] = splitProps(props, [`class`, `inset`, `variant`], ITEM_KEYS);
2241
+ const item = createItem(handlers, (e) => handlers.onSelect?.(e));
2242
+ return (() => {
2243
+ var _el$2 = _tmpl$2$1();
2244
+ var _ref$2 = item.ref;
2245
+ typeof _ref$2 === "function" ? use(_ref$2, _el$2) : item.ref = _el$2;
2246
+ spread(_el$2, mergeProps(() => item.attrs(), {
2247
+ "data-slot": "dropdown-menu-item",
2248
+ get ["data-inset"]() {
2249
+ return insetAttr(local.inset);
2250
+ },
2251
+ get ["data-variant"]() {
2252
+ return local.variant ?? `default`;
2253
+ },
2254
+ get ["class"]() {
2255
+ return cn(DROPDOWN_MENU_CLASSES.item, local.class);
2256
+ }
2257
+ }, rest, () => item.handlers), false, false);
2258
+ return _el$2;
2259
+ })();
2260
+ }
2261
+ const checkedState = (c) => c === `indeterminate` ? `indeterminate` : c ? `checked` : `unchecked`;
2262
+ const IndicatorContext = createContext(() => false);
2263
+ function ItemIndicator(props) {
2264
+ const checked = useContext(IndicatorContext);
2265
+ return createComponent(Show, {
2266
+ get when() {
2267
+ return checked() === true || checked() === `indeterminate`;
2268
+ },
2269
+ get children() {
2270
+ var _el$3 = _tmpl$3();
2271
+ insert(_el$3, () => props.children);
2272
+ effect(() => setAttribute(_el$3, "data-state", checkedState(checked())));
2273
+ return _el$3;
2274
+ }
2275
+ });
2276
+ }
2277
+ function DropdownMenuCheckboxItem(props) {
2278
+ const [local, handlers, rest] = splitProps(props, [`class`, `children`, `checked`, `onCheckedChange`], ITEM_KEYS);
2279
+ const checked = () => local.checked ?? false;
2280
+ const item = createItem(handlers, (e) => {
2281
+ handlers.onSelect?.(e);
2282
+ const c = untrack(checked);
2283
+ local.onCheckedChange?.(c === `indeterminate` ? true : !c);
2284
+ });
2285
+ return createComponent(IndicatorContext.Provider, {
2286
+ value: checked,
2287
+ get children() {
2288
+ var _el$4 = _tmpl$4(), _el$5 = _el$4.firstChild;
2289
+ var _ref$3 = item.ref;
2290
+ typeof _ref$3 === "function" ? use(_ref$3, _el$4) : item.ref = _el$4;
2291
+ spread(_el$4, mergeProps({
2292
+ get ["aria-checked"]() {
2293
+ return memo(() => checked() === `indeterminate`)() ? `mixed` : checked() ? `true` : `false`;
2294
+ }
2295
+ }, () => item.attrs(), {
2296
+ "data-slot": "dropdown-menu-checkbox-item",
2297
+ get ["class"]() {
2298
+ return cn(DROPDOWN_MENU_CLASSES.checkItem, local.class);
2299
+ }
2300
+ }, rest, {
2301
+ get ["data-state"]() {
2302
+ return checkedState(checked());
2303
+ }
2304
+ }, () => item.handlers), false, true);
2305
+ insert(_el$5, createComponent(ItemIndicator, {
2306
+ get children() {
2307
+ return createComponent(PaintIcon, {
2308
+ icon: Check,
2309
+ get ["class"]() {
2310
+ return DROPDOWN_MENU_CLASSES.checkIcon;
2311
+ }
2312
+ });
2313
+ }
2314
+ }));
2315
+ insert(_el$4, () => local.children, null);
2316
+ effect(() => className(_el$5, DROPDOWN_MENU_CLASSES.itemIndicator));
2317
+ return _el$4;
2318
+ }
2319
+ });
2320
+ }
2321
+ const RadioGroupContext = createContext({
2322
+ value: () => void 0,
2323
+ onValueChange: () => {
2324
+ }
2325
+ });
2326
+ function DropdownMenuRadioGroup(props) {
2327
+ const [local, rest] = splitProps(props, [`value`, `onValueChange`]);
2328
+ return createComponent(RadioGroupContext.Provider, {
2329
+ value: {
2330
+ value: () => local.value,
2331
+ onValueChange: (v) => local.onValueChange?.(v)
2332
+ },
2333
+ get children() {
2334
+ var _el$6 = _tmpl$5();
2335
+ spread(_el$6, rest, false, false);
2336
+ return _el$6;
2337
+ }
2338
+ });
2339
+ }
2340
+ function DropdownMenuRadioItem(props) {
2341
+ const [local, handlers, rest] = splitProps(props, [`class`, `children`, `value`], ITEM_KEYS);
2342
+ const group = useContext(RadioGroupContext);
2343
+ const checked = () => local.value === group.value();
2344
+ const item = createItem(handlers, (e) => {
2345
+ handlers.onSelect?.(e);
2346
+ group.onValueChange(local.value);
2347
+ });
2348
+ return createComponent(IndicatorContext.Provider, {
2349
+ value: checked,
2350
+ get children() {
2351
+ var _el$7 = _tmpl$6(), _el$8 = _el$7.firstChild;
2352
+ var _ref$4 = item.ref;
2353
+ typeof _ref$4 === "function" ? use(_ref$4, _el$7) : item.ref = _el$7;
2354
+ spread(_el$7, mergeProps({
2355
+ get ["aria-checked"]() {
2356
+ return checked() ? `true` : `false`;
2357
+ }
2358
+ }, () => item.attrs(), {
2359
+ "data-slot": "dropdown-menu-radio-item",
2360
+ get ["class"]() {
2361
+ return cn(DROPDOWN_MENU_CLASSES.checkItem, local.class);
2362
+ }
2363
+ }, rest, {
2364
+ get ["data-state"]() {
2365
+ return checkedState(checked());
2366
+ }
2367
+ }, () => item.handlers), false, true);
2368
+ insert(_el$8, createComponent(ItemIndicator, {
2369
+ get children() {
2370
+ return createComponent(PaintIcon, {
2371
+ icon: Circle,
2372
+ get ["class"]() {
2373
+ return DROPDOWN_MENU_CLASSES.radioIcon;
2374
+ }
2375
+ });
2376
+ }
2377
+ }));
2378
+ insert(_el$7, () => local.children, null);
2379
+ effect(() => className(_el$8, DROPDOWN_MENU_CLASSES.itemIndicator));
2380
+ return _el$7;
2381
+ }
2382
+ });
2383
+ }
2384
+ function DropdownMenuLabel(props) {
2385
+ const [local, rest] = splitProps(props, [`class`, `inset`]);
2386
+ return (() => {
2387
+ var _el$9 = _tmpl$7();
2388
+ spread(_el$9, mergeProps({
2389
+ get ["data-inset"]() {
2390
+ return insetAttr(local.inset);
2391
+ },
2392
+ get ["class"]() {
2393
+ return cn(DROPDOWN_MENU_CLASSES.label, local.class);
2394
+ }
2395
+ }, rest), false, false);
2396
+ return _el$9;
2397
+ })();
2398
+ }
2399
+ function DropdownMenuSeparator(props) {
2400
+ const [local, rest] = splitProps(props, [`class`]);
2401
+ return (() => {
2402
+ var _el$0 = _tmpl$8();
2403
+ spread(_el$0, mergeProps({
2404
+ get ["class"]() {
2405
+ return cn(DROPDOWN_MENU_CLASSES.separator, local.class);
2406
+ }
2407
+ }, rest), false, false);
2408
+ return _el$0;
2409
+ })();
2410
+ }
2411
+ function DropdownMenuShortcut(props) {
2412
+ const [local, rest] = splitProps(props, [`class`]);
2413
+ return (() => {
2414
+ var _el$1 = _tmpl$9();
2415
+ spread(_el$1, mergeProps({
2416
+ get ["class"]() {
2417
+ return cn(DROPDOWN_MENU_CLASSES.shortcut, local.class);
2418
+ }
2419
+ }, rest), false, false);
2420
+ return _el$1;
2421
+ })();
2422
+ }
2423
+ const SubContext = createContext();
2424
+ const useSub = (part) => {
2425
+ const ctx = useContext(SubContext);
2426
+ if (!ctx) throw new Error(`\`${part}\` must be used within \`DropdownMenuSub\``);
2427
+ return ctx;
2428
+ };
2429
+ function DropdownMenuSub(props) {
2430
+ const parentOpen = useContext(LevelOpenContext);
2431
+ const [open, setOpen] = createOpenState({
2432
+ open: () => props.open,
2433
+ defaultOpen: props.defaultOpen,
2434
+ onOpenChange: () => props.onOpenChange
2435
+ });
2436
+ const [trigger, setTrigger] = createSignal();
2437
+ const [content, setContent] = createSignal();
2438
+ createEffect(on(parentOpen, (o) => o === false && setOpen(false)));
2439
+ onCleanup(() => setOpen(false));
2440
+ const value = {
2441
+ open,
2442
+ setOpen,
2443
+ triggerId: `radix-${createId()}`,
2444
+ contentId: `radix-${createId()}`,
2445
+ trigger,
2446
+ setTrigger,
2447
+ content,
2448
+ setContent
2449
+ };
2450
+ return createComponent(SubContext.Provider, {
2451
+ value,
2452
+ get children() {
2453
+ return createComponent(LevelOpenContext.Provider, {
2454
+ value: open,
2455
+ get children() {
2456
+ return props.children;
2457
+ }
2458
+ });
2459
+ }
2460
+ });
2461
+ }
2462
+ function DropdownMenuSubTrigger(props) {
2463
+ const root = useRoot(`DropdownMenuSubTrigger`);
2464
+ const sub = useSub(`DropdownMenuSubTrigger`);
2465
+ const [local, rest] = splitProps(props, [`class`, `inset`, `variant`, `children`, `disabled`, `ref`, `onClick`, `onPointerMove`, `onPointerLeave`, `onKeyDown`, `onFocus`, `onBlur`]);
2466
+ const disabled = () => local.disabled ?? false;
2467
+ const row = createMenuRow(disabled);
2468
+ let openTimer;
2469
+ let graceTimer;
2470
+ const clearOpenTimer = () => {
2471
+ clearTimeout(openTimer);
2472
+ openTimer = void 0;
2473
+ };
2474
+ onCleanup(() => {
2475
+ clearOpenTimer();
2476
+ clearTimeout(graceTimer);
2477
+ row.level.setGrace(null);
2478
+ });
2479
+ const openKey = () => root.dir() === `rtl` ? `ArrowLeft` : `ArrowRight`;
2480
+ return (() => {
2481
+ var _el$10 = _tmpl$0();
2482
+ var _ref$5 = mergeRefs(row.ref, sub.setTrigger, local.ref);
2483
+ typeof _ref$5 === "function" && use(_ref$5, _el$10);
2484
+ spread(_el$10, mergeProps({
2485
+ get id() {
2486
+ return sub.triggerId;
2487
+ },
2488
+ get ["aria-expanded"]() {
2489
+ return sub.open() ? `true` : `false`;
2490
+ },
2491
+ get ["aria-controls"]() {
2492
+ return sub.contentId;
2493
+ },
2494
+ get ["data-state"]() {
2495
+ return stateOf(sub.open());
2496
+ }
2497
+ }, () => row.attrs(), {
2498
+ "data-slot": "dropdown-menu-sub-trigger",
2499
+ get ["data-inset"]() {
2500
+ return insetAttr(local.inset);
2501
+ },
2502
+ get ["data-variant"]() {
2503
+ return local.variant ?? `default`;
2504
+ },
2505
+ get ["class"]() {
2506
+ return cn(DROPDOWN_MENU_CLASSES.subTrigger, local.class);
2507
+ }
2508
+ }, rest, {
2509
+ get onClick() {
2510
+ return composeHandlers(local.onClick, (e) => {
2511
+ if (untrack(disabled)) return;
2512
+ e.currentTarget.focus();
2513
+ if (!untrack(sub.open)) sub.setOpen(true);
2514
+ });
2515
+ },
2516
+ get onPointerMove() {
2517
+ return composeHandlers(local.onPointerMove, (e) => {
2518
+ if (e.pointerType !== `mouse`) return;
2519
+ if (row.level.onItemEnter(e)) return;
2520
+ if (!untrack(disabled) && !untrack(sub.open) && !openTimer) {
2521
+ row.level.setGrace(null);
2522
+ openTimer = setTimeout(() => {
2523
+ sub.setOpen(true);
2524
+ clearOpenTimer();
2525
+ }, 100);
2526
+ }
2527
+ row.handlers.onPointerMove(e);
2528
+ });
2529
+ },
2530
+ get onPointerLeave() {
2531
+ return composeHandlers(local.onPointerLeave, (e) => {
2532
+ if (e.pointerType !== `mouse`) return;
2533
+ clearOpenTimer();
2534
+ const content = sub.content();
2535
+ const rect = content?.getBoundingClientRect();
2536
+ if (content && rect) {
2537
+ const side = content.dataset.side;
2538
+ const right = side === `right`;
2539
+ const bleed = right ? -5 : 5;
2540
+ const near = rect[right ? `left` : `right`];
2541
+ const far = rect[right ? `right` : `left`];
2542
+ row.level.setGrace({
2543
+ area: [{
2544
+ x: e.clientX + bleed,
2545
+ y: e.clientY
2546
+ }, {
2547
+ x: near,
2548
+ y: rect.top
2549
+ }, {
2550
+ x: far,
2551
+ y: rect.top
2552
+ }, {
2553
+ x: far,
2554
+ y: rect.bottom
2555
+ }, {
2556
+ x: near,
2557
+ y: rect.bottom
2558
+ }],
2559
+ side
2560
+ });
2561
+ clearTimeout(graceTimer);
2562
+ graceTimer = setTimeout(() => row.level.setGrace(null), 300);
2563
+ } else {
2564
+ if (row.level.onTriggerLeave(e)) return;
2565
+ row.level.setGrace(null);
2566
+ row.handlers.onPointerLeave(e);
2567
+ }
2568
+ });
2569
+ },
2570
+ get onKeyDown() {
2571
+ return composeHandlers(local.onKeyDown, (e) => {
2572
+ const typingAhead = row.level.search() !== ``;
2573
+ if (untrack(disabled) || typingAhead && e.key === ` `) return;
2574
+ if ([`Enter`, ` `, openKey()].includes(e.key)) {
2575
+ sub.setOpen(true);
2576
+ sub.content()?.focus();
2577
+ e.preventDefault();
2578
+ return;
2579
+ }
2580
+ row.handlers.onKeyDown(e);
2581
+ });
2582
+ },
2583
+ get onFocus() {
2584
+ return composeHandlers(local.onFocus, row.handlers.onFocus);
2585
+ },
2586
+ get onBlur() {
2587
+ return composeHandlers(local.onBlur, row.handlers.onBlur);
2588
+ }
2589
+ }), false, true);
2590
+ insert(_el$10, () => local.children, null);
2591
+ insert(_el$10, createComponent(PaintIcon, {
2592
+ icon: ChevronRight,
2593
+ get ["class"]() {
2594
+ return DROPDOWN_MENU_CLASSES.subChevron;
2595
+ }
2596
+ }), null);
2597
+ return _el$10;
2598
+ })();
2599
+ }
2600
+ function DropdownMenuSubContent(props) {
2601
+ const root = useRoot(`DropdownMenuSubContent`);
2602
+ const sub = useSub(`DropdownMenuSubContent`);
2603
+ const [local, rest] = splitProps(props, CONTENT_KEYS);
2604
+ const presence = createPresence(sub.open);
2605
+ const closeKey = () => root.dir() === `rtl` ? `ArrowRight` : `ArrowLeft`;
2606
+ return createComponent(DropdownMenuPortal, {
2607
+ get container() {
2608
+ return local.container;
2609
+ },
2610
+ get children() {
2611
+ return createComponent(Show, {
2612
+ get when() {
2613
+ return presence.mounted();
2614
+ },
2615
+ children: (_) => {
2616
+ const lag = layerMountedThisTask();
2617
+ return createComponent(MenuContent, {
2618
+ get anchor() {
2619
+ return sub.trigger();
2620
+ },
2621
+ get side() {
2622
+ return root.dir() === `rtl` ? `left` : `right`;
2623
+ },
2624
+ align: "start",
2625
+ get sideOffset() {
2626
+ return local.sideOffset ?? 0;
2627
+ },
2628
+ get alignOffset() {
2629
+ return local.alignOffset;
2630
+ },
2631
+ get collisionPadding() {
2632
+ return local.collisionPadding ?? 0;
2633
+ },
2634
+ get dir() {
2635
+ return root.dir();
2636
+ },
2637
+ kind: "dropdown-menu",
2638
+ lagParentLayer: lag,
2639
+ root: false,
2640
+ get id() {
2641
+ return sub.contentId;
2642
+ },
2643
+ get labelledBy() {
2644
+ return sub.triggerId;
2645
+ },
2646
+ state: () => stateOf(sub.open()),
2647
+ attrs: () => ({
2648
+ "data-slot": `dropdown-menu-sub-content`,
2649
+ class: cn(DROPDOWN_MENU_CLASSES.subContent, local.class),
2650
+ ...rest
2651
+ }),
2652
+ setContent: (el) => {
2653
+ sub.setContent(el);
2654
+ if (el) {
2655
+ presence.ref(el);
2656
+ noteLayerMount();
2657
+ callRef(local.ref, el);
2658
+ }
2659
+ },
2660
+ onDismiss: () => {
2661
+ },
2662
+ onEscapeKeyDown: (e) => {
2663
+ local.onEscapeKeyDown?.(e);
2664
+ if (e.defaultPrevented) return;
2665
+ root.setOpen(false);
2666
+ e.preventDefault();
2667
+ },
2668
+ onFocusOutside: (e) => {
2669
+ local.onFocusOutside?.(e);
2670
+ if (e.defaultPrevented) return;
2671
+ if (e.target !== sub.trigger()) sub.setOpen(false);
2672
+ },
2673
+ get onInteractOutside() {
2674
+ return local.onInteractOutside;
2675
+ },
2676
+ onCloseAutoFocus: (e) => e.preventDefault(),
2677
+ onKeyDown: (e) => {
2678
+ local.onKeyDown?.(e);
2679
+ if (e.defaultPrevented) return;
2680
+ if (sub.content()?.contains(e.target) && e.key === closeKey()) {
2681
+ sub.setOpen(false);
2682
+ sub.trigger()?.focus();
2683
+ e.preventDefault();
2684
+ }
2685
+ },
2686
+ get children() {
2687
+ return local.children;
2688
+ }
2689
+ });
2690
+ }
2691
+ });
2692
+ }
2693
+ });
2694
+ }
2695
+ function createMediaQuery(query) {
2696
+ if (typeof window === `undefined` || typeof window.matchMedia !== `function`) return () => false;
2697
+ const mql = window.matchMedia(query);
2698
+ const [matches, setMatches] = createSignal(mql.matches);
2699
+ const onChange = () => setMatches(window.matchMedia(query).matches);
2700
+ mql.addEventListener(`change`, onChange);
2701
+ onCleanup(() => mql.removeEventListener(`change`, onChange));
2702
+ return matches;
2703
+ }
2704
+ var _tmpl$ = /* @__PURE__ */ template(`<div data-slot=zoomable-image-pill role=toolbar><span aria-hidden=true data-slot=zoomable-image-divider>`), _tmpl$2 = /* @__PURE__ */ template(`<div data-slot=zoomable-image role=group tabindex=0><img data-slot=zoomable-image-image loading=lazy decoding=async>`, true, false, false);
2705
+ const ZOOM_MATH = {
2706
+ ZOOM,
2707
+ zoomIsTall,
2708
+ zoomRestView,
2709
+ zoomClamp,
2710
+ zoomAtRest,
2711
+ zoomTo,
2712
+ zoomCentre,
2713
+ zoomWheel,
2714
+ zoomScroll,
2715
+ zoomStep,
2716
+ zoomDoubleTap,
2717
+ zoomKey,
2718
+ zoomDrag,
2719
+ zoomPinch,
2720
+ zoomMomentum,
2721
+ zoomMomentumActive,
2722
+ zoomPanRoom,
2723
+ zoomResize,
2724
+ zoomPercent,
2725
+ zoomMenu,
2726
+ zoomBounds
2727
+ };
2728
+ const REST_PILL = {
2729
+ percent: zoomPercent(1),
2730
+ atMin: false,
2731
+ atMax: false,
2732
+ atRest: true
2733
+ };
2734
+ function createZoomableImage(o) {
2735
+ let root;
2736
+ let image;
2737
+ let pillEl;
2738
+ let controller = null;
2739
+ const [loaded, setLoaded] = createSignal(null);
2740
+ const [pill, setPill] = createSignal(REST_PILL);
2741
+ const [pillVisible, setPillVisible] = createSignal(true);
2742
+ const declared = () => zoomDeclaredSize(o.naturalWidth(), o.naturalHeight());
2743
+ const natural = () => declared() ?? loaded();
2744
+ onMount(() => {
2745
+ if (!root || !image) return;
2746
+ const c = createZoomController({
2747
+ math: ZOOM_MATH,
2748
+ root,
2749
+ image,
2750
+ pill: () => pillEl ?? null,
2751
+ natural,
2752
+ initial: o.initial,
2753
+ maxScale: o.maxScale,
2754
+ boundScale: o.scale,
2755
+ transition: o.transition,
2756
+ autoHide: () => o.controls() === `auto`,
2757
+ onPill: (p) => setPill(p),
2758
+ onPillVisible: setPillVisible,
2759
+ onZoom: (scale, atFit) => o.onZoom?.(scale, atFit),
2760
+ onTap: () => o.onTap?.()
2761
+ });
2762
+ controller = c;
2763
+ onCleanup(() => {
2764
+ c.destroy();
2765
+ controller = null;
2766
+ });
2767
+ });
2768
+ createEffect(on(o.src, () => setLoaded(null), {
2769
+ defer: true
2770
+ }));
2771
+ createEffect(on([o.src, () => natural()?.width, () => natural()?.height, o.initial, o.maxScale], () => controller?.reset(), {
2772
+ defer: true
2773
+ }));
2774
+ createEffect(on(o.scale, () => controller?.syncScale(), {
2775
+ defer: true
2776
+ }));
2777
+ const onImageLoad = (e) => {
2778
+ const img = e.currentTarget;
2779
+ if (!declared() && img.naturalWidth > 0 && img.naturalHeight > 0) setLoaded({
2780
+ width: img.naturalWidth,
2781
+ height: img.naturalHeight
2782
+ });
2783
+ };
2784
+ const menuItems = (fitLabel) => {
2785
+ const f = controller?.frame();
2786
+ return controller && f ? zoomMenu(controller.view(), f, fitLabel) : [];
2787
+ };
2788
+ return {
2789
+ rootRef: (el) => root = el,
2790
+ imageRef: (el) => image = el,
2791
+ pillRef: (el) => pillEl = el,
2792
+ controller: () => controller,
2793
+ natural,
2794
+ pill,
2795
+ pillVisible,
2796
+ onImageLoad,
2797
+ menuItems
2798
+ };
2799
+ }
2800
+ const ZOOMABLE_IMAGE_STRINGS = {
2801
+ zoomIn: `Zoom in`,
2802
+ zoomOut: `Zoom out`,
2803
+ zoomToFit: `Zoom to fit`,
2804
+ zoomLevel: `Zoom level`,
2805
+ zoomFit: `Fit`
2806
+ };
2807
+ function ZoomableImage(props) {
2808
+ const [local, rest] = splitProps(props, [`src`, `alt`, `naturalWidth`, `naturalHeight`, `initial`, `maxScale`, `controls`, `scale`, `onScaleChange`, `onZoom`, `onTap`, `strings`, `class`, `style`]);
2809
+ const reducedMotion = createMediaQuery(`(prefers-reduced-motion: reduce)`);
2810
+ const t = () => ({
2811
+ ...ZOOMABLE_IMAGE_STRINGS,
2812
+ ...local.strings
2813
+ });
2814
+ const controls = () => local.controls ?? `auto`;
2815
+ const zoom = createZoomableImage({
2816
+ src: () => local.src,
2817
+ naturalWidth: () => local.naturalWidth,
2818
+ naturalHeight: () => local.naturalHeight,
2819
+ initial: () => local.initial ?? `auto`,
2820
+ maxScale: () => local.maxScale,
2821
+ scale: () => local.scale,
2822
+ controls,
2823
+ transition: () => reducedMotion() ? null : ZOOMABLE_IMAGE_TRANSITION,
2824
+ onZoom: (s, atFit) => {
2825
+ local.onScaleChange?.(s);
2826
+ local.onZoom?.({
2827
+ scale: s,
2828
+ atFit
2829
+ });
2830
+ },
2831
+ onTap: () => local.onTap?.()
2832
+ });
2833
+ const [menuOpen, setMenuOpen] = createSignal(false);
2834
+ createEffect(on(menuOpen, (open) => zoom.controller()?.holdPill(open), {
2835
+ defer: true
2836
+ }));
2837
+ const rootStyle = () => {
2838
+ const aspect = zoomBoxAspect(ZOOM_MATH, zoom.natural(), local.style?.height !== void 0);
2839
+ return css({
2840
+ ...aspect !== null ? {
2841
+ aspectRatio: String(aspect)
2842
+ } : {},
2843
+ ...local.style
2844
+ });
2845
+ };
2846
+ return (() => {
2847
+ var _el$ = _tmpl$2(), _el$2 = _el$.firstChild;
2848
+ var _ref$ = zoom.rootRef;
2849
+ typeof _ref$ === "function" ? use(_ref$, _el$) : zoom.rootRef = _el$;
2850
+ spread(_el$, mergeProps({
2851
+ get ["aria-label"]() {
2852
+ return local.alt || void 0;
2853
+ },
2854
+ get ["class"]() {
2855
+ return cn(ZOOMABLE_IMAGE_CLASSES.root, local.class);
2856
+ },
2857
+ get style() {
2858
+ return rootStyle();
2859
+ }
2860
+ }, rest), false, true);
2861
+ addEventListener(_el$2, "load", zoom.onImageLoad);
2862
+ var _ref$2 = zoom.imageRef;
2863
+ typeof _ref$2 === "function" ? use(_ref$2, _el$2) : zoom.imageRef = _el$2;
2864
+ setAttribute(_el$2, "draggable", false);
2865
+ insert(_el$, createComponent(Show, {
2866
+ get when() {
2867
+ return controls() !== `none`;
2868
+ },
2869
+ get children() {
2870
+ var _el$3 = _tmpl$(), _el$4 = _el$3.firstChild;
2871
+ var _ref$3 = zoom.pillRef;
2872
+ typeof _ref$3 === "function" ? use(_ref$3, _el$3) : zoom.pillRef = _el$3;
2873
+ insert(_el$3, createComponent(Button, {
2874
+ type: "button",
2875
+ variant: "ghost",
2876
+ size: "icon-sm",
2877
+ get ["class"]() {
2878
+ return ZOOMABLE_IMAGE_CLASSES.button;
2879
+ },
2880
+ get ["aria-label"]() {
2881
+ return t().zoomOut;
2882
+ },
2883
+ get disabled() {
2884
+ return zoom.pill().atMin;
2885
+ },
2886
+ onClick: () => zoom.controller()?.step(-1),
2887
+ get children() {
2888
+ return createComponent(PaintIcon, {
2889
+ icon: Minus
2890
+ });
2891
+ }
2892
+ }), _el$4);
2893
+ insert(_el$3, createComponent(DropdownMenu, {
2894
+ get open() {
2895
+ return menuOpen();
2896
+ },
2897
+ onOpenChange: setMenuOpen,
2898
+ get children() {
2899
+ return [createComponent(DropdownMenuTrigger, {
2900
+ as: Button,
2901
+ type: "button",
2902
+ variant: "ghost",
2903
+ size: "sm",
2904
+ get ["class"]() {
2905
+ return ZOOMABLE_IMAGE_CLASSES.percent;
2906
+ },
2907
+ get ["aria-label"]() {
2908
+ return t().zoomLevel;
2909
+ },
2910
+ get children() {
2911
+ return zoom.pill().percent;
2912
+ }
2913
+ }), createComponent(DropdownMenuContent, {
2914
+ side: "top",
2915
+ align: "center",
2916
+ get children() {
2917
+ return createComponent(For, {
2918
+ get each() {
2919
+ return memo(() => !!menuOpen())() ? zoom.menuItems(t().zoomFit) : [];
2920
+ },
2921
+ children: (item) => createComponent(DropdownMenuCheckboxItem, {
2922
+ get checked() {
2923
+ return item.checked;
2924
+ },
2925
+ onSelect: () => {
2926
+ const c = zoom.controller();
2927
+ if (item.scale === null) c?.rest();
2928
+ else c?.zoomScale(item.scale);
2929
+ },
2930
+ get children() {
2931
+ return item.label;
2932
+ }
2933
+ })
2934
+ });
2935
+ }
2936
+ })];
2937
+ }
2938
+ }), _el$4);
2939
+ insert(_el$3, createComponent(Button, {
2940
+ type: "button",
2941
+ variant: "ghost",
2942
+ size: "icon-sm",
2943
+ get ["class"]() {
2944
+ return ZOOMABLE_IMAGE_CLASSES.button;
2945
+ },
2946
+ get ["aria-label"]() {
2947
+ return t().zoomIn;
2948
+ },
2949
+ get disabled() {
2950
+ return zoom.pill().atMax;
2951
+ },
2952
+ onClick: () => zoom.controller()?.step(1),
2953
+ get children() {
2954
+ return createComponent(PaintIcon, {
2955
+ icon: Plus
2956
+ });
2957
+ }
2958
+ }), _el$4);
2959
+ insert(_el$3, createComponent(Button, {
2960
+ type: "button",
2961
+ variant: "ghost",
2962
+ size: "icon-sm",
2963
+ get ["class"]() {
2964
+ return ZOOMABLE_IMAGE_CLASSES.button;
2965
+ },
2966
+ get ["aria-label"]() {
2967
+ return t().zoomToFit;
2968
+ },
2969
+ get ["aria-pressed"]() {
2970
+ return zoom.pill().atRest ? `true` : `false`;
2971
+ },
2972
+ onClick: () => zoom.controller()?.rest(),
2973
+ get children() {
2974
+ return createComponent(PaintIcon, {
2975
+ icon: Maximize2
2976
+ });
2977
+ }
2978
+ }), null);
2979
+ effect((_p$) => {
2980
+ var _v$ = zoom.pillVisible() ? `open` : `closed`, _v$2 = cn(ZOOMABLE_IMAGE_CLASSES.pill, !zoom.pillVisible() && ZOOMABLE_IMAGE_CLASSES.pillHidden), _v$3 = ZOOMABLE_IMAGE_CLASSES.divider;
2981
+ _v$ !== _p$.e && setAttribute(_el$3, "data-state", _p$.e = _v$);
2982
+ _v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
2983
+ _v$3 !== _p$.a && className(_el$4, _p$.a = _v$3);
2984
+ return _p$;
2985
+ }, {
2986
+ e: void 0,
2987
+ t: void 0,
2988
+ a: void 0
2989
+ });
2990
+ return _el$3;
2991
+ }
2992
+ }), null);
2993
+ effect((_p$) => {
2994
+ var _v$4 = local.src || void 0, _v$5 = local.alt, _v$6 = ZOOMABLE_IMAGE_CLASSES.image, _v$7 = css(zoomImageStyle(zoom.natural()));
2995
+ _v$4 !== _p$.e && setAttribute(_el$2, "src", _p$.e = _v$4);
2996
+ _v$5 !== _p$.t && setAttribute(_el$2, "alt", _p$.t = _v$5);
2997
+ _v$6 !== _p$.a && className(_el$2, _p$.a = _v$6);
2998
+ _p$.o = style(_el$2, _v$7, _p$.o);
2999
+ return _p$;
3000
+ }, {
3001
+ e: void 0,
3002
+ t: void 0,
3003
+ a: void 0,
3004
+ o: void 0
3005
+ });
3006
+ return _el$;
3007
+ })();
3008
+ }
1690
3009
  export {
3010
+ DialogOverlayPart as $,
1691
3011
  findNextItem as A,
1692
3012
  BubbleCheck as B,
1693
3013
  CHROME as C,
@@ -1695,25 +3015,65 @@ export {
1695
3015
  popperWrapper as E,
1696
3016
  mountIn as F,
1697
3017
  SELECTION_KEYS as G,
1698
- createMediaQuery as H,
3018
+ createZoomableImage as H,
1699
3019
  IconGlyph as I,
1700
- px as J,
3020
+ createMediaQuery$1 as J,
1701
3021
  KEY_INTENT as K,
1702
3022
  LayerPortal as L,
1703
3023
  MenuContent as M,
1704
3024
  NativeSelect as N,
1705
3025
  OPEN_KEYS as O,
1706
3026
  PaintIcon as P,
1707
- FALLBACK_ICONS as Q,
1708
- resolveIcon as R,
3027
+ px as Q,
3028
+ FALLBACK_ICONS as R,
1709
3029
  SliderBubble as S,
1710
- bubbleOnChange as T,
1711
- focusIntent as U,
3030
+ resolveIcon as T,
3031
+ DialogRoot as U,
1712
3032
  VisuallyHidden as V,
1713
- wrapArray as W,
1714
- styleWriter as X,
1715
- setChecked as Y,
3033
+ DialogClosePart as W,
3034
+ mergeRefs as X,
3035
+ DialogContentPart as Y,
3036
+ ZOOM_MATH as Z,
3037
+ DialogDescriptionPart as _,
1716
3038
  createElementSize$1 as a,
3039
+ DialogPortalPart as a0,
3040
+ DialogTitlePart as a1,
3041
+ DialogTriggerPart as a2,
3042
+ Button as a3,
3043
+ bubbleOnChange as a4,
3044
+ useDialogContext as a5,
3045
+ callRef as a6,
3046
+ createOpenState as a7,
3047
+ composeHandlers as a8,
3048
+ styleObject as a9,
3049
+ ZOOMABLE_IMAGE_STRINGS as aA,
3050
+ ZoomableImage as aB,
3051
+ layerPointerEvents as aa,
3052
+ noteLayerMount as ab,
3053
+ layerMountedThisTask as ac,
3054
+ stateOf as ad,
3055
+ createId as ae,
3056
+ callHandler as af,
3057
+ focusIntent as ag,
3058
+ wrapArray as ah,
3059
+ styleWriter as ai,
3060
+ setChecked as aj,
3061
+ createMediaQuery as ak,
3062
+ DropdownMenu as al,
3063
+ DropdownMenuCheckboxItem as am,
3064
+ DropdownMenuContent as an,
3065
+ DropdownMenuGroup as ao,
3066
+ DropdownMenuItem as ap,
3067
+ DropdownMenuLabel as aq,
3068
+ DropdownMenuPortal as ar,
3069
+ DropdownMenuRadioGroup as as,
3070
+ DropdownMenuRadioItem as at,
3071
+ DropdownMenuSeparator as au,
3072
+ DropdownMenuShortcut as av,
3073
+ DropdownMenuSub as aw,
3074
+ DropdownMenuSubContent as ax,
3075
+ DropdownMenuSubTrigger as ay,
3076
+ DropdownMenuTrigger as az,
1717
3077
  createListNavigation as b,
1718
3078
  css as c,
1719
3079
  createListNavigationSync as d,
@@ -1726,18 +3086,18 @@ export {
1726
3086
  Popper as k,
1727
3087
  bindStyle as l,
1728
3088
  LayerContext as m,
1729
- useKeyboardTracking as n,
3089
+ useFocusGuards as n,
1730
3090
  graceArea as o,
1731
3091
  createFocusScope as p,
1732
3092
  useScrollLock as q,
1733
3093
  rovingFocusFirst as r,
1734
3094
  useModalEffects as s,
1735
3095
  transformOrigin as t,
1736
- useFocusGuards as u,
3096
+ useKeyboardTracking as u,
1737
3097
  createMenuRow as v,
1738
3098
  createSelectable as w,
1739
3099
  popperContentStyle as x,
1740
3100
  inPolygon as y,
1741
3101
  radixTypeahead as z
1742
3102
  };
1743
- //# sourceMappingURL=image-loading-status--T9ny7b0.js.map
3103
+ //# sourceMappingURL=zoomable-image-CmoMEUF6.js.map