overflow-toolbar 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -34
- package/dist/components/MuiOverflow/MuiOverflow.js +3 -2
- package/dist/components/MuiOverflow/MuiOverflow.js.map +1 -1
- package/dist/components/MuiOverflow/MuiOverflowItem.d.ts +6 -6
- package/dist/components/MuiOverflow/MuiOverflowItem.d.ts.map +1 -1
- package/dist/components/MuiOverflow/MuiOverflowItem.js +9 -8
- package/dist/components/MuiOverflow/MuiOverflowItem.js.map +1 -1
- package/dist/components/MuiOverflow/MuiOverflowMenu.d.ts +4 -4
- package/dist/components/MuiOverflow/MuiOverflowMenu.d.ts.map +1 -1
- package/dist/components/MuiOverflow/MuiOverflowMenu.js +8 -7
- package/dist/components/MuiOverflow/MuiOverflowMenu.js.map +1 -1
- package/dist/components/MuiOverflow/index.d.ts +1 -0
- package/dist/components/MuiOverflow/index.d.ts.map +1 -1
- package/dist/components/NoFrameworkOverflow/NoFrameworkOverflow.d.ts +3 -0
- package/dist/components/NoFrameworkOverflow/NoFrameworkOverflow.d.ts.map +1 -1
- package/dist/components/NoFrameworkOverflow/NoFrameworkOverflow.js +21 -17
- package/dist/components/NoFrameworkOverflow/NoFrameworkOverflow.js.map +1 -1
- package/dist/components/NoFrameworkOverflow/index.d.ts +2 -0
- package/dist/components/NoFrameworkOverflow/index.d.ts.map +1 -1
- package/dist/components/NoFrameworkOverflow/noframework.css +1 -110
- package/dist/components/Overflow/Overflow.css +1 -1
- package/dist/components/Overflow/Overflow.d.ts +8 -1
- package/dist/components/Overflow/Overflow.d.ts.map +1 -1
- package/dist/components/Overflow/Overflow.js +32 -32
- package/dist/components/Overflow/Overflow.js.map +1 -1
- package/dist/components/Overflow/OverflowController.d.ts +2 -1
- package/dist/components/Overflow/OverflowController.d.ts.map +1 -1
- package/dist/components/Overflow/OverflowController.js +44 -40
- package/dist/components/Overflow/OverflowController.js.map +1 -1
- package/dist/components/Overflow/OverflowItem.d.ts +10 -6
- package/dist/components/Overflow/OverflowItem.d.ts.map +1 -1
- package/dist/components/Overflow/OverflowItem.js +20 -11
- package/dist/components/Overflow/OverflowItem.js.map +1 -1
- package/dist/components/Overflow/OverflowMenu.d.ts +12 -4
- package/dist/components/Overflow/OverflowMenu.d.ts.map +1 -1
- package/dist/components/Overflow/OverflowMenu.js +37 -30
- package/dist/components/Overflow/OverflowMenu.js.map +1 -1
- package/dist/components/Overflow/index.d.ts +1 -0
- package/dist/components/Overflow/index.d.ts.map +1 -1
- package/dist/components/Overflow/overflowSteps.d.ts +10 -6
- package/dist/components/Overflow/overflowSteps.d.ts.map +1 -1
- package/dist/components/Overflow/overflowSteps.js +34 -23
- package/dist/components/Overflow/overflowSteps.js.map +1 -1
- package/dist/components/Overflow/useResizer.d.ts.map +1 -1
- package/dist/components/Overflow/useResizer.js +5 -3
- package/dist/components/Overflow/useResizer.js.map +1 -1
- package/dist/components/RxOverflow/RxOverflow.d.ts +0 -1
- package/dist/components/RxOverflow/RxOverflow.d.ts.map +1 -1
- package/dist/components/RxOverflow/RxOverflow.js +1 -1
- package/dist/components/RxOverflow/RxOverflow.js.map +1 -1
- package/dist/components/RxOverflow/RxOverflowItem.d.ts +6 -6
- package/dist/components/RxOverflow/RxOverflowItem.d.ts.map +1 -1
- package/dist/components/RxOverflow/RxOverflowItem.js +7 -6
- package/dist/components/RxOverflow/RxOverflowItem.js.map +1 -1
- package/dist/components/RxOverflow/RxOverflowMenu.d.ts +4 -4
- package/dist/components/RxOverflow/RxOverflowMenu.d.ts.map +1 -1
- package/dist/components/RxOverflow/RxOverflowMenu.js +19 -16
- package/dist/components/RxOverflow/RxOverflowMenu.js.map +1 -1
- package/dist/components/RxOverflow/index.d.ts +2 -0
- package/dist/components/RxOverflow/index.d.ts.map +1 -1
- package/dist/index.js +30 -27
- package/dist/index.js.map +1 -1
- package/dist/mui.js +7 -6
- package/dist/mui.js.map +1 -1
- package/dist/overflow.js +7 -6
- package/dist/overflow.js.map +1 -1
- package/dist/rx.js +10 -8
- package/dist/rx.js.map +1 -1
- package/dist/vanilla.js +4 -2
- package/dist/vanilla.js.map +1 -1
- package/package.json +2 -14
- package/styles.d.ts +0 -3
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
|
|
2
|
+
/** Props for the Overflow container component. */
|
|
3
3
|
export interface OverflowProps {
|
|
4
|
+
/** OverflowItem and OverflowMenu components. Must be direct children (no wrapper elements). */
|
|
4
5
|
children: ReactNode;
|
|
6
|
+
/** CSS class name for the container `<ul>`. */
|
|
5
7
|
className?: string;
|
|
8
|
+
/** Inline styles for the container `<ul>`. */
|
|
6
9
|
style?: React.CSSProperties;
|
|
10
|
+
/** When true, items collapse one at a time with tight spacing and grouped corners. */
|
|
7
11
|
compact?: boolean;
|
|
12
|
+
/** When true, items collapse from the right instead of the left. */
|
|
8
13
|
reverse?: boolean;
|
|
14
|
+
/** When true, all items with a `minStateWidth` snap to min state together, and all hideable items snap to hidden together. */
|
|
15
|
+
snap?: boolean;
|
|
9
16
|
}
|
|
10
17
|
declare const Overflow: import("react").ForwardRefExoticComponent<OverflowProps & import("react").RefAttributes<HTMLUListElement>>;
|
|
11
18
|
export default Overflow;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Overflow.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/Overflow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,SAAS,EAA8C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Overflow.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/Overflow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,SAAS,EAA8C,MAAM,OAAO,CAAC;AAUnI,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,+FAA+F;IAC/F,QAAQ,EAAE,SAAS,CAAC;IACpB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,sFAAsF;IACtF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8HAA8H;IAC9H,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,QAAA,MAAM,QAAQ,4GA0FZ,CAAC;AAEH,eAAe,QAAQ,CAAC"}
|
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
import { jsx as S } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, [f
|
|
22
|
-
|
|
2
|
+
import { forwardRef as N, useState as g, useRef as j, useMemo as d, Children as i, isValidElement as c, Fragment as A, useLayoutEffect as V } from "react";
|
|
3
|
+
import b from "./OverflowContext.js";
|
|
4
|
+
import { buildOrderedSteps as B, computeNextSteps as R, deriveHiddenMap as F } from "./overflowSteps.js";
|
|
5
|
+
import { useResizer as H } from "./useResizer.js";
|
|
6
|
+
const P = N(function({ children: r, className: M, style: W, compact: x, reverse: y, snap: u }, E) {
|
|
7
|
+
const [p, m] = g([]), O = j(null), s = E ?? O, f = d(() => i.toArray(
|
|
8
|
+
i.count(r) === 1 && c(r) && r.type === A ? r.props.children : r
|
|
9
|
+
), [r]), { orderedSteps: l, inMenuIds: a } = d(() => {
|
|
10
|
+
const e = [], t = /* @__PURE__ */ new Set(), v = /* @__PURE__ */ new Set();
|
|
11
|
+
return i.forEach(f, (o) => {
|
|
12
|
+
if (!c(o)) return;
|
|
13
|
+
const w = o.type.overflowRole;
|
|
14
|
+
w === "menu" ? i.forEach(o.props.children, (n) => {
|
|
15
|
+
c(n) && n.props.menuId && (t.add(n.props.menuId), e.includes(n.props.menuId) || e.push(n.props.menuId));
|
|
16
|
+
}) : w === "item" && o.props.menuId && (e.includes(o.props.menuId) || e.push(o.props.menuId), o.props.minStateWidth !== void 0 && v.add(o.props.menuId));
|
|
17
|
+
}), {
|
|
18
|
+
orderedSteps: B(e, t, v),
|
|
19
|
+
inMenuIds: t
|
|
20
|
+
};
|
|
21
|
+
}, [f]);
|
|
22
|
+
V(() => {
|
|
23
23
|
const e = s.current;
|
|
24
|
-
e &&
|
|
25
|
-
(
|
|
24
|
+
e && m(
|
|
25
|
+
(t) => R(t, e.scrollWidth, e.clientWidth, l)
|
|
26
26
|
);
|
|
27
|
-
}, [
|
|
27
|
+
}, [p, l, s]), H(s, () => {
|
|
28
28
|
const e = s.current;
|
|
29
|
-
e &&
|
|
30
|
-
(
|
|
29
|
+
e && m(
|
|
30
|
+
(t) => R(t, e.scrollWidth, e.clientWidth, l)
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
|
-
const
|
|
34
|
-
() => ({ hiddenMap:
|
|
35
|
-
[
|
|
36
|
-
),
|
|
37
|
-
return /* @__PURE__ */ S(
|
|
33
|
+
const I = d(() => F(p, u, a), [p, u, a]), h = d(
|
|
34
|
+
() => ({ hiddenMap: I }),
|
|
35
|
+
[I]
|
|
36
|
+
), z = ["overflow", x && "overflow-compact", y && "overflow-reverse", u && "overflow-snap", M].filter(Boolean).join(" ");
|
|
37
|
+
return /* @__PURE__ */ S(b, { value: h, children: /* @__PURE__ */ S("ul", { ref: s, className: z, style: { ...W, "--hiddenCount": p.length }, children: f }) });
|
|
38
38
|
});
|
|
39
39
|
export {
|
|
40
|
-
|
|
40
|
+
P as default
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=Overflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Overflow.js","sources":["../../../src/components/Overflow/Overflow.tsx"],"sourcesContent":["import { Children, Fragment, forwardRef, isValidElement, type ReactNode, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"Overflow.js","sources":["../../../src/components/Overflow/Overflow.tsx"],"sourcesContent":["import { Children, Fragment, forwardRef, isValidElement, type ReactNode, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport OverflowContext from './OverflowContext';\nimport { type AppliedStep, buildOrderedSteps, computeNextSteps, deriveHiddenMap } from './overflowSteps';\nimport { useResizer } from './useResizer';\n\n/** Shared type for components that declare an overflowRole ('item' | 'menu'). */\ninterface OverflowRoleComponent {\n overflowRole?: 'item' | 'menu';\n}\n\n/** Props for the Overflow container component. */\nexport interface OverflowProps {\n /** OverflowItem and OverflowMenu components. Must be direct children (no wrapper elements). */\n children: ReactNode;\n /** CSS class name for the container `<ul>`. */\n className?: string;\n /** Inline styles for the container `<ul>`. */\n style?: React.CSSProperties;\n /** When true, items collapse one at a time with tight spacing and grouped corners. */\n compact?: boolean;\n /** When true, items collapse from the right instead of the left. */\n reverse?: boolean;\n /** When true, all items with a `minStateWidth` snap to min state together, and all hideable items snap to hidden together. */\n snap?: boolean;\n}\n\nconst Overflow = forwardRef<HTMLUListElement, OverflowProps>(function Overflow({ children, className, style, compact, reverse, snap }, ref) {\n const [appliedSteps, setAppliedSteps] = useState<AppliedStep[]>([]);\n const internalRef = useRef<HTMLUListElement | null>(null);\n const listRef = (ref ?? internalRef) as React.RefObject<HTMLUListElement | null>;\n\n // Unwrap a single top-level Fragment so items work in Storybook args, etc.\n const resolvedChildren = useMemo(() => Children.toArray(\n Children.count(children) === 1 && isValidElement<{ children: ReactNode }>(children) && children.type === Fragment\n ? children.props.children\n : children,\n ), [children]);\n\n // Build ordered steps by scanning resolved children using overflowRole markers\n const { orderedSteps, inMenuIds } = useMemo(() => {\n const menuIds: string[] = [];\n const inMenuIds = new Set<string>();\n const minWidthMenuIds = new Set<string>();\n\n // Scan resolved children: collect menuIds, detect which are in an OverflowMenu\n Children.forEach(resolvedChildren, (child) => {\n if (!isValidElement<{ menuId?: string; children?: ReactNode; minStateWidth?: string }>(child)) return;\n\n const role = (child.type as OverflowRoleComponent).overflowRole;\n\n if (role === 'menu') {\n // Scan OverflowMenu children for menuIds that have menu representation\n Children.forEach(child.props.children, (menuChild) => {\n if (!isValidElement<{ menuId?: string }>(menuChild)) return;\n if (menuChild.props.menuId) {\n inMenuIds.add(menuChild.props.menuId);\n if (!menuIds.includes(menuChild.props.menuId)) {\n menuIds.push(menuChild.props.menuId);\n }\n }\n });\n } else if (role === 'item' && child.props.menuId) {\n if (!menuIds.includes(child.props.menuId)) {\n menuIds.push(child.props.menuId);\n }\n if (child.props.minStateWidth !== undefined) {\n minWidthMenuIds.add(child.props.menuId);\n }\n }\n });\n\n const orderedIds = menuIds;\n return {\n orderedSteps: buildOrderedSteps(orderedIds, inMenuIds, minWidthMenuIds),\n inMenuIds,\n };\n }, [resolvedChildren]);\n\n // Measure and collapse/expand after each render until stable.\n // useLayoutEffect runs synchronously after DOM mutations but before paint,\n // so all collapsing settles in one frame — no intermediate flicker.\n useLayoutEffect(() => {\n const element = listRef.current;\n if (!element) return;\n setAppliedSteps(prev =>\n computeNextSteps(prev, element.scrollWidth, element.clientWidth, orderedSteps)\n );\n }, [appliedSteps, orderedSteps, listRef]);\n\n // Re-measure when the container is externally resized (window resize, parent layout change)\n const onResize = () => {\n const element = listRef.current;\n if (!element) return;\n setAppliedSteps(prev =>\n computeNextSteps(prev, element.scrollWidth, element.clientWidth, orderedSteps)\n );\n };\n\n useResizer(listRef, onResize);\n\n const hiddenMap = useMemo(() => deriveHiddenMap(appliedSteps, snap, inMenuIds), [appliedSteps, snap, inMenuIds]);\n\n const ctxValue = useMemo(\n () => ({ hiddenMap }),\n [hiddenMap],\n );\n\n const classNames = ['overflow', compact && 'overflow-compact', reverse && 'overflow-reverse', snap && 'overflow-snap', className].filter(Boolean).join(' ');\n\n return (\n <OverflowContext value={ctxValue}>\n <ul ref={listRef} className={classNames} style={{ ...style, '--hiddenCount': appliedSteps.length } as React.CSSProperties}>\n {resolvedChildren}\n </ul>\n </OverflowContext>\n );\n});\n\nexport default Overflow;\n"],"names":["Overflow","forwardRef","children","className","style","compact","reverse","snap","ref","appliedSteps","setAppliedSteps","useState","internalRef","useRef","listRef","resolvedChildren","useMemo","Children","isValidElement","Fragment","orderedSteps","inMenuIds","menuIds","minWidthMenuIds","child","role","menuChild","buildOrderedSteps","useLayoutEffect","element","computeNextSteps","prev","useResizer","hiddenMap","deriveHiddenMap","ctxValue","classNames","OverflowContext","jsx"],"mappings":";;;;;AA0BA,MAAMA,IAAWC,EAA4C,SAAkB,EAAE,UAAAC,GAAU,WAAAC,GAAW,OAAAC,GAAO,SAAAC,GAAS,SAAAC,GAAS,MAAAC,EAAA,GAAQC,GAAK;AAC1I,QAAM,CAACC,GAAcC,CAAe,IAAIC,EAAwB,CAAA,CAAE,GAC5DC,IAAcC,EAAgC,IAAI,GAClDC,IAAWN,KAAOI,GAGlBG,IAAmBC,EAAQ,MAAMC,EAAS;AAAA,IAC9CA,EAAS,MAAMf,CAAQ,MAAM,KAAKgB,EAAwChB,CAAQ,KAAKA,EAAS,SAASiB,IACrGjB,EAAS,MAAM,WACfA;AAAA,EAAA,GACH,CAACA,CAAQ,CAAC,GAGP,EAAE,cAAAkB,GAAc,WAAAC,EAAA,IAAcL,EAAQ,MAAM;AAChD,UAAMM,IAAoB,CAAA,GACpBD,wBAAgB,IAAA,GAChBE,wBAAsB,IAAA;AAG5B,WAAAN,EAAS,QAAQF,GAAkB,CAACS,MAAU;AAC5C,UAAI,CAACN,EAAkFM,CAAK,EAAG;AAE/F,YAAMC,IAAQD,EAAM,KAA+B;AAEnD,MAAIC,MAAS,SAEXR,EAAS,QAAQO,EAAM,MAAM,UAAU,CAACE,MAAc;AACpD,QAAKR,EAAoCQ,CAAS,KAC9CA,EAAU,MAAM,WAClBL,EAAU,IAAIK,EAAU,MAAM,MAAM,GAC/BJ,EAAQ,SAASI,EAAU,MAAM,MAAM,KAC1CJ,EAAQ,KAAKI,EAAU,MAAM,MAAM;AAAA,MAGzC,CAAC,IACQD,MAAS,UAAUD,EAAM,MAAM,WACnCF,EAAQ,SAASE,EAAM,MAAM,MAAM,KACtCF,EAAQ,KAAKE,EAAM,MAAM,MAAM,GAE7BA,EAAM,MAAM,kBAAkB,UAChCD,EAAgB,IAAIC,EAAM,MAAM,MAAM;AAAA,IAG5C,CAAC,GAGM;AAAA,MACL,cAAcG,EAFGL,GAE2BD,GAAWE,CAAe;AAAA,MACtE,WAAAF;AAAAA,IAAA;AAAA,EAEJ,GAAG,CAACN,CAAgB,CAAC;AAKrB,EAAAa,EAAgB,MAAM;AACpB,UAAMC,IAAUf,EAAQ;AACxB,IAAKe,KACLnB;AAAA,MAAgB,OACdoB,EAAiBC,GAAMF,EAAQ,aAAaA,EAAQ,aAAaT,CAAY;AAAA,IAAA;AAAA,EAEjF,GAAG,CAACX,GAAcW,GAAcN,CAAO,CAAC,GAWxCkB,EAAWlB,GARM,MAAM;AACrB,UAAMe,IAAUf,EAAQ;AACxB,IAAKe,KACLnB;AAAA,MAAgB,OACdoB,EAAiBC,GAAMF,EAAQ,aAAaA,EAAQ,aAAaT,CAAY;AAAA,IAAA;AAAA,EAEjF,CAE4B;AAE5B,QAAMa,IAAYjB,EAAQ,MAAMkB,EAAgBzB,GAAcF,GAAMc,CAAS,GAAG,CAACZ,GAAcF,GAAMc,CAAS,CAAC,GAEzGc,IAAWnB;AAAA,IACf,OAAO,EAAE,WAAAiB,EAAA;AAAA,IACT,CAACA,CAAS;AAAA,EAAA,GAGNG,IAAa,CAAC,YAAY/B,KAAW,oBAAoBC,KAAW,oBAAoBC,KAAQ,iBAAiBJ,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE1J,2BACGkC,GAAA,EAAgB,OAAOF,GACtB,UAAA,gBAAAG,EAAC,MAAA,EAAG,KAAKxB,GAAS,WAAWsB,GAAY,OAAO,EAAE,GAAGhC,GAAO,iBAAiBK,EAAa,OAAA,GACvF,aACH,GACF;AAEJ,CAAC;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface ScannedItem {
|
|
2
2
|
el: HTMLElement;
|
|
3
3
|
buttonEl: HTMLElement | null;
|
|
4
|
-
|
|
4
|
+
menuId: string | undefined;
|
|
5
5
|
minStateWidth: string | undefined;
|
|
6
6
|
}
|
|
7
7
|
export interface ScannedMenu {
|
|
@@ -22,6 +22,7 @@ export interface OverflowHost {
|
|
|
22
22
|
scanChildren(): ScanResult;
|
|
23
23
|
isCompact(): boolean;
|
|
24
24
|
isReverse(): boolean;
|
|
25
|
+
isSnap(): boolean;
|
|
25
26
|
}
|
|
26
27
|
export declare class OverflowController {
|
|
27
28
|
private host;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverflowController.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowController.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,WAAW,CAAC;IAChB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,IAAI,WAAW,CAAC;IAC9B,YAAY,IAAI,UAAU,CAAC;IAC3B,SAAS,IAAI,OAAO,CAAC;IACrB,SAAS,IAAI,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"OverflowController.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowController.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,WAAW,CAAC;IAChB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,IAAI,WAAW,CAAC;IAC9B,YAAY,IAAI,UAAU,CAAC;IAC3B,SAAS,IAAI,OAAO,CAAC;IACrB,SAAS,IAAI,OAAO,CAAC;IACrB,MAAM,IAAI,OAAO,CAAC;CACnB;AAyBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,EAAE,CAA+B;IACzC,OAAO,CAAC,QAAQ,CAA2D;gBAE/D,IAAI,EAAE,YAAY;IAI9B,iDAAiD;IACjD,OAAO,IAAI,IAAI;IAKf,kDAAkD;IAClD,UAAU,IAAI,IAAI;IAMlB,oEAAoE;IACpE,MAAM,IAAI,IAAI;IAQd,OAAO,CAAC,IAAI;IAsBZ,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,UAAU;IAwDlB,OAAO,CAAC,cAAc;IAsCtB,OAAO,CAAC,mBAAmB;IAmD3B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,UAAU;CAkCnB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildOrderedSteps as u, computeNextSteps as
|
|
1
|
+
import { buildOrderedSteps as u, computeNextSteps as S, deriveHiddenMap as f } from "./overflowSteps.js";
|
|
2
2
|
const m = {
|
|
3
3
|
"font-size": "0",
|
|
4
4
|
"min-width": "100%",
|
|
@@ -13,7 +13,7 @@ const m = {
|
|
|
13
13
|
"border-top-right-radius",
|
|
14
14
|
"border-bottom-right-radius"
|
|
15
15
|
];
|
|
16
|
-
class
|
|
16
|
+
class v {
|
|
17
17
|
host;
|
|
18
18
|
orderedSteps = [];
|
|
19
19
|
appliedSteps = [];
|
|
@@ -38,10 +38,10 @@ class g {
|
|
|
38
38
|
scan() {
|
|
39
39
|
this.lastScan = this.host.scanChildren();
|
|
40
40
|
const t = [], e = /* @__PURE__ */ new Set();
|
|
41
|
-
for (const
|
|
42
|
-
|
|
43
|
-
const s = this.lastScan.menu?.inMenuIds ?? /* @__PURE__ */ new Set()
|
|
44
|
-
this.orderedSteps = u(
|
|
41
|
+
for (const r of this.lastScan.items)
|
|
42
|
+
r.menuId && (t.push(r.menuId), r.minStateWidth && e.add(r.menuId)), r.minStateWidth && (r.el.style.setProperty("--min-state-width", r.minStateWidth), r.el.setAttribute("data-can-min", ""));
|
|
43
|
+
const s = this.lastScan.menu?.inMenuIds ?? /* @__PURE__ */ new Set();
|
|
44
|
+
this.orderedSteps = u(t, s, e);
|
|
45
45
|
}
|
|
46
46
|
startObserver() {
|
|
47
47
|
this.ro?.disconnect();
|
|
@@ -51,67 +51,71 @@ class g {
|
|
|
51
51
|
onResize() {
|
|
52
52
|
const t = this.host.getContainerEl();
|
|
53
53
|
for (; ; ) {
|
|
54
|
-
const { scrollWidth: e, clientWidth: s } = t,
|
|
54
|
+
const { scrollWidth: e, clientWidth: s } = t, r = S(
|
|
55
55
|
this.appliedSteps,
|
|
56
56
|
e,
|
|
57
57
|
s,
|
|
58
58
|
this.orderedSteps
|
|
59
59
|
);
|
|
60
|
-
if (
|
|
61
|
-
this.appliedSteps =
|
|
60
|
+
if (r === this.appliedSteps) break;
|
|
61
|
+
this.appliedSteps = r, this.applyState();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
applyState() {
|
|
65
|
-
const t =
|
|
65
|
+
const t = this.host.isSnap(), e = f(
|
|
66
|
+
this.appliedSteps,
|
|
67
|
+
t,
|
|
68
|
+
this.lastScan.menu?.inMenuIds
|
|
69
|
+
);
|
|
66
70
|
this.host.getContainerEl().style.setProperty("--hiddenCount", String(this.appliedSteps.length));
|
|
67
|
-
const
|
|
68
|
-
let
|
|
71
|
+
const r = this.host.isCompact(), n = this.host.isReverse();
|
|
72
|
+
let l = !1;
|
|
69
73
|
const o = [];
|
|
70
|
-
for (const
|
|
71
|
-
const a =
|
|
72
|
-
|
|
74
|
+
for (const i of this.lastScan.items) {
|
|
75
|
+
const a = i.menuId ? e.get(i.menuId) ?? "visible" : "visible";
|
|
76
|
+
i.el.setAttribute("data-state", a), a === "visible" ? (i.el.style.removeProperty("display"), i.el.style.removeProperty("max-width"), i.el.style.removeProperty("overflow"), this.clearMinStyles(i.buttonEl), o.push(i)) : a === "min" ? (i.el.style.removeProperty("display"), i.el.style.setProperty("max-width", i.minStateWidth ?? "2.25rem"), i.el.style.setProperty("overflow", "hidden"), this.applyMinStyles(i.buttonEl), o.push(i)) : (i.el.style.setProperty("display", "none"), i.el.style.removeProperty("max-width"), i.el.style.removeProperty("overflow"), this.clearMinStyles(i.buttonEl), l = !0);
|
|
73
77
|
}
|
|
74
|
-
const { menu:
|
|
78
|
+
const { menu: p, menuFirst: d } = this.lastScan, h = this.applyMenuState(p, e, l);
|
|
75
79
|
this.applyCompactCorners(
|
|
76
80
|
o,
|
|
77
|
-
l,
|
|
78
81
|
p,
|
|
79
82
|
d,
|
|
80
|
-
|
|
83
|
+
h,
|
|
84
|
+
r,
|
|
81
85
|
n
|
|
82
86
|
);
|
|
83
87
|
}
|
|
84
88
|
applyMenuState(t, e, s) {
|
|
85
89
|
if (!t) return !1;
|
|
86
|
-
const
|
|
87
|
-
t.el.style.setProperty("display",
|
|
88
|
-
for (const
|
|
89
|
-
const
|
|
90
|
-
|
|
90
|
+
const r = s || t.hasMenuOnlyItems;
|
|
91
|
+
t.el.style.setProperty("display", r ? "" : "none"), t.el.setAttribute("data-state", r ? "visible" : "hidden"), t.triggerEl.setAttribute("aria-haspopup", "menu"), t.triggerEl.setAttribute("aria-expanded", String(r)), r ? this.applyMinStyles(t.triggerEl) : this.clearMinStyles(t.triggerEl);
|
|
92
|
+
for (const n of t.menuItemEls) {
|
|
93
|
+
const l = n.dataset.menuId;
|
|
94
|
+
l ? e.get(l) === "hidden" ? n.style.removeProperty("display") : n.style.setProperty("display", "none") : n.style.removeProperty("display");
|
|
91
95
|
}
|
|
92
|
-
return
|
|
96
|
+
return r;
|
|
93
97
|
}
|
|
94
|
-
applyCompactCorners(t, e, s,
|
|
95
|
-
for (let
|
|
96
|
-
const p = t[
|
|
98
|
+
applyCompactCorners(t, e, s, r, n, l) {
|
|
99
|
+
for (let o = 0; o < t.length; o++) {
|
|
100
|
+
const p = t[o].buttonEl;
|
|
97
101
|
if (!p) continue;
|
|
98
|
-
const d =
|
|
102
|
+
const d = o === 0, h = o === t.length - 1, i = s ? !d || r : !d, a = s ? !h : !h || r;
|
|
99
103
|
this.setCorners(
|
|
100
104
|
p,
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
n && (l ? a : i),
|
|
106
|
+
n && (l ? i : a)
|
|
103
107
|
);
|
|
104
108
|
}
|
|
105
109
|
if (e?.triggerEl) {
|
|
106
|
-
const
|
|
110
|
+
const o = r && t.length > 0;
|
|
107
111
|
s ? this.setCorners(
|
|
108
112
|
e.triggerEl,
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
n && o && l,
|
|
114
|
+
n && o && !l
|
|
111
115
|
) : this.setCorners(
|
|
112
116
|
e.triggerEl,
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
n && o && !l,
|
|
118
|
+
n && o && l
|
|
115
119
|
);
|
|
116
120
|
}
|
|
117
121
|
}
|
|
@@ -131,12 +135,12 @@ class g {
|
|
|
131
135
|
clearState() {
|
|
132
136
|
this.host.getContainerEl().style.removeProperty("--hiddenCount");
|
|
133
137
|
for (const s of this.lastScan.items)
|
|
134
|
-
if (s.el.removeAttribute("data-state"), s.el.style.removeProperty("display"), s.el.style.removeProperty("max-width"), s.el.style.removeProperty("overflow"), this.clearMinStyles(s.buttonEl), s.buttonEl)
|
|
135
|
-
for (const
|
|
136
|
-
s.buttonEl.style.removeProperty(
|
|
138
|
+
if (s.el.removeAttribute("data-state"), s.el.removeAttribute("data-can-min"), s.el.style.removeProperty("display"), s.el.style.removeProperty("max-width"), s.el.style.removeProperty("overflow"), s.el.style.removeProperty("--min-state-width"), this.clearMinStyles(s.buttonEl), s.buttonEl)
|
|
139
|
+
for (const r of c)
|
|
140
|
+
s.buttonEl.style.removeProperty(r);
|
|
137
141
|
const e = this.lastScan.menu;
|
|
138
142
|
if (e) {
|
|
139
|
-
e.el.removeAttribute("data-state"), e.el.style.removeProperty("display"), this.clearMinStyles(e.triggerEl);
|
|
143
|
+
e.el.removeAttribute("data-state"), e.el.style.removeProperty("display"), e.triggerEl.removeAttribute("aria-haspopup"), e.triggerEl.removeAttribute("aria-expanded"), this.clearMinStyles(e.triggerEl);
|
|
140
144
|
for (const s of c)
|
|
141
145
|
e.triggerEl.style.removeProperty(s);
|
|
142
146
|
for (const s of e.menuItemEls)
|
|
@@ -145,6 +149,6 @@ class g {
|
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
export {
|
|
148
|
-
|
|
152
|
+
v as OverflowController
|
|
149
153
|
};
|
|
150
154
|
//# sourceMappingURL=OverflowController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverflowController.js","sources":["../../../src/components/Overflow/OverflowController.ts"],"sourcesContent":["import {\n type AppliedStep,\n type Step,\n buildOrderedSteps,\n computeNextSteps,\n deriveHiddenMap,\n} from './overflowSteps';\n\n/* ── Public types ───────────────────────────────────────── */\n\nexport interface ScannedItem {\n el: HTMLElement;\n buttonEl: HTMLElement | null;\n menuid: string | undefined;\n minStateWidth: string | undefined;\n}\n\nexport interface ScannedMenu {\n el: HTMLElement;\n triggerEl: HTMLElement;\n menuItemEls: HTMLElement[];\n inMenuIds: Set<string>;\n hasMenuOnlyItems: boolean;\n}\n\nexport interface ScanResult {\n items: ScannedItem[];\n menu: ScannedMenu | null;\n /** true when the menu appears before items in DOM order */\n menuFirst: boolean;\n}\n\nexport interface OverflowHost {\n getContainerEl(): HTMLElement;\n scanChildren(): ScanResult;\n isCompact(): boolean;\n isReverse(): boolean;\n}\n\n/* ── Shared style constants (kebab-case for setProperty) ── */\n\nconst MIN_STATE_STYLES: Record<string, string> = {\n 'font-size': '0',\n 'min-width': '100%',\n 'width': '100%',\n 'max-width': '100%',\n 'align-items': 'center',\n 'justify-content': 'center',\n 'gap': '0',\n};\n\nconst MIN_STATE_KEYS = Object.keys(MIN_STATE_STYLES);\n\nconst CORNER_PROPS = [\n 'border-top-left-radius',\n 'border-bottom-left-radius',\n 'border-top-right-radius',\n 'border-bottom-right-radius',\n] as const;\n\n/* ── Controller ─────────────────────────────────────────── */\n\nexport class OverflowController {\n private host: OverflowHost;\n private orderedSteps: Step[] = [];\n private appliedSteps: AppliedStep[] = [];\n private ro: ResizeObserver | null = null;\n private lastScan: ScanResult = { items: [], menu: null, menuFirst: false };\n\n constructor(host: OverflowHost) {\n this.host = host;\n }\n\n /** Start observing (call after DOM is ready). */\n connect(): void {\n this.scan();\n this.startObserver();\n }\n\n /** Stop observing and clear all applied state. */\n disconnect(): void {\n this.ro?.disconnect();\n this.ro = null;\n this.clearState();\n }\n\n /** Re-scan children + restart (call after external DOM changes). */\n update(): void {\n this.appliedSteps = [];\n this.scan();\n this.startObserver();\n }\n\n /* ── Private ──────────────────────────────────────────── */\n\n private scan(): void {\n this.lastScan = this.host.scanChildren();\n\n const menuIds: string[] = [];\n const minWidthMenuIds = new Set<string>();\n\n for (const item of this.lastScan.items) {\n if (item.menuid) {\n menuIds.push(item.menuid);\n if (item.minStateWidth) minWidthMenuIds.add(item.menuid);\n }\n }\n\n const inMenuIds = this.lastScan.menu?.inMenuIds ?? new Set<string>();\n const isReverse = this.host.isReverse();\n const ids = isReverse ? [...menuIds].reverse() : menuIds;\n this.orderedSteps = buildOrderedSteps(ids, inMenuIds, minWidthMenuIds);\n }\n\n private startObserver(): void {\n this.ro?.disconnect();\n const container = this.host.getContainerEl();\n this.ro = new ResizeObserver(() => this.onResize());\n this.ro.observe(container);\n this.onResize();\n this.applyState();\n }\n\n private onResize(): void {\n const container = this.host.getContainerEl();\n\n // Loop until stable — each applyState() mutates the DOM synchronously,\n // so the next iteration gets updated dimensions.\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { scrollWidth, clientWidth } = container;\n const next = computeNextSteps(\n this.appliedSteps,\n scrollWidth,\n clientWidth,\n this.orderedSteps,\n );\n if (next === this.appliedSteps) break;\n this.appliedSteps = next;\n this.applyState();\n }\n }\n\n private applyState(): void {\n const hiddenMap = deriveHiddenMap(this.appliedSteps);\n const container = this.host.getContainerEl();\n container.style.setProperty('--hiddenCount', String(this.appliedSteps.length));\n\n const isCompact = this.host.isCompact();\n const isReverse = this.host.isReverse();\n\n let anyFullyHidden = false;\n const visibleItems: ScannedItem[] = [];\n\n // Apply item states\n for (const item of this.lastScan.items) {\n const state = item.menuid\n ? (hiddenMap.get(item.menuid) ?? 'visible')\n : 'visible';\n\n item.el.setAttribute('data-state', state);\n\n if (state === 'visible') {\n item.el.style.removeProperty('display');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n this.clearMinStyles(item.buttonEl);\n visibleItems.push(item);\n } else if (state === 'min') {\n item.el.style.removeProperty('display');\n item.el.style.setProperty('max-width', item.minStateWidth ?? '2.25rem');\n item.el.style.setProperty('overflow', 'hidden');\n this.applyMinStyles(item.buttonEl);\n visibleItems.push(item);\n } else {\n // hidden\n item.el.style.setProperty('display', 'none');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n this.clearMinStyles(item.buttonEl);\n anyFullyHidden = true;\n }\n }\n\n // Menu\n const { menu, menuFirst } = this.lastScan;\n const menuVisible = this.applyMenuState(menu, hiddenMap, anyFullyHidden);\n\n // Compact corners\n this.applyCompactCorners(\n visibleItems, menu, menuFirst, menuVisible, isCompact, isReverse,\n );\n }\n\n private applyMenuState(\n menu: ScannedMenu | null,\n hiddenMap: Map<string, 'min' | 'hidden'>,\n anyFullyHidden: boolean,\n ): boolean {\n if (!menu) return false;\n\n const showOpener = anyFullyHidden || menu.hasMenuOnlyItems;\n menu.el.style.setProperty('display', showOpener ? '' : 'none');\n menu.el.setAttribute('data-state', showOpener ? 'visible' : 'hidden');\n\n // Opener trigger styles (icon-only display)\n if (showOpener) {\n this.applyMinStyles(menu.triggerEl);\n } else {\n this.clearMinStyles(menu.triggerEl);\n }\n\n // Show/hide individual menu items\n for (const mi of menu.menuItemEls) {\n const mid = mi.getAttribute('menuid') ?? mi.dataset.menuid;\n if (!mid) {\n // Menu-only item — always visible\n mi.style.removeProperty('display');\n } else if (hiddenMap.get(mid) === 'hidden') {\n mi.style.removeProperty('display');\n } else {\n mi.style.setProperty('display', 'none');\n }\n }\n\n return showOpener;\n }\n\n private applyCompactCorners(\n visibleItems: ScannedItem[],\n menu: ScannedMenu | null,\n menuFirst: boolean,\n menuVisible: boolean,\n isCompact: boolean,\n isReverse: boolean,\n ): void {\n for (let i = 0; i < visibleItems.length; i++) {\n const btn = visibleItems[i].buttonEl;\n if (!btn) continue;\n\n const isFirst = i === 0;\n const isLast = i === visibleItems.length - 1;\n\n // Determine adjacency based on menu position\n const hasPrev = menuFirst\n ? (!isFirst || menuVisible)\n : !isFirst;\n const hasNext = menuFirst\n ? !isLast\n : (!isLast || menuVisible);\n\n // Normal (row): prev = left, next = right\n // Reverse (row-reverse): prev = right, next = left\n this.setCorners(btn,\n isCompact && (isReverse ? hasNext : hasPrev),\n isCompact && (isReverse ? hasPrev : hasNext),\n );\n }\n\n // Menu trigger corners\n if (menu?.triggerEl) {\n const hasAdjacentItem = menuVisible && visibleItems.length > 0;\n\n if (menuFirst) {\n // Menu first in DOM → left in normal, right in reverse\n this.setCorners(menu.triggerEl,\n isCompact && hasAdjacentItem && isReverse,\n isCompact && hasAdjacentItem && !isReverse,\n );\n } else {\n // Menu last in DOM → right in normal, left in reverse\n this.setCorners(menu.triggerEl,\n isCompact && hasAdjacentItem && !isReverse,\n isCompact && hasAdjacentItem && isReverse,\n );\n }\n }\n }\n\n private setCorners(\n el: HTMLElement,\n squareLeft: boolean,\n squareRight: boolean,\n ): void {\n el.style.borderTopLeftRadius = squareLeft ? '0' : '';\n el.style.borderBottomLeftRadius = squareLeft ? '0' : '';\n el.style.borderTopRightRadius = squareRight ? '0' : '';\n el.style.borderBottomRightRadius = squareRight ? '0' : '';\n }\n\n private applyMinStyles(el: HTMLElement | null): void {\n if (!el) return;\n for (const key of MIN_STATE_KEYS) {\n el.style.setProperty(key, MIN_STATE_STYLES[key]);\n }\n }\n\n private clearMinStyles(el: HTMLElement | null): void {\n if (!el) return;\n for (const key of MIN_STATE_KEYS) {\n el.style.removeProperty(key);\n }\n }\n\n private clearState(): void {\n const container = this.host.getContainerEl();\n container.style.removeProperty('--hiddenCount');\n\n for (const item of this.lastScan.items) {\n item.el.removeAttribute('data-state');\n item.el.style.removeProperty('display');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n this.clearMinStyles(item.buttonEl);\n if (item.buttonEl) {\n for (const prop of CORNER_PROPS) {\n item.buttonEl.style.removeProperty(prop);\n }\n }\n }\n\n const menu = this.lastScan.menu;\n if (menu) {\n menu.el.removeAttribute('data-state');\n menu.el.style.removeProperty('display');\n this.clearMinStyles(menu.triggerEl);\n for (const prop of CORNER_PROPS) {\n menu.triggerEl.style.removeProperty(prop);\n }\n for (const mi of menu.menuItemEls) {\n mi.style.removeProperty('display');\n }\n }\n }\n}\n"],"names":["MIN_STATE_STYLES","MIN_STATE_KEYS","CORNER_PROPS","OverflowController","host","menuIds","minWidthMenuIds","item","inMenuIds","ids","buildOrderedSteps","container","scrollWidth","clientWidth","next","computeNextSteps","hiddenMap","deriveHiddenMap","isCompact","isReverse","anyFullyHidden","visibleItems","state","menu","menuFirst","menuVisible","showOpener","mi","mid","i","btn","isFirst","isLast","hasPrev","hasNext","hasAdjacentItem","el","squareLeft","squareRight","key","prop"],"mappings":";AAyCA,MAAMA,IAA2C;AAAA,EAC/C,aAAa;AAAA,EACb,aAAa;AAAA,EACb,OAAS;AAAA,EACT,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,KAAO;AACT,GAEMC,IAAiB,OAAO,KAAKD,CAAgB,GAE7CE,IAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,MAAMC,EAAmB;AAAA,EACtB;AAAA,EACA,eAAuB,CAAA;AAAA,EACvB,eAA8B,CAAA;AAAA,EAC9B,KAA4B;AAAA,EAC5B,WAAuB,EAAE,OAAO,CAAA,GAAI,MAAM,MAAM,WAAW,GAAA;AAAA,EAEnE,YAAYC,GAAoB;AAC9B,SAAK,OAAOA;AAAA,EACd;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,KAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA;AAAA,EAGA,aAAmB;AACjB,SAAK,IAAI,WAAA,GACT,KAAK,KAAK,MACV,KAAK,WAAA;AAAA,EACP;AAAA;AAAA,EAGA,SAAe;AACb,SAAK,eAAe,CAAA,GACpB,KAAK,KAAA,GACL,KAAK,cAAA;AAAA,EACP;AAAA;AAAA,EAIQ,OAAa;AACnB,SAAK,WAAW,KAAK,KAAK,aAAA;AAE1B,UAAMC,IAAoB,CAAA,GACpBC,wBAAsB,IAAA;AAE5B,eAAWC,KAAQ,KAAK,SAAS;AAC/B,MAAIA,EAAK,WACPF,EAAQ,KAAKE,EAAK,MAAM,GACpBA,EAAK,iBAAeD,EAAgB,IAAIC,EAAK,MAAM;AAI3D,UAAMC,IAAY,KAAK,SAAS,MAAM,iCAAiB,IAAA,GAEjDC,IADY,KAAK,KAAK,UAAA,IACJ,CAAC,GAAGJ,CAAO,EAAE,YAAYA;AACjD,SAAK,eAAeK,EAAkBD,GAAKD,GAAWF,CAAe;AAAA,EACvE;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,IAAI,WAAA;AACT,UAAMK,IAAY,KAAK,KAAK,eAAA;AAC5B,SAAK,KAAK,IAAI,eAAe,MAAM,KAAK,UAAU,GAClD,KAAK,GAAG,QAAQA,CAAS,GACzB,KAAK,SAAA,GACL,KAAK,WAAA;AAAA,EACP;AAAA,EAEQ,WAAiB;AACvB,UAAMA,IAAY,KAAK,KAAK,eAAA;AAK5B,eAAa;AACX,YAAM,EAAE,aAAAC,GAAa,aAAAC,EAAA,IAAgBF,GAC/BG,IAAOC;AAAA,QACX,KAAK;AAAA,QACLH;AAAA,QACAC;AAAA,QACA,KAAK;AAAA,MAAA;AAEP,UAAIC,MAAS,KAAK,aAAc;AAChC,WAAK,eAAeA,GACpB,KAAK,WAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEQ,aAAmB;AACzB,UAAME,IAAYC,EAAgB,KAAK,YAAY;AAEnD,IADkB,KAAK,KAAK,eAAA,EAClB,MAAM,YAAY,iBAAiB,OAAO,KAAK,aAAa,MAAM,CAAC;AAE7E,UAAMC,IAAY,KAAK,KAAK,UAAA,GACtBC,IAAY,KAAK,KAAK,UAAA;AAE5B,QAAIC,IAAiB;AACrB,UAAMC,IAA8B,CAAA;AAGpC,eAAWd,KAAQ,KAAK,SAAS,OAAO;AACtC,YAAMe,IAAQf,EAAK,SACdS,EAAU,IAAIT,EAAK,MAAM,KAAK,YAC/B;AAEJ,MAAAA,EAAK,GAAG,aAAa,cAAce,CAAK,GAEpCA,MAAU,aACZf,EAAK,GAAG,MAAM,eAAe,SAAS,GACtCA,EAAK,GAAG,MAAM,eAAe,WAAW,GACxCA,EAAK,GAAG,MAAM,eAAe,UAAU,GACvC,KAAK,eAAeA,EAAK,QAAQ,GACjCc,EAAa,KAAKd,CAAI,KACbe,MAAU,SACnBf,EAAK,GAAG,MAAM,eAAe,SAAS,GACtCA,EAAK,GAAG,MAAM,YAAY,aAAaA,EAAK,iBAAiB,SAAS,GACtEA,EAAK,GAAG,MAAM,YAAY,YAAY,QAAQ,GAC9C,KAAK,eAAeA,EAAK,QAAQ,GACjCc,EAAa,KAAKd,CAAI,MAGtBA,EAAK,GAAG,MAAM,YAAY,WAAW,MAAM,GAC3CA,EAAK,GAAG,MAAM,eAAe,WAAW,GACxCA,EAAK,GAAG,MAAM,eAAe,UAAU,GACvC,KAAK,eAAeA,EAAK,QAAQ,GACjCa,IAAiB;AAAA,IAErB;AAGA,UAAM,EAAE,MAAAG,GAAM,WAAAC,EAAA,IAAc,KAAK,UAC3BC,IAAc,KAAK,eAAeF,GAAMP,GAAWI,CAAc;AAGvE,SAAK;AAAA,MACHC;AAAA,MAAcE;AAAA,MAAMC;AAAA,MAAWC;AAAA,MAAaP;AAAA,MAAWC;AAAA,IAAA;AAAA,EAE3D;AAAA,EAEQ,eACNI,GACAP,GACAI,GACS;AACT,QAAI,CAACG,EAAM,QAAO;AAElB,UAAMG,IAAaN,KAAkBG,EAAK;AAC1C,IAAAA,EAAK,GAAG,MAAM,YAAY,WAAWG,IAAa,KAAK,MAAM,GAC7DH,EAAK,GAAG,aAAa,cAAcG,IAAa,YAAY,QAAQ,GAGhEA,IACF,KAAK,eAAeH,EAAK,SAAS,IAElC,KAAK,eAAeA,EAAK,SAAS;AAIpC,eAAWI,KAAMJ,EAAK,aAAa;AACjC,YAAMK,IAAMD,EAAG,aAAa,QAAQ,KAAKA,EAAG,QAAQ;AACpD,MAAKC,IAGMZ,EAAU,IAAIY,CAAG,MAAM,WAChCD,EAAG,MAAM,eAAe,SAAS,IAEjCA,EAAG,MAAM,YAAY,WAAW,MAAM,IAJtCA,EAAG,MAAM,eAAe,SAAS;AAAA,IAMrC;AAEA,WAAOD;AAAA,EACT;AAAA,EAEQ,oBACNL,GACAE,GACAC,GACAC,GACAP,GACAC,GACM;AACN,aAASU,IAAI,GAAGA,IAAIR,EAAa,QAAQQ,KAAK;AAC5C,YAAMC,IAAMT,EAAaQ,CAAC,EAAE;AAC5B,UAAI,CAACC,EAAK;AAEV,YAAMC,IAAUF,MAAM,GAChBG,IAASH,MAAMR,EAAa,SAAS,GAGrCY,IAAUT,IACX,CAACO,KAAWN,IACb,CAACM,GACCG,IAAUV,IACZ,CAACQ,IACA,CAACA,KAAUP;AAIhB,WAAK;AAAA,QAAWK;AAAA,QACdZ,MAAcC,IAAYe,IAAUD;AAAA,QACpCf,MAAcC,IAAYc,IAAUC;AAAA,MAAA;AAAA,IAExC;AAGA,QAAIX,GAAM,WAAW;AACnB,YAAMY,IAAkBV,KAAeJ,EAAa,SAAS;AAE7D,MAAIG,IAEF,KAAK;AAAA,QAAWD,EAAK;AAAA,QACnBL,KAAaiB,KAAmBhB;AAAA,QAChCD,KAAaiB,KAAmB,CAAChB;AAAA,MAAA,IAInC,KAAK;AAAA,QAAWI,EAAK;AAAA,QACnBL,KAAaiB,KAAmB,CAAChB;AAAA,QACjCD,KAAaiB,KAAmBhB;AAAA,MAAA;AAAA,IAGtC;AAAA,EACF;AAAA,EAEQ,WACNiB,GACAC,GACAC,GACM;AACN,IAAAF,EAAG,MAAM,sBAAsBC,IAAa,MAAM,IAClDD,EAAG,MAAM,yBAAyBC,IAAa,MAAM,IACrDD,EAAG,MAAM,uBAAuBE,IAAc,MAAM,IACpDF,EAAG,MAAM,0BAA0BE,IAAc,MAAM;AAAA,EACzD;AAAA,EAEQ,eAAeF,GAA8B;AACnD,QAAKA;AACL,iBAAWG,KAAOtC;AAChB,QAAAmC,EAAG,MAAM,YAAYG,GAAKvC,EAAiBuC,CAAG,CAAC;AAAA,EAEnD;AAAA,EAEQ,eAAeH,GAA8B;AACnD,QAAKA;AACL,iBAAWG,KAAOtC;AAChB,QAAAmC,EAAG,MAAM,eAAeG,CAAG;AAAA,EAE/B;AAAA,EAEQ,aAAmB;AAEzB,IADkB,KAAK,KAAK,eAAA,EAClB,MAAM,eAAe,eAAe;AAE9C,eAAWhC,KAAQ,KAAK,SAAS;AAM/B,UALAA,EAAK,GAAG,gBAAgB,YAAY,GACpCA,EAAK,GAAG,MAAM,eAAe,SAAS,GACtCA,EAAK,GAAG,MAAM,eAAe,WAAW,GACxCA,EAAK,GAAG,MAAM,eAAe,UAAU,GACvC,KAAK,eAAeA,EAAK,QAAQ,GAC7BA,EAAK;AACP,mBAAWiC,KAAQtC;AACjB,UAAAK,EAAK,SAAS,MAAM,eAAeiC,CAAI;AAK7C,UAAMjB,IAAO,KAAK,SAAS;AAC3B,QAAIA,GAAM;AACR,MAAAA,EAAK,GAAG,gBAAgB,YAAY,GACpCA,EAAK,GAAG,MAAM,eAAe,SAAS,GACtC,KAAK,eAAeA,EAAK,SAAS;AAClC,iBAAWiB,KAAQtC;AACjB,QAAAqB,EAAK,UAAU,MAAM,eAAeiB,CAAI;AAE1C,iBAAWb,KAAMJ,EAAK;AACpB,QAAAI,EAAG,MAAM,eAAe,SAAS;AAAA,IAErC;AAAA,EACF;AACF;"}
|
|
1
|
+
{"version":3,"file":"OverflowController.js","sources":["../../../src/components/Overflow/OverflowController.ts"],"sourcesContent":["import {\n type AppliedStep,\n type Step,\n buildOrderedSteps,\n computeNextSteps,\n deriveHiddenMap,\n} from './overflowSteps';\n\n/* ── Public types ───────────────────────────────────────── */\n\nexport interface ScannedItem {\n el: HTMLElement;\n buttonEl: HTMLElement | null;\n menuId: string | undefined;\n minStateWidth: string | undefined;\n}\n\nexport interface ScannedMenu {\n el: HTMLElement;\n triggerEl: HTMLElement;\n menuItemEls: HTMLElement[];\n inMenuIds: Set<string>;\n hasMenuOnlyItems: boolean;\n}\n\nexport interface ScanResult {\n items: ScannedItem[];\n menu: ScannedMenu | null;\n /** true when the menu appears before items in DOM order */\n menuFirst: boolean;\n}\n\nexport interface OverflowHost {\n getContainerEl(): HTMLElement;\n scanChildren(): ScanResult;\n isCompact(): boolean;\n isReverse(): boolean;\n isSnap(): boolean;\n}\n\n/* ── Shared style constants (kebab-case for setProperty) ── */\n\nconst MIN_STATE_STYLES: Record<string, string> = {\n 'font-size': '0',\n 'min-width': '100%',\n 'width': '100%',\n 'max-width': '100%',\n 'align-items': 'center',\n 'justify-content': 'center',\n 'gap': '0',\n};\n\nconst MIN_STATE_KEYS = Object.keys(MIN_STATE_STYLES);\n\nconst CORNER_PROPS = [\n 'border-top-left-radius',\n 'border-bottom-left-radius',\n 'border-top-right-radius',\n 'border-bottom-right-radius',\n] as const;\n\n/* ── Controller ─────────────────────────────────────────── */\n\nexport class OverflowController {\n private host: OverflowHost;\n private orderedSteps: Step[] = [];\n private appliedSteps: AppliedStep[] = [];\n private ro: ResizeObserver | null = null;\n private lastScan: ScanResult = { items: [], menu: null, menuFirst: false };\n\n constructor(host: OverflowHost) {\n this.host = host;\n }\n\n /** Start observing (call after DOM is ready). */\n connect(): void {\n this.scan();\n this.startObserver();\n }\n\n /** Stop observing and clear all applied state. */\n disconnect(): void {\n this.ro?.disconnect();\n this.ro = null;\n this.clearState();\n }\n\n /** Re-scan children + restart (call after external DOM changes). */\n update(): void {\n this.appliedSteps = [];\n this.scan();\n this.startObserver();\n }\n\n /* ── Private ──────────────────────────────────────────── */\n\n private scan(): void {\n this.lastScan = this.host.scanChildren();\n\n const menuIds: string[] = [];\n const minWidthMenuIds = new Set<string>();\n\n for (const item of this.lastScan.items) {\n if (item.menuId) {\n menuIds.push(item.menuId);\n if (item.minStateWidth) minWidthMenuIds.add(item.menuId);\n }\n // Set CSS custom properties for snap targeting\n if (item.minStateWidth) {\n item.el.style.setProperty('--min-state-width', item.minStateWidth);\n item.el.setAttribute('data-can-min', '');\n }\n }\n\n const inMenuIds = this.lastScan.menu?.inMenuIds ?? new Set<string>();\n this.orderedSteps = buildOrderedSteps(menuIds, inMenuIds, minWidthMenuIds);\n }\n\n private startObserver(): void {\n this.ro?.disconnect();\n const container = this.host.getContainerEl();\n this.ro = new ResizeObserver(() => this.onResize());\n this.ro.observe(container);\n this.onResize();\n this.applyState();\n }\n\n private onResize(): void {\n const container = this.host.getContainerEl();\n\n // Loop until stable — each applyState() mutates the DOM synchronously,\n // so the next iteration gets updated dimensions.\n while (true) {\n const { scrollWidth, clientWidth } = container;\n const next = computeNextSteps(\n this.appliedSteps,\n scrollWidth,\n clientWidth,\n this.orderedSteps,\n );\n if (next === this.appliedSteps) break;\n this.appliedSteps = next;\n this.applyState();\n }\n }\n\n private applyState(): void {\n const isSnap = this.host.isSnap();\n const hiddenMap = deriveHiddenMap(\n this.appliedSteps,\n isSnap,\n this.lastScan.menu?.inMenuIds,\n );\n const container = this.host.getContainerEl();\n container.style.setProperty('--hiddenCount', String(this.appliedSteps.length));\n\n const isCompact = this.host.isCompact();\n const isReverse = this.host.isReverse();\n\n let anyFullyHidden = false;\n const visibleItems: ScannedItem[] = [];\n\n // Apply item states\n for (const item of this.lastScan.items) {\n const state = item.menuId\n ? (hiddenMap.get(item.menuId) ?? 'visible')\n : 'visible';\n\n item.el.setAttribute('data-state', state);\n\n if (state === 'visible') {\n item.el.style.removeProperty('display');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n this.clearMinStyles(item.buttonEl);\n visibleItems.push(item);\n } else if (state === 'min') {\n item.el.style.removeProperty('display');\n item.el.style.setProperty('max-width', item.minStateWidth ?? '2.25rem');\n item.el.style.setProperty('overflow', 'hidden');\n this.applyMinStyles(item.buttonEl);\n visibleItems.push(item);\n } else {\n // hidden\n item.el.style.setProperty('display', 'none');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n this.clearMinStyles(item.buttonEl);\n anyFullyHidden = true;\n }\n }\n\n // Menu\n const { menu, menuFirst } = this.lastScan;\n const menuVisible = this.applyMenuState(menu, hiddenMap, anyFullyHidden);\n\n // Compact corners\n this.applyCompactCorners(\n visibleItems, menu, menuFirst, menuVisible, isCompact, isReverse,\n );\n }\n\n private applyMenuState(\n menu: ScannedMenu | null,\n hiddenMap: Map<string, 'min' | 'hidden'>,\n anyFullyHidden: boolean,\n ): boolean {\n if (!menu) return false;\n\n const showOpener = anyFullyHidden || menu.hasMenuOnlyItems;\n menu.el.style.setProperty('display', showOpener ? '' : 'none');\n menu.el.setAttribute('data-state', showOpener ? 'visible' : 'hidden');\n\n // ARIA attributes on the trigger\n menu.triggerEl.setAttribute('aria-haspopup', 'menu');\n menu.triggerEl.setAttribute('aria-expanded', String(showOpener));\n\n // Opener trigger styles (icon-only display)\n if (showOpener) {\n this.applyMinStyles(menu.triggerEl);\n } else {\n this.clearMinStyles(menu.triggerEl);\n }\n\n // Show/hide individual menu items\n for (const mi of menu.menuItemEls) {\n const mid = mi.dataset.menuId;\n if (!mid) {\n // Menu-only item — always visible\n mi.style.removeProperty('display');\n } else if (hiddenMap.get(mid) === 'hidden') {\n mi.style.removeProperty('display');\n } else {\n mi.style.setProperty('display', 'none');\n }\n }\n\n return showOpener;\n }\n\n private applyCompactCorners(\n visibleItems: ScannedItem[],\n menu: ScannedMenu | null,\n menuFirst: boolean,\n menuVisible: boolean,\n isCompact: boolean,\n isReverse: boolean,\n ): void {\n for (let i = 0; i < visibleItems.length; i++) {\n const btn = visibleItems[i].buttonEl;\n if (!btn) continue;\n\n const isFirst = i === 0;\n const isLast = i === visibleItems.length - 1;\n\n // Determine adjacency based on menu position\n const hasPrev = menuFirst\n ? (!isFirst || menuVisible)\n : !isFirst;\n const hasNext = menuFirst\n ? !isLast\n : (!isLast || menuVisible);\n\n // Normal (row): prev = left, next = right\n // Reverse (row-reverse): prev = right, next = left\n this.setCorners(btn,\n isCompact && (isReverse ? hasNext : hasPrev),\n isCompact && (isReverse ? hasPrev : hasNext),\n );\n }\n\n // Menu trigger corners\n if (menu?.triggerEl) {\n const hasAdjacentItem = menuVisible && visibleItems.length > 0;\n\n if (menuFirst) {\n // Menu first in DOM → left in normal, right in reverse\n this.setCorners(menu.triggerEl,\n isCompact && hasAdjacentItem && isReverse,\n isCompact && hasAdjacentItem && !isReverse,\n );\n } else {\n // Menu last in DOM → right in normal, left in reverse\n this.setCorners(menu.triggerEl,\n isCompact && hasAdjacentItem && !isReverse,\n isCompact && hasAdjacentItem && isReverse,\n );\n }\n }\n }\n\n private setCorners(\n el: HTMLElement,\n squareLeft: boolean,\n squareRight: boolean,\n ): void {\n el.style.borderTopLeftRadius = squareLeft ? '0' : '';\n el.style.borderBottomLeftRadius = squareLeft ? '0' : '';\n el.style.borderTopRightRadius = squareRight ? '0' : '';\n el.style.borderBottomRightRadius = squareRight ? '0' : '';\n }\n\n private applyMinStyles(el: HTMLElement | null): void {\n if (!el) return;\n for (const key of MIN_STATE_KEYS) {\n el.style.setProperty(key, MIN_STATE_STYLES[key]);\n }\n }\n\n private clearMinStyles(el: HTMLElement | null): void {\n if (!el) return;\n for (const key of MIN_STATE_KEYS) {\n el.style.removeProperty(key);\n }\n }\n\n private clearState(): void {\n const container = this.host.getContainerEl();\n container.style.removeProperty('--hiddenCount');\n\n for (const item of this.lastScan.items) {\n item.el.removeAttribute('data-state');\n item.el.removeAttribute('data-can-min');\n item.el.style.removeProperty('display');\n item.el.style.removeProperty('max-width');\n item.el.style.removeProperty('overflow');\n item.el.style.removeProperty('--min-state-width');\n this.clearMinStyles(item.buttonEl);\n if (item.buttonEl) {\n for (const prop of CORNER_PROPS) {\n item.buttonEl.style.removeProperty(prop);\n }\n }\n }\n\n const menu = this.lastScan.menu;\n if (menu) {\n menu.el.removeAttribute('data-state');\n menu.el.style.removeProperty('display');\n menu.triggerEl.removeAttribute('aria-haspopup');\n menu.triggerEl.removeAttribute('aria-expanded');\n this.clearMinStyles(menu.triggerEl);\n for (const prop of CORNER_PROPS) {\n menu.triggerEl.style.removeProperty(prop);\n }\n for (const mi of menu.menuItemEls) {\n mi.style.removeProperty('display');\n }\n }\n }\n}\n"],"names":["MIN_STATE_STYLES","MIN_STATE_KEYS","CORNER_PROPS","OverflowController","host","menuIds","minWidthMenuIds","item","inMenuIds","buildOrderedSteps","container","scrollWidth","clientWidth","next","computeNextSteps","isSnap","hiddenMap","deriveHiddenMap","isCompact","isReverse","anyFullyHidden","visibleItems","state","menu","menuFirst","menuVisible","showOpener","mi","mid","i","btn","isFirst","isLast","hasPrev","hasNext","hasAdjacentItem","el","squareLeft","squareRight","key","prop"],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
/** Props for the OverflowItem component. */
|
|
2
3
|
export interface OverflowItemProps {
|
|
4
|
+
/** The item content (typically a button or link). */
|
|
3
5
|
children: ReactNode;
|
|
4
|
-
|
|
6
|
+
/** Links this toolbar item to its menu counterpart. Items with matching menuIds are shown/hidden together. */
|
|
7
|
+
menuId?: string;
|
|
8
|
+
/** CSS width value for the min (icon-only) state. When set, the item shrinks to this width before being fully hidden. */
|
|
5
9
|
minStateWidth?: string;
|
|
6
10
|
}
|
|
7
|
-
declare function OverflowItem({ children,
|
|
8
|
-
declare
|
|
9
|
-
overflowRole: "item";
|
|
10
|
-
}
|
|
11
|
-
export default
|
|
11
|
+
declare function OverflowItem({ children, menuId, minStateWidth }: OverflowItemProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
declare namespace OverflowItem {
|
|
13
|
+
var overflowRole: "item";
|
|
14
|
+
}
|
|
15
|
+
export default OverflowItem;
|
|
12
16
|
//# sourceMappingURL=OverflowItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverflowItem.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"OverflowItem.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,QAAQ,EAAE,SAAS,CAAC;IACpB,8GAA8G;IAC9G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yHAAyH;IACzH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,iBAAiB,2CA+B3E;kBA/BQ,YAAY;;;AAkCrB,eAAe,YAAY,CAAC"}
|
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useOverflow as
|
|
3
|
-
function
|
|
4
|
-
const { hiddenMap:
|
|
5
|
-
let
|
|
1
|
+
import { jsx as v } from "react/jsx-runtime";
|
|
2
|
+
import { useOverflow as f } from "./OverflowContext.js";
|
|
3
|
+
function r({ children: a, menuId: e, minStateWidth: o }) {
|
|
4
|
+
const { hiddenMap: s } = f();
|
|
5
|
+
let i, l;
|
|
6
6
|
if (e !== void 0) {
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const t = s.get(e);
|
|
8
|
+
t === "hidden" ? i = { display: "none" } : t === "min" && o !== void 0 && (i = { minWidth: o, width: o, maxWidth: o, overflow: "hidden" }, l = "overflow-item-min");
|
|
9
9
|
}
|
|
10
|
-
const
|
|
11
|
-
return /* @__PURE__ */
|
|
10
|
+
const d = e !== void 0 ? s.get(e) ?? "visible" : void 0;
|
|
11
|
+
return /* @__PURE__ */ v(
|
|
12
|
+
"li",
|
|
13
|
+
{
|
|
14
|
+
style: { ...o !== void 0 ? { "--min-state-width": o } : void 0, ...i },
|
|
15
|
+
className: l,
|
|
16
|
+
"data-state": d,
|
|
17
|
+
"data-can-min": o !== void 0 || void 0,
|
|
18
|
+
children: a
|
|
19
|
+
}
|
|
20
|
+
);
|
|
12
21
|
}
|
|
13
|
-
|
|
22
|
+
r.overflowRole = "item";
|
|
14
23
|
export {
|
|
15
|
-
|
|
24
|
+
r as default
|
|
16
25
|
};
|
|
17
26
|
//# sourceMappingURL=OverflowItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverflowItem.js","sources":["../../../src/components/Overflow/OverflowItem.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport { useOverflow } from './OverflowContext';\n\nexport interface OverflowItemProps {\n children: ReactNode;\n
|
|
1
|
+
{"version":3,"file":"OverflowItem.js","sources":["../../../src/components/Overflow/OverflowItem.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport { useOverflow } from './OverflowContext';\n\n/** Props for the OverflowItem component. */\nexport interface OverflowItemProps {\n /** The item content (typically a button or link). */\n children: ReactNode;\n /** Links this toolbar item to its menu counterpart. Items with matching menuIds are shown/hidden together. */\n menuId?: string;\n /** CSS width value for the min (icon-only) state. When set, the item shrinks to this width before being fully hidden. */\n minStateWidth?: string;\n}\n\nfunction OverflowItem({ children, menuId, minStateWidth }: OverflowItemProps) {\n const { hiddenMap } = useOverflow();\n\n let style: CSSProperties | undefined;\n let className: string | undefined;\n if (menuId !== undefined) {\n const state = hiddenMap.get(menuId);\n if (state === 'hidden') {\n style = { display: 'none' };\n } else if (state === 'min' && minStateWidth !== undefined) {\n style = { minWidth: minStateWidth, width: minStateWidth, maxWidth: minStateWidth, overflow: 'hidden' };\n className = 'overflow-item-min';\n }\n }\n\n const dataState = menuId !== undefined ? (hiddenMap.get(menuId) ?? 'visible') : undefined;\n\n const snapStyle = minStateWidth !== undefined\n ? { '--min-state-width': minStateWidth } as CSSProperties\n : undefined;\n\n return (\n <li\n style={{ ...snapStyle, ...style }}\n className={className}\n data-state={dataState}\n data-can-min={minStateWidth !== undefined || undefined}\n >\n {children}\n </li>\n );\n}\n\nOverflowItem.overflowRole = 'item' as const;\nexport default OverflowItem;\n"],"names":["OverflowItem","children","menuId","minStateWidth","hiddenMap","useOverflow","style","className","state","dataState","jsx"],"mappings":";;AAaA,SAASA,EAAa,EAAE,UAAAC,GAAU,QAAAC,GAAQ,eAAAC,KAAoC;AAC5E,QAAM,EAAE,WAAAC,EAAA,IAAcC,EAAA;AAEtB,MAAIC,GACAC;AACJ,MAAIL,MAAW,QAAW;AACxB,UAAMM,IAAQJ,EAAU,IAAIF,CAAM;AAClC,IAAIM,MAAU,WACZF,IAAQ,EAAE,SAAS,OAAA,IACVE,MAAU,SAASL,MAAkB,WAC9CG,IAAQ,EAAE,UAAUH,GAAe,OAAOA,GAAe,UAAUA,GAAe,UAAU,SAAA,GAC5FI,IAAY;AAAA,EAEhB;AAEA,QAAME,IAAYP,MAAW,SAAaE,EAAU,IAAIF,CAAM,KAAK,YAAa;AAMhF,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO,EAAE,GANKP,MAAkB,SAChC,EAAE,qBAAqBA,MACvB,QAIuB,GAAGG,EAAA;AAAA,MAC1B,WAAAC;AAAA,MACA,cAAYE;AAAA,MACZ,gBAAcN,MAAkB,UAAa;AAAA,MAE5C,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP;AAEAD,EAAa,eAAe;"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
/** Props passed to the `renderMenu` callback to render a framework-specific dropdown. */
|
|
2
3
|
export interface RenderMenuProps {
|
|
4
|
+
/** The DOM element to anchor the menu to (null when closed). */
|
|
3
5
|
anchorEl: HTMLElement | null;
|
|
6
|
+
/** Whether the menu is currently open. */
|
|
4
7
|
open: boolean;
|
|
8
|
+
/** Call to close the menu. */
|
|
5
9
|
onClose: () => void;
|
|
10
|
+
/** The menu item elements to render inside the dropdown. */
|
|
6
11
|
children: ReactNode;
|
|
7
12
|
}
|
|
13
|
+
/** Props for controlling the menu open/close state externally. */
|
|
8
14
|
export interface OverflowMenuControlProps {
|
|
15
|
+
/** Controlled open state. When provided, you manage open/close. */
|
|
9
16
|
open?: boolean;
|
|
17
|
+
/** Called when the menu opens or closes. Use alone for notifications, or with `open` for full control. */
|
|
10
18
|
onOpenChange?: (open: boolean) => void;
|
|
11
19
|
}
|
|
12
20
|
interface OverflowMenuProps extends OverflowMenuControlProps {
|
|
@@ -15,8 +23,8 @@ interface OverflowMenuProps extends OverflowMenuControlProps {
|
|
|
15
23
|
renderMenu: (props: RenderMenuProps) => ReactNode;
|
|
16
24
|
}
|
|
17
25
|
declare function OverflowMenu({ opener, children, renderMenu, open: controlledOpen, onOpenChange }: OverflowMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
-
declare
|
|
19
|
-
overflowRole: "menu";
|
|
20
|
-
}
|
|
21
|
-
export default
|
|
26
|
+
declare namespace OverflowMenu {
|
|
27
|
+
var overflowRole: "menu";
|
|
28
|
+
}
|
|
29
|
+
export default OverflowMenu;
|
|
22
30
|
//# sourceMappingURL=OverflowMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverflowMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"OverflowMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Overflow/OverflowMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6D,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAI/H,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,8BAA8B;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,kEAAkE;AAClE,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0GAA0G;IAC1G,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,UAAU,iBAAkB,SAAQ,wBAAwB;IAC1D,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,SAAS,CAAC;CACnD;AAED,iBAAS,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,iBAAiB,2CAgG5G;kBAhGQ,YAAY;;;AAmGrB,eAAe,YAAY,CAAC"}
|