@namroodinc/liquid-editorial 0.1.4 → 0.1.6

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.
Files changed (46) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +112 -14
  3. package/UPGRADING.md +87 -0
  4. package/dist/components/ImageCropper/index.cjs +1 -1
  5. package/dist/components/ImageCropper/index.cjs.map +1 -1
  6. package/dist/components/ImageCropper/index.d.cts +3 -17
  7. package/dist/components/ImageCropper/index.d.cts.map +1 -1
  8. package/dist/components/ImageCropper/index.d.ts +3 -17
  9. package/dist/components/ImageCropper/index.d.ts.map +1 -1
  10. package/dist/components/ImageCropper/index.js +143 -180
  11. package/dist/components/ImageCropper/index.js.map +1 -1
  12. package/dist/components/ImageCropper/style.css +2 -94
  13. package/dist/components/Pagination/index.cjs +2 -0
  14. package/dist/components/Pagination/index.cjs.map +1 -0
  15. package/dist/components/Pagination/index.d.cts +24 -0
  16. package/dist/components/Pagination/index.d.cts.map +1 -0
  17. package/dist/components/Pagination/index.d.ts +24 -0
  18. package/dist/components/Pagination/index.d.ts.map +1 -0
  19. package/dist/components/Pagination/index.js +96 -0
  20. package/dist/components/Pagination/index.js.map +1 -0
  21. package/dist/components/Pagination/style.css +52 -0
  22. package/dist/components/Popover/index.cjs +1 -1
  23. package/dist/components/Popover/index.cjs.map +1 -1
  24. package/dist/components/Popover/index.d.cts +5 -1
  25. package/dist/components/Popover/index.d.cts.map +1 -1
  26. package/dist/components/Popover/index.d.ts +5 -1
  27. package/dist/components/Popover/index.d.ts.map +1 -1
  28. package/dist/components/Popover/index.js +25 -24
  29. package/dist/components/Popover/index.js.map +1 -1
  30. package/dist/components/Select/index.cjs +1 -1
  31. package/dist/components/Select/index.cjs.map +1 -1
  32. package/dist/components/Select/index.d.cts +3 -0
  33. package/dist/components/Select/index.d.cts.map +1 -1
  34. package/dist/components/Select/index.d.ts +3 -0
  35. package/dist/components/Select/index.d.ts.map +1 -1
  36. package/dist/components/Select/index.js +50 -48
  37. package/dist/components/Select/index.js.map +1 -1
  38. package/dist/components/Slider/style.css +14 -5
  39. package/dist/index.cjs +1 -1
  40. package/dist/index.d.cts +5 -3
  41. package/dist/index.d.cts.map +1 -1
  42. package/dist/index.d.ts +5 -3
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +9 -8
  45. package/dist/styles.css +1 -0
  46. package/package.json +1 -1
@@ -0,0 +1,24 @@
1
+ import { type HTMLAttributes } from "react";
2
+ import type { PopoverPlacement } from "../Popover/index.cjs";
3
+ export type PaginationSize = "sm" | "md";
4
+ export interface PaginationState {
5
+ /** One-based page number. */
6
+ page: number;
7
+ /** Positive integer results per page. */
8
+ pageSize: number;
9
+ }
10
+ export interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "onChange">, PaginationState {
11
+ /** Total number of matching results, before pagination. */
12
+ totalResults: number;
13
+ /** Emitted once per user change, with both values ready to apply together. */
14
+ onChange: (next: PaginationState) => void;
15
+ /** Nonempty list of positive integers containing the current pageSize. */
16
+ pageSizeOptions?: number[];
17
+ size?: PaginationSize;
18
+ isDisabled?: boolean;
19
+ showLabels?: boolean;
20
+ menuPlacement?: PopoverPlacement;
21
+ }
22
+ /** Controlled navigation for a result set. Data loading and slicing belong to the application. */
23
+ export declare const Pagination: import("react").ForwardRefExoticComponent<PaginationProps & import("react").RefAttributes<HTMLElement>>;
24
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Pagination/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAG/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eACf,SACE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,EAC1D,eAAe;IACjB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,kGAAkG;AAClG,eAAO,MAAM,UAAU,yGAkHtB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { type HTMLAttributes } from "react";
2
+ import type { PopoverPlacement } from "../Popover/index.js";
3
+ export type PaginationSize = "sm" | "md";
4
+ export interface PaginationState {
5
+ /** One-based page number. */
6
+ page: number;
7
+ /** Positive integer results per page. */
8
+ pageSize: number;
9
+ }
10
+ export interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "onChange">, PaginationState {
11
+ /** Total number of matching results, before pagination. */
12
+ totalResults: number;
13
+ /** Emitted once per user change, with both values ready to apply together. */
14
+ onChange: (next: PaginationState) => void;
15
+ /** Nonempty list of positive integers containing the current pageSize. */
16
+ pageSizeOptions?: number[];
17
+ size?: PaginationSize;
18
+ isDisabled?: boolean;
19
+ showLabels?: boolean;
20
+ menuPlacement?: PopoverPlacement;
21
+ }
22
+ /** Controlled navigation for a result set. Data loading and slicing belong to the application. */
23
+ export declare const Pagination: import("react").ForwardRefExoticComponent<PaginationProps & import("react").RefAttributes<HTMLElement>>;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Pagination/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAG/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,aAAa,CAAC;AAErB,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eACf,SACE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,EAC1D,eAAe;IACjB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,kGAAkG;AAClG,eAAO,MAAM,UAAU,yGAkHtB,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { Button as e } from "../Button/index.js";
2
+ import { Select as t } from "../Select/index.js";
3
+ import { forwardRef as n, useId as r } from "react";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/components/Pagination/index.tsx
6
+ var o = n(function({ totalResults: n, page: o, pageSize: s, onChange: c, pageSizeOptions: l = [
7
+ 10,
8
+ 25,
9
+ 50,
10
+ 100
11
+ ], size: u = "sm", isDisabled: d = !1, showLabels: f = !0, menuPlacement: p = "bottom", className: m, ...h }, g) {
12
+ let _ = r(), v = Math.max(1, Math.ceil(n / s)), y = Math.min(Math.max(1, o), v), b = d || n === 0, x = b || y === 1, S = b || y === v, C = (y - 1) * s + 1, w = Math.min(y * s, n), T = (e) => {
13
+ let t = Math.min(Math.max(1, e), v);
14
+ t !== y && c({
15
+ page: t,
16
+ pageSize: s
17
+ });
18
+ };
19
+ return /* @__PURE__ */ a("nav", {
20
+ ref: g,
21
+ "aria-label": "Pagination",
22
+ "data-size": u,
23
+ className: ["ds-pagination", m].filter(Boolean).join(" "),
24
+ ...h,
25
+ children: [
26
+ /* @__PURE__ */ i("div", {
27
+ className: "ds-pagination__actions",
28
+ children: /* @__PURE__ */ i(e, {
29
+ variant: "neutral",
30
+ size: u,
31
+ iconStart: "chevron-left",
32
+ isIconOnly: !f,
33
+ "aria-label": "Previous page",
34
+ isDisabled: x,
35
+ onClick: () => T(y - 1),
36
+ children: "Previous"
37
+ })
38
+ }),
39
+ /* @__PURE__ */ a("div", {
40
+ className: "ds-pagination__centre",
41
+ children: [/* @__PURE__ */ a("div", {
42
+ className: "ds-pagination__per-page",
43
+ children: [/* @__PURE__ */ i("span", {
44
+ id: _,
45
+ children: "Per page"
46
+ }), /* @__PURE__ */ i("div", {
47
+ className: "ds-pagination__select",
48
+ children: /* @__PURE__ */ i(t, {
49
+ "aria-labelledby": _,
50
+ value: String(s),
51
+ options: l.map((e) => ({
52
+ value: String(e),
53
+ label: String(e)
54
+ })),
55
+ size: u,
56
+ menuPlacement: p,
57
+ isDisabled: b || n <= Math.min(...l),
58
+ onValueChange: (e) => {
59
+ let t = Number(e);
60
+ if (t === s) return;
61
+ let r = Math.floor((y - 1) * s / t) + 1, i = Math.max(1, Math.ceil(n / t));
62
+ c({
63
+ page: Math.min(r, i),
64
+ pageSize: t
65
+ });
66
+ }
67
+ })
68
+ })]
69
+ }), /* @__PURE__ */ i("span", {
70
+ className: "ds-pagination__range",
71
+ "aria-live": "polite",
72
+ "aria-atomic": "true",
73
+ children: n === 0 ? "No results" : `${C.toLocaleString("en-US")}–${w.toLocaleString("en-US")} of ${n.toLocaleString("en-US")}`
74
+ })]
75
+ }),
76
+ /* @__PURE__ */ i("div", {
77
+ className: "ds-pagination__actions ds-pagination__actions--next",
78
+ children: /* @__PURE__ */ i(e, {
79
+ variant: "neutral",
80
+ size: u,
81
+ iconStart: f ? void 0 : "chevron-right",
82
+ iconEnd: f ? "chevron-right" : void 0,
83
+ isIconOnly: !f,
84
+ "aria-label": "Next page",
85
+ isDisabled: S,
86
+ onClick: () => T(y + 1),
87
+ children: "Next"
88
+ })
89
+ })
90
+ ]
91
+ });
92
+ });
93
+ //#endregion
94
+ export { o as Pagination };
95
+
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Pagination","forwardRef","rest","labelId","useId","pageCount","totalResults","pageSize","currentPage","page","disabled","isDisabled","atStart","atEnd","start","end","go","next","nextPage","onChange","size","className","Button","showLabels","Select","pageSizeOptions","value","nextSize","nextPageCount"],"sources":["../../../src/components/Pagination/index.tsx"],"sourcesContent":["import { forwardRef, useId, type HTMLAttributes } from \"react\";\nimport { Button } from \"../Button\";\nimport { Select } from \"../Select\";\nimport type { PopoverPlacement } from \"../Popover\";\nimport \"./style.css\";\n\nexport type PaginationSize = \"sm\" | \"md\";\n\nexport interface PaginationState {\n /** One-based page number. */\n page: number;\n /** Positive integer results per page. */\n pageSize: number;\n}\n\nexport interface PaginationProps\n extends\n Omit<HTMLAttributes<HTMLElement>, \"children\" | \"onChange\">,\n PaginationState {\n /** Total number of matching results, before pagination. */\n totalResults: number;\n /** Emitted once per user change, with both values ready to apply together. */\n onChange: (next: PaginationState) => void;\n /** Nonempty list of positive integers containing the current pageSize. */\n pageSizeOptions?: number[];\n size?: PaginationSize;\n isDisabled?: boolean;\n showLabels?: boolean;\n menuPlacement?: PopoverPlacement;\n}\n\n/** Controlled navigation for a result set. Data loading and slicing belong to the application. */\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(\n function Pagination(\n {\n totalResults,\n page,\n pageSize,\n onChange,\n pageSizeOptions = [10, 25, 50, 100],\n size = \"sm\",\n isDisabled = false,\n showLabels = true,\n menuPlacement = \"bottom\",\n className,\n ...rest\n },\n ref,\n ) {\n const labelId = useId();\n const pageCount = Math.max(1, Math.ceil(totalResults / pageSize));\n const currentPage = Math.min(Math.max(1, page), pageCount);\n const disabled = isDisabled || totalResults === 0;\n const atStart = disabled || currentPage === 1;\n const atEnd = disabled || currentPage === pageCount;\n const start = (currentPage - 1) * pageSize + 1;\n const end = Math.min(currentPage * pageSize, totalResults);\n\n const go = (nextPage: number) => {\n const next = Math.min(Math.max(1, nextPage), pageCount);\n if (next !== currentPage) onChange({ page: next, pageSize });\n };\n\n return (\n <nav\n ref={ref}\n aria-label=\"Pagination\"\n data-size={size}\n className={[\"ds-pagination\", className].filter(Boolean).join(\" \")}\n {...rest}\n >\n <div className=\"ds-pagination__actions\">\n <Button\n variant=\"neutral\"\n size={size}\n iconStart=\"chevron-left\"\n isIconOnly={!showLabels}\n aria-label=\"Previous page\"\n isDisabled={atStart}\n onClick={() => go(currentPage - 1)}\n >\n Previous\n </Button>\n </div>\n\n <div className=\"ds-pagination__centre\">\n <div className=\"ds-pagination__per-page\">\n <span id={labelId}>Per page</span>\n <div className=\"ds-pagination__select\">\n <Select\n aria-labelledby={labelId}\n value={String(pageSize)}\n options={pageSizeOptions.map((value) => ({\n value: String(value),\n label: String(value),\n }))}\n size={size}\n menuPlacement={menuPlacement}\n isDisabled={\n disabled || totalResults <= Math.min(...pageSizeOptions)\n }\n onValueChange={(value) => {\n const nextSize = Number(value);\n if (nextSize === pageSize) return;\n const nextPage =\n Math.floor(((currentPage - 1) * pageSize) / nextSize) + 1;\n const nextPageCount = Math.max(\n 1,\n Math.ceil(totalResults / nextSize),\n );\n onChange({\n page: Math.min(nextPage, nextPageCount),\n pageSize: nextSize,\n });\n }}\n />\n </div>\n </div>\n <span\n className=\"ds-pagination__range\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n {totalResults === 0\n ? \"No results\"\n : `${start.toLocaleString(\"en-US\")}–${end.toLocaleString(\"en-US\")} of ${totalResults.toLocaleString(\"en-US\")}`}\n </span>\n </div>\n\n <div className=\"ds-pagination__actions ds-pagination__actions--next\">\n <Button\n variant=\"neutral\"\n size={size}\n iconStart={showLabels ? undefined : \"chevron-right\"}\n iconEnd={showLabels ? \"chevron-right\" : undefined}\n isIconOnly={!showLabels}\n aria-label=\"Next page\"\n isDisabled={atEnd}\n onClick={() => go(currentPage + 1)}\n >\n Next\n </Button>\n </div>\n </nav>\n );\n },\n);\n"],"mappings":";;;;;AAgCA,IAAaA,IAAaC,EACxB,SACE,EACE,iBACA,SACA,aACA,aACA,qBAAkB;CAAC;CAAI;CAAI;CAAI;AAAG,GAClC,UAAO,MACP,gBAAa,IACb,gBAAa,IACb,mBAAgB,UAChB,cACA,GAAGC,KAEL,GACA;CACA,IAAMC,IAAUC,EAAM,GAChBC,IAAY,KAAK,IAAI,GAAG,KAAK,KAAKC,IAAeC,CAAQ,CAAC,GAC1DC,IAAc,KAAK,IAAI,KAAK,IAAI,GAAGC,CAAI,GAAGJ,CAAS,GACnDK,IAAWC,KAAcL,MAAiB,GAC1CM,IAAUF,KAAYF,MAAgB,GACtCK,IAAQH,KAAYF,MAAgBH,GACpCS,KAASN,IAAc,KAAKD,IAAW,GACvCQ,IAAM,KAAK,IAAIP,IAAcD,GAAUD,CAAY,GAEnDU,KAAM,MAAqB;EAC/B,IAAMC,IAAO,KAAK,IAAI,KAAK,IAAI,GAAGC,CAAQ,GAAGb,CAAS;EACtD,AAAIY,MAAST,KAAaW,EAAS;GAAE,MAAMF;GAAM;EAAS,CAAC;CAC7D;CAEA,OACE,kBAAC,OAAD;EACO;EACL,cAAW;EACX,aAAWG;EACX,WAAW,CAAC,iBAAiBC,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAChE,GAAInB;EALN,UAAA;GAOE,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAACoB,GAAD;KACE,SAAQ;KACF;KACN,WAAU;KACV,YAAY,CAACC;KACb,cAAW;KACX,YAAYX;KACZ,eAAeI,EAAGR,IAAc,CAAC;KAClC,UAAA;IAEO,CAAA;GACL,CAAA;GAEL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,QAAD;MAAM,IAAIL;MAAS,UAAA;KAAc,CAAA,GACjC,kBAAC,OAAD;MAAK,WAAU;MACb,UAAA,kBAACqB,GAAD;OACE,mBAAiBrB;OACjB,OAAO,OAAOI,CAAQ;OACtB,SAASkB,EAAgB,KAAK,OAAW;QACvC,OAAO,OAAOC,CAAK;QACnB,OAAO,OAAOA,CAAK;OACrB,EAAE;OACI;OACS;OACf,YACEhB,KAAYJ,KAAgB,KAAK,IAAI,GAAGmB,CAAe;OAEzD,gBAAgB,MAAU;QACxB,IAAME,IAAW,OAAOD,CAAK;QAC7B,IAAIC,MAAapB,GAAU;QAC3B,IAAMW,IACJ,KAAK,OAAQV,IAAc,KAAKD,IAAYoB,CAAQ,IAAI,GACpDC,IAAgB,KAAK,IACzB,GACA,KAAK,KAAKtB,IAAeqB,CAAQ,CACnC;QACA,EAAS;SACP,MAAM,KAAK,IAAIT,GAAUU,CAAa;SACtC,UAAUD;QACZ,CAAC;OACH;MACD,CAAA;KACE,CAAA,CACF;IACL,CAAA,GAAA,kBAAC,QAAD;KACE,WAAU;KACV,aAAU;KACV,eAAY;KAEX,UAAArB,MAAiB,IACd,eACA,GAAGQ,EAAM,eAAe,OAAO,EAAE,GAAGC,EAAI,eAAe,OAAO,EAAE,MAAMT,EAAa,eAAe,OAAO;IACzG,CAAA,CACH;;GAEL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAACgB,GAAD;KACE,SAAQ;KACF;KACN,WAAWC,IAAa,KAAA,IAAY;KACpC,SAASA,IAAa,kBAAkB,KAAA;KACxC,YAAY,CAACA;KACb,cAAW;KACX,YAAYV;KACZ,eAAeG,EAAGR,IAAc,CAAC;KAClC,UAAA;IAEO,CAAA;GACL,CAAA;EACF;;AAET,CACF"}
@@ -0,0 +1,52 @@
1
+ @layer components {
2
+ .ds-pagination {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ align-items: center;
6
+ justify-content: space-between;
7
+ gap: var(--space-4);
8
+ padding: var(--space-3) var(--space-5);
9
+ font-family: var(--font-sans);
10
+ color: var(--color-text);
11
+ }
12
+
13
+ .ds-pagination__actions {
14
+ flex: none;
15
+ align-self: center;
16
+ }
17
+
18
+ .ds-pagination__actions--next {
19
+ margin-inline-start: auto;
20
+ }
21
+
22
+ .ds-pagination__centre {
23
+ display: flex;
24
+ flex: 1 1 15rem;
25
+ flex-wrap: wrap;
26
+ align-items: center;
27
+ justify-content: center;
28
+ min-inline-size: 0;
29
+ gap: var(--space-2) var(--space-6);
30
+ }
31
+
32
+ .ds-pagination__per-page {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: var(--space-2);
36
+ color: var(--color-text-muted);
37
+ font-size: var(--font-size-sm);
38
+ white-space: nowrap;
39
+ }
40
+
41
+ .ds-pagination__select {
42
+ inline-size: 5rem;
43
+ flex: none;
44
+ }
45
+
46
+ .ds-pagination__range {
47
+ color: var(--color-text-muted);
48
+ font-size: var(--font-size-sm);
49
+ font-variant-numeric: tabular-nums;
50
+ white-space: nowrap;
51
+ }
52
+ }
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("react"),t=require("react/jsx-runtime"),n=require("react-dom");function r(...e){return e.filter(Boolean).join(` `)}var i=8;function a({anchorRef:a,anchorId:o,isOpen:s,align:c=`start`,matchAnchorWidth:l=!1,offset:u=4,className:d,children:f,role:p,id:m,panelRef:h,...g}){let _=(0,e.useRef)(null),v=(0,e.useId)(),y=m??v,b=(0,e.useCallback)(()=>{let e=a.current??(o?document.getElementById(o):null),t=_.current;if(!e||!t)return;let n=e.getBoundingClientRect();l&&(t.style.width=`${n.width}px`);let r=t.getBoundingClientRect(),s=document.documentElement.clientWidth,d=document.documentElement.clientHeight,f=d-n.bottom-u-i,p=n.top-u-i,m=f<r.height&&p>f,h=Math.max(120,m?p:f),g=m?Math.max(i,n.top-u-Math.min(r.height,h)):Math.min(n.bottom+u,d-i),v=c===`end`?n.right-r.width:n.left,y=Math.max(i,Math.min(v,s-r.width-i));t.style.left=`${Math.round(y)}px`,t.style.top=`${Math.round(g)}px`,t.style.setProperty(`--popover-max-block-size`,`${Math.round(h)}px`),t.style.visibility=`visible`},[c,o,a,l,u]);if((0,e.useEffect)(()=>{if(!s)return;let e=document.querySelector(`[data-popover-instance="${CSS.escape(v)}"]`);_.current=e,h&&(h.current=e),b();let t=()=>b();return window.addEventListener(`resize`,t),window.addEventListener(`scroll`,t,!0),()=>{window.removeEventListener(`resize`,t),window.removeEventListener(`scroll`,t,!0),_.current=null,h&&(h.current=null)}},[v,s,y,h,b]),!s||typeof document>`u`)return null;let x=(0,t.jsx)(`div`,{id:y,"data-popover-instance":v,role:p,className:r(`ds-popover`,d),...g,children:f});return(0,n.createPortal)(x,document.body)}exports.Popover=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("react"),t=require("react/jsx-runtime"),n=require("react-dom");function r(...e){return e.filter(Boolean).join(` `)}var i=8;function a({anchorRef:a,anchorId:o,isOpen:s,align:c=`start`,placement:l=`bottom`,matchAnchorWidth:u=!1,offset:d=4,className:f,children:p,role:m,id:h,panelRef:g,..._}){let v=(0,e.useRef)(null),y=(0,e.useId)(),b=h??y,x=(0,e.useCallback)(()=>{let e=a.current??(o?document.getElementById(o):null),t=v.current;if(!e||!t)return;let n=e.getBoundingClientRect();u&&(t.style.width=`${n.width}px`);let r=t.getBoundingClientRect(),s=document.documentElement.clientWidth,f=document.documentElement.clientHeight,p=f-n.bottom-d-i,m=n.top-d-i,h=l===`top`?m>=r.height||m>p:p<r.height&&m>p,g=Math.max(120,h?m:p),_=h?Math.max(i,n.top-d-Math.min(r.height,g)):Math.min(n.bottom+d,f-i),y=c===`end`?n.right-r.width:n.left,b=Math.max(i,Math.min(y,s-r.width-i));t.style.left=`${Math.round(b)}px`,t.style.top=`${Math.round(_)}px`,t.style.setProperty(`--popover-max-block-size`,`${Math.round(g)}px`),t.style.visibility=`visible`},[c,o,a,u,d,l]);if((0,e.useEffect)(()=>{if(!s)return;let e=document.querySelector(`[data-popover-instance="${CSS.escape(y)}"]`);v.current=e,g&&(g.current=e),x();let t=()=>x();return window.addEventListener(`resize`,t),window.addEventListener(`scroll`,t,!0),()=>{window.removeEventListener(`resize`,t),window.removeEventListener(`scroll`,t,!0),v.current=null,g&&(g.current=null)}},[y,s,b,g,x]),!s||typeof document>`u`)return null;let S=(0,t.jsx)(`div`,{id:b,"data-popover-instance":y,role:m,className:r(`ds-popover`,f),..._,children:p});return(0,n.createPortal)(S,document.body)}exports.Popover=a;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["useRef","useId","useCallback","createPortal","react","react_jsx_runtime","react_dom","cx","parts","VIEWPORT_MARGIN","Popover","rest","floatingRef","generatedId","panelId","id","place","reference","anchorRef","anchorId","floating","anchor","matchAnchorWidth","panel","viewportWidth","viewportHeight","roomBelow","offset","roomAbove","placeAbove","availableHeight","top","preferredLeft","align","left","isOpen","panelRef","update","className"],"sources":["../../../src/components/Popover/index.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nconst VIEWPORT_MARGIN = 8;\n\nexport type PopoverAlign = \"start\" | \"end\";\n\nexport interface PopoverProps {\n /** The control the panel hangs off. */\n anchorRef: RefObject<HTMLElement | null>;\n /** Optional DOM id fallback for composed controls whose refs are consumed by a field wrapper. */\n anchorId?: string;\n isOpen: boolean;\n /** Which edge of the anchor the panel lines up with. Flips when it must. */\n align?: PopoverAlign;\n /** Match the anchor's width — for listboxes that read as one field. */\n matchAnchorWidth?: boolean;\n /** Gap between anchor and panel. */\n offset?: number;\n className?: string;\n children: ReactNode;\n role?: string;\n id?: string;\n \"aria-label\"?: string;\n panelRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * A panel anchored to a control. It is positioned against the viewport, so it\n * flips above the anchor when the space below runs out and slides inward\n * rather than being cut off at any edge.\n */\nexport function Popover({\n anchorRef,\n anchorId,\n isOpen,\n align = \"start\",\n matchAnchorWidth = false,\n offset = 4,\n className,\n children,\n role,\n id,\n panelRef,\n ...rest\n}: PopoverProps) {\n const floatingRef = useRef<HTMLDivElement | null>(null);\n const generatedId = useId();\n const panelId = id ?? generatedId;\n\n const place = useCallback(() => {\n const reference = anchorRef.current ?? (anchorId ? document.getElementById(anchorId) : null);\n const floating = floatingRef.current;\n if (!reference || !floating) return;\n\n const anchor = reference.getBoundingClientRect();\n if (matchAnchorWidth) floating.style.width = `${anchor.width}px`;\n const panel = floating.getBoundingClientRect();\n const viewportWidth = document.documentElement.clientWidth;\n const viewportHeight = document.documentElement.clientHeight;\n const roomBelow = viewportHeight - anchor.bottom - offset - VIEWPORT_MARGIN;\n const roomAbove = anchor.top - offset - VIEWPORT_MARGIN;\n const placeAbove = roomBelow < panel.height && roomAbove > roomBelow;\n const availableHeight = Math.max(120, placeAbove ? roomAbove : roomBelow);\n const top = placeAbove\n ? Math.max(VIEWPORT_MARGIN, anchor.top - offset - Math.min(panel.height, availableHeight))\n : Math.min(anchor.bottom + offset, viewportHeight - VIEWPORT_MARGIN);\n const preferredLeft = align === \"end\" ? anchor.right - panel.width : anchor.left;\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(preferredLeft, viewportWidth - panel.width - VIEWPORT_MARGIN),\n );\n\n floating.style.left = `${Math.round(left)}px`;\n floating.style.top = `${Math.round(top)}px`;\n floating.style.setProperty(\"--popover-max-block-size\", `${Math.round(availableHeight)}px`);\n floating.style.visibility = \"visible\";\n }, [align, anchorId, anchorRef, matchAnchorWidth, offset]);\n\n useEffect(() => {\n if (!isOpen) return;\n const floating = document.querySelector<HTMLDivElement>(\n `[data-popover-instance=\"${CSS.escape(generatedId)}\"]`,\n );\n floatingRef.current = floating;\n if (panelRef) panelRef.current = floating;\n place();\n const update = () => place();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n floatingRef.current = null;\n if (panelRef) panelRef.current = null;\n };\n }, [generatedId, isOpen, panelId, panelRef, place]);\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const panel = (\n <div\n id={panelId}\n data-popover-instance={generatedId}\n role={role}\n className={cx(\"ds-popover\", className)}\n {...rest}\n >\n {children}\n </div>\n );\n\n return createPortal(panel, document.body);\n}\n"],"mappings":"A,gJAIA,SAASO,EAAG,GAAGC,EAAuC,CACpD,OAAOA,EAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACvC,CAEA,IAAMC,EAAkB,EA6BxB,SAAgBC,EAAQ,CACtB,YACA,WACA,SACA,QAAQ,QACR,mBAAmB,GACnB,SAAS,EACT,YACA,WACA,OACA,KACA,WACA,GAAGC,GACY,CACf,IAAMC,GAAA,EAAcZ,EAAAA,OAAAA,CAA8B,IAAI,EAChDa,GAAA,EAAcZ,EAAAA,MAAAA,CAAM,EACpBa,EAAUC,GAAMF,EAEhBG,GAAA,EAAQd,EAAAA,YAAAA,KAAkB,CAC9B,IAAMe,EAAYC,EAAU,UAAYC,EAAW,SAAS,eAAeA,CAAQ,EAAI,MACjFC,EAAWR,EAAY,QAC7B,GAAI,CAACK,GAAa,CAACG,EAAU,OAE7B,IAAMC,EAASJ,EAAU,sBAAsB,EAC3CK,IAAkB,EAAS,MAAM,MAAQ,GAAGD,EAAO,MAAM,KAC7D,IAAME,EAAQH,EAAS,sBAAsB,EACvCI,EAAgB,SAAS,gBAAgB,YACzCC,EAAiB,SAAS,gBAAgB,aAC1CC,EAAYD,EAAiBJ,EAAO,OAASM,EAASlB,EACtDmB,EAAYP,EAAO,IAAMM,EAASlB,EAClCoB,EAAaH,EAAYH,EAAM,QAAUK,EAAYF,EACrDI,EAAkB,KAAK,IAAI,IAAKD,EAAaD,EAAYF,CAAS,EAClEK,EAAMF,EACR,KAAK,IAAIpB,EAAiBY,EAAO,IAAMM,EAAS,KAAK,IAAIJ,EAAM,OAAQO,CAAe,CAAC,EACvF,KAAK,IAAIT,EAAO,OAASM,EAAQF,EAAiBhB,CAAe,EAC/DuB,EAAgBC,IAAU,MAAQZ,EAAO,MAAQE,EAAM,MAAQF,EAAO,KACtEa,EAAO,KAAK,IAChBzB,EACA,KAAK,IAAIuB,EAAeR,EAAgBD,EAAM,MAAQd,CAAe,CACvE,EAEA,EAAS,MAAM,KAAO,GAAG,KAAK,MAAMyB,CAAI,EAAE,IAC1C,EAAS,MAAM,IAAM,GAAG,KAAK,MAAMH,CAAG,EAAE,IACxCX,EAAS,MAAM,YAAY,2BAA4B,GAAG,KAAK,MAAMU,CAAe,EAAE,GAAG,EACzF,EAAS,MAAM,WAAa,SAC9B,EAAG,CAACG,EAAOd,EAAUD,EAAWI,EAAkBK,CAAM,CAAC,EAqBzD,IAnBA,EAAAvB,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC+B,EAAQ,OACb,IAAMf,EAAW,SAAS,cACxB,2BAA2B,IAAI,OAAOP,CAAW,EAAE,GACrD,EACA,EAAY,QAAUO,EAClBgB,IAAU,EAAS,QAAUhB,GACjCJ,EAAM,EACN,IAAMqB,MAAerB,EAAM,EAG3B,OAFA,OAAO,iBAAiB,SAAUqB,CAAM,EACxC,OAAO,iBAAiB,SAAUA,EAAQ,EAAI,MACjC,CACX,OAAO,oBAAoB,SAAUA,CAAM,EAC3C,OAAO,oBAAoB,SAAUA,EAAQ,EAAI,EACjD,EAAY,QAAU,KAClBD,IAAU,EAAS,QAAU,KACnC,CACF,EAAG,CAACvB,EAAasB,EAAQrB,EAASsB,EAAUpB,CAAK,CAAC,EAE9C,CAACmB,GAAU,OAAO,SAAa,IAAa,OAAO,KAEvD,IAAMZ,GACJ,EAAAlB,EAAA,IAAA,CAAC,MAAD,CACE,GAAIS,EACJ,wBAAuBD,EACjB,OACN,UAAWN,EAAG,aAAc+B,CAAS,EACrC,GAAI3B,EAEH,UACE,CAAA,EAGP,OAAA,EAAOR,EAAAA,aAAAA,CAAaoB,EAAO,SAAS,IAAI,CAC1C,C"}
1
+ {"version":3,"file":"index.cjs","names":["useRef","useId","useCallback","createPortal","react","react_jsx_runtime","react_dom","cx","parts","VIEWPORT_MARGIN","Popover","rest","floatingRef","generatedId","panelId","id","place","reference","anchorRef","anchorId","floating","anchor","matchAnchorWidth","panel","viewportWidth","viewportHeight","roomBelow","offset","roomAbove","placeAbove","placement","availableHeight","top","preferredLeft","align","left","isOpen","panelRef","update","className"],"sources":["../../../src/components/Popover/index.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nconst VIEWPORT_MARGIN = 8;\n\nexport type PopoverAlign = \"start\" | \"end\";\nexport type PopoverPlacement = \"top\" | \"bottom\";\n\nexport interface PopoverProps {\n /** The control the panel hangs off. */\n anchorRef: RefObject<HTMLElement | null>;\n /** Optional DOM id fallback for composed controls whose refs are consumed by a field wrapper. */\n anchorId?: string;\n isOpen: boolean;\n /** Which edge of the anchor the panel lines up with. Flips when it must. */\n align?: PopoverAlign;\n /** Preferred side of the anchor. Flips when the other side has more room. */\n placement?: PopoverPlacement;\n /** Match the anchor's width — for listboxes that read as one field. */\n matchAnchorWidth?: boolean;\n /** Gap between anchor and panel. */\n offset?: number;\n className?: string;\n children: ReactNode;\n role?: string;\n id?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n panelRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * A panel anchored to a control. It is positioned against the viewport, so it\n * flips above the anchor when the space below runs out and slides inward\n * rather than being cut off at any edge.\n */\nexport function Popover({\n anchorRef,\n anchorId,\n isOpen,\n align = \"start\",\n placement = \"bottom\",\n matchAnchorWidth = false,\n offset = 4,\n className,\n children,\n role,\n id,\n panelRef,\n ...rest\n}: PopoverProps) {\n const floatingRef = useRef<HTMLDivElement | null>(null);\n const generatedId = useId();\n const panelId = id ?? generatedId;\n\n const place = useCallback(() => {\n const reference = anchorRef.current ?? (anchorId ? document.getElementById(anchorId) : null);\n const floating = floatingRef.current;\n if (!reference || !floating) return;\n\n const anchor = reference.getBoundingClientRect();\n if (matchAnchorWidth) floating.style.width = `${anchor.width}px`;\n const panel = floating.getBoundingClientRect();\n const viewportWidth = document.documentElement.clientWidth;\n const viewportHeight = document.documentElement.clientHeight;\n const roomBelow = viewportHeight - anchor.bottom - offset - VIEWPORT_MARGIN;\n const roomAbove = anchor.top - offset - VIEWPORT_MARGIN;\n const placeAbove = placement === \"top\"\n ? roomAbove >= panel.height || roomAbove > roomBelow\n : roomBelow < panel.height && roomAbove > roomBelow;\n const availableHeight = Math.max(120, placeAbove ? roomAbove : roomBelow);\n const top = placeAbove\n ? Math.max(VIEWPORT_MARGIN, anchor.top - offset - Math.min(panel.height, availableHeight))\n : Math.min(anchor.bottom + offset, viewportHeight - VIEWPORT_MARGIN);\n const preferredLeft = align === \"end\" ? anchor.right - panel.width : anchor.left;\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(preferredLeft, viewportWidth - panel.width - VIEWPORT_MARGIN),\n );\n\n floating.style.left = `${Math.round(left)}px`;\n floating.style.top = `${Math.round(top)}px`;\n floating.style.setProperty(\"--popover-max-block-size\", `${Math.round(availableHeight)}px`);\n floating.style.visibility = \"visible\";\n }, [align, anchorId, anchorRef, matchAnchorWidth, offset, placement]);\n\n useEffect(() => {\n if (!isOpen) return;\n const floating = document.querySelector<HTMLDivElement>(\n `[data-popover-instance=\"${CSS.escape(generatedId)}\"]`,\n );\n floatingRef.current = floating;\n if (panelRef) panelRef.current = floating;\n place();\n const update = () => place();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n floatingRef.current = null;\n if (panelRef) panelRef.current = null;\n };\n }, [generatedId, isOpen, panelId, panelRef, place]);\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const panel = (\n <div\n id={panelId}\n data-popover-instance={generatedId}\n role={role}\n className={cx(\"ds-popover\", className)}\n {...rest}\n >\n {children}\n </div>\n );\n\n return createPortal(panel, document.body);\n}\n"],"mappings":"A,gJAIA,SAASO,EAAG,GAAGC,EAAuC,CACpD,OAAOA,EAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACvC,CAEA,IAAMC,EAAkB,EAiCxB,SAAgBC,EAAQ,CACtB,YACA,WACA,SACA,QAAQ,QACR,YAAY,SACZ,mBAAmB,GACnB,SAAS,EACT,YACA,WACA,OACA,KACA,WACA,GAAGC,GACY,CACf,IAAMC,GAAA,EAAcZ,EAAAA,OAAAA,CAA8B,IAAI,EAChDa,GAAA,EAAcZ,EAAAA,MAAAA,CAAM,EACpBa,EAAUC,GAAMF,EAEhBG,GAAA,EAAQd,EAAAA,YAAAA,KAAkB,CAC9B,IAAMe,EAAYC,EAAU,UAAYC,EAAW,SAAS,eAAeA,CAAQ,EAAI,MACjFC,EAAWR,EAAY,QAC7B,GAAI,CAACK,GAAa,CAACG,EAAU,OAE7B,IAAMC,EAASJ,EAAU,sBAAsB,EAC3CK,IAAkB,EAAS,MAAM,MAAQ,GAAGD,EAAO,MAAM,KAC7D,IAAME,EAAQH,EAAS,sBAAsB,EACvCI,EAAgB,SAAS,gBAAgB,YACzCC,EAAiB,SAAS,gBAAgB,aAC1CC,EAAYD,EAAiBJ,EAAO,OAASM,EAASlB,EACtDmB,EAAYP,EAAO,IAAMM,EAASlB,EAClCoB,EAAaC,IAAc,MAC7BF,GAAaL,EAAM,QAAUK,EAAYF,EACzCA,EAAYH,EAAM,QAAUK,EAAYF,EACtCK,EAAkB,KAAK,IAAI,IAAKF,EAAaD,EAAYF,CAAS,EAClEM,EAAMH,EACR,KAAK,IAAIpB,EAAiBY,EAAO,IAAMM,EAAS,KAAK,IAAIJ,EAAM,OAAQQ,CAAe,CAAC,EACvF,KAAK,IAAIV,EAAO,OAASM,EAAQF,EAAiBhB,CAAe,EAC/DwB,EAAgBC,IAAU,MAAQb,EAAO,MAAQE,EAAM,MAAQF,EAAO,KACtEc,EAAO,KAAK,IAChB1B,EACA,KAAK,IAAIwB,EAAeT,EAAgBD,EAAM,MAAQd,CAAe,CACvE,EAEA,EAAS,MAAM,KAAO,GAAG,KAAK,MAAM0B,CAAI,EAAE,IAC1C,EAAS,MAAM,IAAM,GAAG,KAAK,MAAMH,CAAG,EAAE,IACxCZ,EAAS,MAAM,YAAY,2BAA4B,GAAG,KAAK,MAAMW,CAAe,EAAE,GAAG,EACzF,EAAS,MAAM,WAAa,SAC9B,EAAG,CAACG,EAAOf,EAAUD,EAAWI,EAAkBK,EAAQG,CAAS,CAAC,EAqBpE,IAnBA,EAAA1B,EAAA,UAAA,KAAgB,CACd,GAAI,CAACgC,EAAQ,OACb,IAAMhB,EAAW,SAAS,cACxB,2BAA2B,IAAI,OAAOP,CAAW,EAAE,GACrD,EACA,EAAY,QAAUO,EAClBiB,IAAU,EAAS,QAAUjB,GACjCJ,EAAM,EACN,IAAMsB,MAAetB,EAAM,EAG3B,OAFA,OAAO,iBAAiB,SAAUsB,CAAM,EACxC,OAAO,iBAAiB,SAAUA,EAAQ,EAAI,MACjC,CACX,OAAO,oBAAoB,SAAUA,CAAM,EAC3C,OAAO,oBAAoB,SAAUA,EAAQ,EAAI,EACjD,EAAY,QAAU,KAClBD,IAAU,EAAS,QAAU,KACnC,CACF,EAAG,CAACxB,EAAauB,EAAQtB,EAASuB,EAAUrB,CAAK,CAAC,EAE9C,CAACoB,GAAU,OAAO,SAAa,IAAa,OAAO,KAEvD,IAAMb,GACJ,EAAAlB,EAAA,IAAA,CAAC,MAAD,CACE,GAAIS,EACJ,wBAAuBD,EACjB,OACN,UAAWN,EAAG,aAAcgC,CAAS,EACrC,GAAI5B,EAEH,UACE,CAAA,EAGP,OAAA,EAAOR,EAAAA,aAAAA,CAAaoB,EAAO,SAAS,IAAI,CAC1C,C"}
@@ -1,5 +1,6 @@
1
1
  import { type ReactNode, type RefObject } from "react";
2
2
  export type PopoverAlign = "start" | "end";
3
+ export type PopoverPlacement = "top" | "bottom";
3
4
  export interface PopoverProps {
4
5
  /** The control the panel hangs off. */
5
6
  anchorRef: RefObject<HTMLElement | null>;
@@ -8,6 +9,8 @@ export interface PopoverProps {
8
9
  isOpen: boolean;
9
10
  /** Which edge of the anchor the panel lines up with. Flips when it must. */
10
11
  align?: PopoverAlign;
12
+ /** Preferred side of the anchor. Flips when the other side has more room. */
13
+ placement?: PopoverPlacement;
11
14
  /** Match the anchor's width — for listboxes that read as one field. */
12
15
  matchAnchorWidth?: boolean;
13
16
  /** Gap between anchor and panel. */
@@ -17,6 +20,7 @@ export interface PopoverProps {
17
20
  role?: string;
18
21
  id?: string;
19
22
  "aria-label"?: string;
23
+ "aria-labelledby"?: string;
20
24
  panelRef?: RefObject<HTMLDivElement | null>;
21
25
  }
22
26
  /**
@@ -24,5 +28,5 @@ export interface PopoverProps {
24
28
  * flips above the anchor when the space below runs out and slides inward
25
29
  * rather than being cut off at any edge.
26
30
  */
27
- export declare function Popover({ anchorRef, anchorId, isOpen, align, matchAnchorWidth, offset, className, children, role, id, panelRef, ...rest }: PopoverProps): import("react").ReactPortal | null;
31
+ export declare function Popover({ anchorRef, anchorId, isOpen, align, placement, matchAnchorWidth, offset, className, children, role, id, panelRef, ...rest }: PopoverProps): import("react").ReactPortal | null;
28
32
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Popover/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9F,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAe,EACf,gBAAwB,EACxB,MAAU,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,sCAoEd"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Popover/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9F,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAC3C,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAe,EACf,SAAoB,EACpB,gBAAwB,EACxB,MAAU,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,sCAsEd"}
@@ -1,5 +1,6 @@
1
1
  import { type ReactNode, type RefObject } from "react";
2
2
  export type PopoverAlign = "start" | "end";
3
+ export type PopoverPlacement = "top" | "bottom";
3
4
  export interface PopoverProps {
4
5
  /** The control the panel hangs off. */
5
6
  anchorRef: RefObject<HTMLElement | null>;
@@ -8,6 +9,8 @@ export interface PopoverProps {
8
9
  isOpen: boolean;
9
10
  /** Which edge of the anchor the panel lines up with. Flips when it must. */
10
11
  align?: PopoverAlign;
12
+ /** Preferred side of the anchor. Flips when the other side has more room. */
13
+ placement?: PopoverPlacement;
11
14
  /** Match the anchor's width — for listboxes that read as one field. */
12
15
  matchAnchorWidth?: boolean;
13
16
  /** Gap between anchor and panel. */
@@ -17,6 +20,7 @@ export interface PopoverProps {
17
20
  role?: string;
18
21
  id?: string;
19
22
  "aria-label"?: string;
23
+ "aria-labelledby"?: string;
20
24
  panelRef?: RefObject<HTMLDivElement | null>;
21
25
  }
22
26
  /**
@@ -24,5 +28,5 @@ export interface PopoverProps {
24
28
  * flips above the anchor when the space below runs out and slides inward
25
29
  * rather than being cut off at any edge.
26
30
  */
27
- export declare function Popover({ anchorRef, anchorId, isOpen, align, matchAnchorWidth, offset, className, children, role, id, panelRef, ...rest }: PopoverProps): import("react").ReactPortal | null;
31
+ export declare function Popover({ anchorRef, anchorId, isOpen, align, placement, matchAnchorWidth, offset, className, children, role, id, panelRef, ...rest }: PopoverProps): import("react").ReactPortal | null;
28
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Popover/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9F,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAe,EACf,gBAAwB,EACxB,MAAU,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,sCAoEd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Popover/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE9F,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAC3C,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,KAAe,EACf,SAAoB,EACpB,gBAAwB,EACxB,MAAU,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,sCAsEd"}
@@ -6,45 +6,46 @@ function o(...e) {
6
6
  return e.filter(Boolean).join(" ");
7
7
  }
8
8
  var s = 8;
9
- function c({ anchorRef: c, anchorId: l, isOpen: u, align: d = "start", matchAnchorWidth: f = !1, offset: p = 4, className: m, children: h, role: g, id: _, panelRef: v, ...y }) {
10
- let b = r(null), x = n(), S = _ ?? x, C = e(() => {
11
- let e = c.current ?? (l ? document.getElementById(l) : null), t = b.current;
9
+ function c({ anchorRef: c, anchorId: l, isOpen: u, align: d = "start", placement: f = "bottom", matchAnchorWidth: p = !1, offset: m = 4, className: h, children: g, role: _, id: v, panelRef: y, ...b }) {
10
+ let x = r(null), S = n(), C = v ?? S, w = e(() => {
11
+ let e = c.current ?? (l ? document.getElementById(l) : null), t = x.current;
12
12
  if (!e || !t) return;
13
13
  let n = e.getBoundingClientRect();
14
- f && (t.style.width = `${n.width}px`);
15
- let r = t.getBoundingClientRect(), i = document.documentElement.clientWidth, a = document.documentElement.clientHeight, o = a - n.bottom - p - s, u = n.top - p - s, m = o < r.height && u > o, h = Math.max(120, m ? u : o), g = m ? Math.max(s, n.top - p - Math.min(r.height, h)) : Math.min(n.bottom + p, a - s), _ = d === "end" ? n.right - r.width : n.left, v = Math.max(s, Math.min(_, i - r.width - s));
16
- t.style.left = `${Math.round(v)}px`, t.style.top = `${Math.round(g)}px`, t.style.setProperty("--popover-max-block-size", `${Math.round(h)}px`), t.style.visibility = "visible";
14
+ p && (t.style.width = `${n.width}px`);
15
+ let r = t.getBoundingClientRect(), i = document.documentElement.clientWidth, a = document.documentElement.clientHeight, o = a - n.bottom - m - s, u = n.top - m - s, h = f === "top" ? u >= r.height || u > o : o < r.height && u > o, g = Math.max(120, h ? u : o), _ = h ? Math.max(s, n.top - m - Math.min(r.height, g)) : Math.min(n.bottom + m, a - s), v = d === "end" ? n.right - r.width : n.left, y = Math.max(s, Math.min(v, i - r.width - s));
16
+ t.style.left = `${Math.round(y)}px`, t.style.top = `${Math.round(_)}px`, t.style.setProperty("--popover-max-block-size", `${Math.round(g)}px`), t.style.visibility = "visible";
17
17
  }, [
18
18
  d,
19
19
  l,
20
20
  c,
21
- f,
22
- p
21
+ p,
22
+ m,
23
+ f
23
24
  ]);
24
25
  if (t(() => {
25
26
  if (!u) return;
26
- let e = document.querySelector(`[data-popover-instance="${CSS.escape(x)}"]`);
27
- b.current = e, v && (v.current = e), C();
28
- let t = () => C();
27
+ let e = document.querySelector(`[data-popover-instance="${CSS.escape(S)}"]`);
28
+ x.current = e, y && (y.current = e), w();
29
+ let t = () => w();
29
30
  return window.addEventListener("resize", t), window.addEventListener("scroll", t, !0), () => {
30
- window.removeEventListener("resize", t), window.removeEventListener("scroll", t, !0), b.current = null, v && (v.current = null);
31
+ window.removeEventListener("resize", t), window.removeEventListener("scroll", t, !0), x.current = null, y && (y.current = null);
31
32
  };
32
33
  }, [
33
- x,
34
- u,
35
34
  S,
36
- v,
37
- C
35
+ u,
36
+ C,
37
+ y,
38
+ w
38
39
  ]), !u || typeof document > "u") return null;
39
- let w = /* @__PURE__ */ i("div", {
40
- id: S,
41
- "data-popover-instance": x,
42
- role: g,
43
- className: o("ds-popover", m),
44
- ...y,
45
- children: h
40
+ let T = /* @__PURE__ */ i("div", {
41
+ id: C,
42
+ "data-popover-instance": S,
43
+ role: _,
44
+ className: o("ds-popover", h),
45
+ ...b,
46
+ children: g
46
47
  });
47
- return a(w, document.body);
48
+ return a(T, document.body);
48
49
  }
49
50
  //#endregion
50
51
  export { c as Popover };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["cx","parts","VIEWPORT_MARGIN","Popover","rest","floatingRef","useRef","generatedId","useId","panelId","id","place","useCallback","reference","anchorRef","anchorId","floating","anchor","matchAnchorWidth","panel","viewportWidth","viewportHeight","roomBelow","offset","roomAbove","placeAbove","availableHeight","top","preferredLeft","align","left","useEffect","isOpen","panelRef","update","className","createPortal"],"sources":["../../../src/components/Popover/index.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nconst VIEWPORT_MARGIN = 8;\n\nexport type PopoverAlign = \"start\" | \"end\";\n\nexport interface PopoverProps {\n /** The control the panel hangs off. */\n anchorRef: RefObject<HTMLElement | null>;\n /** Optional DOM id fallback for composed controls whose refs are consumed by a field wrapper. */\n anchorId?: string;\n isOpen: boolean;\n /** Which edge of the anchor the panel lines up with. Flips when it must. */\n align?: PopoverAlign;\n /** Match the anchor's width — for listboxes that read as one field. */\n matchAnchorWidth?: boolean;\n /** Gap between anchor and panel. */\n offset?: number;\n className?: string;\n children: ReactNode;\n role?: string;\n id?: string;\n \"aria-label\"?: string;\n panelRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * A panel anchored to a control. It is positioned against the viewport, so it\n * flips above the anchor when the space below runs out and slides inward\n * rather than being cut off at any edge.\n */\nexport function Popover({\n anchorRef,\n anchorId,\n isOpen,\n align = \"start\",\n matchAnchorWidth = false,\n offset = 4,\n className,\n children,\n role,\n id,\n panelRef,\n ...rest\n}: PopoverProps) {\n const floatingRef = useRef<HTMLDivElement | null>(null);\n const generatedId = useId();\n const panelId = id ?? generatedId;\n\n const place = useCallback(() => {\n const reference = anchorRef.current ?? (anchorId ? document.getElementById(anchorId) : null);\n const floating = floatingRef.current;\n if (!reference || !floating) return;\n\n const anchor = reference.getBoundingClientRect();\n if (matchAnchorWidth) floating.style.width = `${anchor.width}px`;\n const panel = floating.getBoundingClientRect();\n const viewportWidth = document.documentElement.clientWidth;\n const viewportHeight = document.documentElement.clientHeight;\n const roomBelow = viewportHeight - anchor.bottom - offset - VIEWPORT_MARGIN;\n const roomAbove = anchor.top - offset - VIEWPORT_MARGIN;\n const placeAbove = roomBelow < panel.height && roomAbove > roomBelow;\n const availableHeight = Math.max(120, placeAbove ? roomAbove : roomBelow);\n const top = placeAbove\n ? Math.max(VIEWPORT_MARGIN, anchor.top - offset - Math.min(panel.height, availableHeight))\n : Math.min(anchor.bottom + offset, viewportHeight - VIEWPORT_MARGIN);\n const preferredLeft = align === \"end\" ? anchor.right - panel.width : anchor.left;\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(preferredLeft, viewportWidth - panel.width - VIEWPORT_MARGIN),\n );\n\n floating.style.left = `${Math.round(left)}px`;\n floating.style.top = `${Math.round(top)}px`;\n floating.style.setProperty(\"--popover-max-block-size\", `${Math.round(availableHeight)}px`);\n floating.style.visibility = \"visible\";\n }, [align, anchorId, anchorRef, matchAnchorWidth, offset]);\n\n useEffect(() => {\n if (!isOpen) return;\n const floating = document.querySelector<HTMLDivElement>(\n `[data-popover-instance=\"${CSS.escape(generatedId)}\"]`,\n );\n floatingRef.current = floating;\n if (panelRef) panelRef.current = floating;\n place();\n const update = () => place();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n floatingRef.current = null;\n if (panelRef) panelRef.current = null;\n };\n }, [generatedId, isOpen, panelId, panelRef, place]);\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const panel = (\n <div\n id={panelId}\n data-popover-instance={generatedId}\n role={role}\n className={cx(\"ds-popover\", className)}\n {...rest}\n >\n {children}\n </div>\n );\n\n return createPortal(panel, document.body);\n}\n"],"mappings":";;;;AAIA,SAASA,EAAG,GAAGC,GAAuC;CACpD,OAAOA,EAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AACvC;AAEA,IAAMC,IAAkB;AA6BxB,SAAgBC,EAAQ,EACtB,cACA,aACA,WACA,WAAQ,SACR,sBAAmB,IACnB,YAAS,GACT,cACA,aACA,SACA,OACA,aACA,GAAGC,KACY;CACf,IAAMC,IAAcC,EAA8B,IAAI,GAChDC,IAAcC,EAAM,GACpBC,IAAUC,KAAMH,GAEhBI,IAAQC,QAAkB;EAC9B,IAAMC,IAAYC,EAAU,YAAYC,IAAW,SAAS,eAAeA,CAAQ,IAAI,OACjFC,IAAWX,EAAY;EAC7B,IAAI,CAACQ,KAAa,CAACG,GAAU;EAE7B,IAAMC,IAASJ,EAAU,sBAAsB;EAC/C,AAAIK,MAAkB,EAAS,MAAM,QAAQ,GAAGD,EAAO,MAAM;EAC7D,IAAME,IAAQH,EAAS,sBAAsB,GACvCI,IAAgB,SAAS,gBAAgB,aACzCC,IAAiB,SAAS,gBAAgB,cAC1CC,IAAYD,IAAiBJ,EAAO,SAASM,IAASrB,GACtDsB,IAAYP,EAAO,MAAMM,IAASrB,GAClCuB,IAAaH,IAAYH,EAAM,UAAUK,IAAYF,GACrDI,IAAkB,KAAK,IAAI,KAAKD,IAAaD,IAAYF,CAAS,GAClEK,IAAMF,IACR,KAAK,IAAIvB,GAAiBe,EAAO,MAAMM,IAAS,KAAK,IAAIJ,EAAM,QAAQO,CAAe,CAAC,IACvF,KAAK,IAAIT,EAAO,SAASM,GAAQF,IAAiBnB,CAAe,GAC/D0B,IAAgBC,MAAU,QAAQZ,EAAO,QAAQE,EAAM,QAAQF,EAAO,MACtEa,IAAO,KAAK,IAChB5B,GACA,KAAK,IAAI0B,GAAeR,IAAgBD,EAAM,QAAQjB,CAAe,CACvE;EAKA,AAHA,EAAS,MAAM,OAAO,GAAG,KAAK,MAAM4B,CAAI,EAAE,KAC1C,EAAS,MAAM,MAAM,GAAG,KAAK,MAAMH,CAAG,EAAE,KACxCX,EAAS,MAAM,YAAY,4BAA4B,GAAG,KAAK,MAAMU,CAAe,EAAE,GAAG,GACzF,EAAS,MAAM,aAAa;CAC9B,GAAG;EAACG;EAAOd;EAAUD;EAAWI;EAAkBK;CAAM,CAAC;CAqBzD,IAnBAQ,QAAgB;EACd,IAAI,CAACC,GAAQ;EACb,IAAMhB,IAAW,SAAS,cACxB,2BAA2B,IAAI,OAAOT,CAAW,EAAE,GACrD;EAGA,AAFA,EAAY,UAAUS,GAClBiB,MAAU,EAAS,UAAUjB,IACjCL,EAAM;EACN,IAAMuB,UAAevB,EAAM;EAG3B,OAFA,OAAO,iBAAiB,UAAUuB,CAAM,GACxC,OAAO,iBAAiB,UAAUA,GAAQ,EAAI,SACjC;GAIX,AAHA,OAAO,oBAAoB,UAAUA,CAAM,GAC3C,OAAO,oBAAoB,UAAUA,GAAQ,EAAI,GACjD,EAAY,UAAU,MAClBD,MAAU,EAAS,UAAU;EACnC;CACF,GAAG;EAAC1B;EAAayB;EAAQvB;EAASwB;EAAUtB;CAAK,CAAC,GAE9C,CAACqB,KAAU,OAAO,WAAa,KAAa,OAAO;CAEvD,IAAMb,IACJ,kBAAC,OAAD;EACE,IAAIV;EACJ,yBAAuBF;EACjB;EACN,WAAWP,EAAG,cAAcmC,CAAS;EACrC,GAAI/B;EAEH;CACE,CAAA;CAGP,OAAOgC,EAAajB,GAAO,SAAS,IAAI;AAC1C"}
1
+ {"version":3,"file":"index.js","names":["cx","parts","VIEWPORT_MARGIN","Popover","rest","floatingRef","useRef","generatedId","useId","panelId","id","place","useCallback","reference","anchorRef","anchorId","floating","anchor","matchAnchorWidth","panel","viewportWidth","viewportHeight","roomBelow","offset","roomAbove","placeAbove","placement","availableHeight","top","preferredLeft","align","left","useEffect","isOpen","panelRef","update","className","createPortal"],"sources":["../../../src/components/Popover/index.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useRef, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nconst VIEWPORT_MARGIN = 8;\n\nexport type PopoverAlign = \"start\" | \"end\";\nexport type PopoverPlacement = \"top\" | \"bottom\";\n\nexport interface PopoverProps {\n /** The control the panel hangs off. */\n anchorRef: RefObject<HTMLElement | null>;\n /** Optional DOM id fallback for composed controls whose refs are consumed by a field wrapper. */\n anchorId?: string;\n isOpen: boolean;\n /** Which edge of the anchor the panel lines up with. Flips when it must. */\n align?: PopoverAlign;\n /** Preferred side of the anchor. Flips when the other side has more room. */\n placement?: PopoverPlacement;\n /** Match the anchor's width — for listboxes that read as one field. */\n matchAnchorWidth?: boolean;\n /** Gap between anchor and panel. */\n offset?: number;\n className?: string;\n children: ReactNode;\n role?: string;\n id?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n panelRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * A panel anchored to a control. It is positioned against the viewport, so it\n * flips above the anchor when the space below runs out and slides inward\n * rather than being cut off at any edge.\n */\nexport function Popover({\n anchorRef,\n anchorId,\n isOpen,\n align = \"start\",\n placement = \"bottom\",\n matchAnchorWidth = false,\n offset = 4,\n className,\n children,\n role,\n id,\n panelRef,\n ...rest\n}: PopoverProps) {\n const floatingRef = useRef<HTMLDivElement | null>(null);\n const generatedId = useId();\n const panelId = id ?? generatedId;\n\n const place = useCallback(() => {\n const reference = anchorRef.current ?? (anchorId ? document.getElementById(anchorId) : null);\n const floating = floatingRef.current;\n if (!reference || !floating) return;\n\n const anchor = reference.getBoundingClientRect();\n if (matchAnchorWidth) floating.style.width = `${anchor.width}px`;\n const panel = floating.getBoundingClientRect();\n const viewportWidth = document.documentElement.clientWidth;\n const viewportHeight = document.documentElement.clientHeight;\n const roomBelow = viewportHeight - anchor.bottom - offset - VIEWPORT_MARGIN;\n const roomAbove = anchor.top - offset - VIEWPORT_MARGIN;\n const placeAbove = placement === \"top\"\n ? roomAbove >= panel.height || roomAbove > roomBelow\n : roomBelow < panel.height && roomAbove > roomBelow;\n const availableHeight = Math.max(120, placeAbove ? roomAbove : roomBelow);\n const top = placeAbove\n ? Math.max(VIEWPORT_MARGIN, anchor.top - offset - Math.min(panel.height, availableHeight))\n : Math.min(anchor.bottom + offset, viewportHeight - VIEWPORT_MARGIN);\n const preferredLeft = align === \"end\" ? anchor.right - panel.width : anchor.left;\n const left = Math.max(\n VIEWPORT_MARGIN,\n Math.min(preferredLeft, viewportWidth - panel.width - VIEWPORT_MARGIN),\n );\n\n floating.style.left = `${Math.round(left)}px`;\n floating.style.top = `${Math.round(top)}px`;\n floating.style.setProperty(\"--popover-max-block-size\", `${Math.round(availableHeight)}px`);\n floating.style.visibility = \"visible\";\n }, [align, anchorId, anchorRef, matchAnchorWidth, offset, placement]);\n\n useEffect(() => {\n if (!isOpen) return;\n const floating = document.querySelector<HTMLDivElement>(\n `[data-popover-instance=\"${CSS.escape(generatedId)}\"]`,\n );\n floatingRef.current = floating;\n if (panelRef) panelRef.current = floating;\n place();\n const update = () => place();\n window.addEventListener(\"resize\", update);\n window.addEventListener(\"scroll\", update, true);\n return () => {\n window.removeEventListener(\"resize\", update);\n window.removeEventListener(\"scroll\", update, true);\n floatingRef.current = null;\n if (panelRef) panelRef.current = null;\n };\n }, [generatedId, isOpen, panelId, panelRef, place]);\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const panel = (\n <div\n id={panelId}\n data-popover-instance={generatedId}\n role={role}\n className={cx(\"ds-popover\", className)}\n {...rest}\n >\n {children}\n </div>\n );\n\n return createPortal(panel, document.body);\n}\n"],"mappings":";;;;AAIA,SAASA,EAAG,GAAGC,GAAuC;CACpD,OAAOA,EAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AACvC;AAEA,IAAMC,IAAkB;AAiCxB,SAAgBC,EAAQ,EACtB,cACA,aACA,WACA,WAAQ,SACR,eAAY,UACZ,sBAAmB,IACnB,YAAS,GACT,cACA,aACA,SACA,OACA,aACA,GAAGC,KACY;CACf,IAAMC,IAAcC,EAA8B,IAAI,GAChDC,IAAcC,EAAM,GACpBC,IAAUC,KAAMH,GAEhBI,IAAQC,QAAkB;EAC9B,IAAMC,IAAYC,EAAU,YAAYC,IAAW,SAAS,eAAeA,CAAQ,IAAI,OACjFC,IAAWX,EAAY;EAC7B,IAAI,CAACQ,KAAa,CAACG,GAAU;EAE7B,IAAMC,IAASJ,EAAU,sBAAsB;EAC/C,AAAIK,MAAkB,EAAS,MAAM,QAAQ,GAAGD,EAAO,MAAM;EAC7D,IAAME,IAAQH,EAAS,sBAAsB,GACvCI,IAAgB,SAAS,gBAAgB,aACzCC,IAAiB,SAAS,gBAAgB,cAC1CC,IAAYD,IAAiBJ,EAAO,SAASM,IAASrB,GACtDsB,IAAYP,EAAO,MAAMM,IAASrB,GAClCuB,IAAaC,MAAc,QAC7BF,KAAaL,EAAM,UAAUK,IAAYF,IACzCA,IAAYH,EAAM,UAAUK,IAAYF,GACtCK,IAAkB,KAAK,IAAI,KAAKF,IAAaD,IAAYF,CAAS,GAClEM,IAAMH,IACR,KAAK,IAAIvB,GAAiBe,EAAO,MAAMM,IAAS,KAAK,IAAIJ,EAAM,QAAQQ,CAAe,CAAC,IACvF,KAAK,IAAIV,EAAO,SAASM,GAAQF,IAAiBnB,CAAe,GAC/D2B,IAAgBC,MAAU,QAAQb,EAAO,QAAQE,EAAM,QAAQF,EAAO,MACtEc,IAAO,KAAK,IAChB7B,GACA,KAAK,IAAI2B,GAAeT,IAAgBD,EAAM,QAAQjB,CAAe,CACvE;EAKA,AAHA,EAAS,MAAM,OAAO,GAAG,KAAK,MAAM6B,CAAI,EAAE,KAC1C,EAAS,MAAM,MAAM,GAAG,KAAK,MAAMH,CAAG,EAAE,KACxCZ,EAAS,MAAM,YAAY,4BAA4B,GAAG,KAAK,MAAMW,CAAe,EAAE,GAAG,GACzF,EAAS,MAAM,aAAa;CAC9B,GAAG;EAACG;EAAOf;EAAUD;EAAWI;EAAkBK;EAAQG;CAAS,CAAC;CAqBpE,IAnBAM,QAAgB;EACd,IAAI,CAACC,GAAQ;EACb,IAAMjB,IAAW,SAAS,cACxB,2BAA2B,IAAI,OAAOT,CAAW,EAAE,GACrD;EAGA,AAFA,EAAY,UAAUS,GAClBkB,MAAU,EAAS,UAAUlB,IACjCL,EAAM;EACN,IAAMwB,UAAexB,EAAM;EAG3B,OAFA,OAAO,iBAAiB,UAAUwB,CAAM,GACxC,OAAO,iBAAiB,UAAUA,GAAQ,EAAI,SACjC;GAIX,AAHA,OAAO,oBAAoB,UAAUA,CAAM,GAC3C,OAAO,oBAAoB,UAAUA,GAAQ,EAAI,GACjD,EAAY,UAAU,MAClBD,MAAU,EAAS,UAAU;EACnC;CACF,GAAG;EAAC3B;EAAa0B;EAAQxB;EAASyB;EAAUvB;CAAK,CAAC,GAE9C,CAACsB,KAAU,OAAO,WAAa,KAAa,OAAO;CAEvD,IAAMd,IACJ,kBAAC,OAAD;EACE,IAAIV;EACJ,yBAAuBF;EACjB;EACN,WAAWP,EAAG,cAAcoC,CAAS;EACrC,GAAIhC;EAEH;CACE,CAAA;CAGP,OAAOiC,EAAalB,GAAO,SAAS,IAAI;AAC1C"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../chunks/Icon-CWsA1W83.cjs");;/* empty css */const t=require("../Popover/index.cjs");let n=require("react"),r=require("react/jsx-runtime");function i(...e){return e.filter(Boolean).join(` `)}var a=(0,n.forwardRef)(function({options:a,value:o,defaultValue:s,onValueChange:c,placeholder:l=`Select an option`,size:u=`md`,isDisabled:d=!1,isInvalid:f=!1,className:p,disabled:m,onClick:h,onKeyDown:g,..._},v){let[y,b]=(0,n.useState)(s??``),x=o??y,[S,C]=(0,n.useState)(!1),[w,T]=(0,n.useState)(0),E=(0,n.useRef)(null),D=(0,n.useRef)(null),O=(0,n.useRef)(null),k=(0,n.useId)(),A=d||m,j=S&&!A,M=a.find(e=>e.value===x),N=a.filter(e=>!e.isDisabled),P=(0,n.useCallback)(e=>{o===void 0&&b(e),c?.(e),C(!1)},[c,o]);(0,n.useEffect)(()=>{if(!j)return;let e=a.findIndex(e=>e.value===x&&!e.isDisabled);T(e<0?a.indexOf(N[0]):e);let t=e=>{let t=e.target;!E.current?.contains(t)&&!O.current?.contains(t)&&C(!1)};return document.addEventListener(`mousedown`,t),()=>document.removeEventListener(`mousedown`,t)},[j]),(0,n.useEffect)(()=>{j&&(O.current?.querySelectorAll(`[role='option']`)[w])?.scrollIntoView({block:`nearest`})},[w,j]);let F=e=>{let t=a.map((e,t)=>({option:e,index:t})).filter(e=>!e.option.isDisabled);if(t.length===0)return;let n=t[(t.findIndex(e=>e.index===w)+e+t.length)%t.length];T(n.index)},I=e=>{if(!A){if(e.key===`Escape`)C(!1),D.current?.focus();else if(!j&&(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `))e.preventDefault(),C(!0);else if(j){if(e.key===`Tab`)C(!1);else if(e.key===`ArrowDown`||e.key===`ArrowUp`)e.preventDefault(),F(e.key===`ArrowDown`?1:-1);else if(e.key===`Home`||e.key===`End`){e.preventDefault();let t=e.key===`Home`?N[0]:N[N.length-1];t&&T(a.indexOf(t))}else if(e.key===`Enter`||e.key===` `){e.preventDefault();let t=a[w];t&&!t.isDisabled&&P(t.value)}}}};return(0,r.jsxs)(`div`,{className:`ds-select-root`,ref:E,children:[(0,r.jsxs)(`button`,{ref:e=>{D.current=e,typeof v==`function`?v(e):v&&(v.current=e)},type:`button`,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":j,"aria-controls":j?k:void 0,"aria-activedescendant":j&&a[w]&&!a[w].isDisabled?`${k}-option-${w}`:void 0,"aria-invalid":f||void 0,disabled:A,"data-size":u,"data-placeholder":M?void 0:``,className:i(`ds-field-skin`,`ds-select`,p),onClick:e=>{h?.(e),e.defaultPrevented||C(e=>!e)},onKeyDown:e=>{g?.(e),e.defaultPrevented||I(e)},..._,children:[(0,r.jsx)(`span`,{className:`ds-select__value`,children:M?M.label:l}),(0,r.jsx)(e.t,{name:`chevron-down`,size:16,className:`ds-select__chevron`})]}),(0,r.jsx)(t.Popover,{anchorRef:D,isOpen:j,matchAnchorWidth:!0,panelRef:O,id:k,role:`listbox`,"aria-label":_[`aria-label`]??l,className:`ds-surface-raised ds-select__menu`,children:(0,r.jsx)(`div`,{onKeyDown:I,children:a.map((t,n)=>(0,r.jsxs)(`div`,{id:`${k}-option-${n}`,role:`option`,"aria-selected":t.value===x,"aria-disabled":t.isDisabled||void 0,"data-active":n===w||void 0,className:`ds-select__option`,onMouseEnter:()=>!t.isDisabled&&T(n),onClick:()=>{t.isDisabled||(P(t.value),D.current?.focus())},children:[(0,r.jsxs)(`span`,{className:`ds-select__option-body`,children:[(0,r.jsx)(`span`,{className:`ds-select__option-label`,children:t.label}),t.description&&(0,r.jsx)(`span`,{className:`ds-select__option-description`,children:t.description})]}),t.value===x&&(0,r.jsx)(e.t,{name:`check`,size:16})]},t.value))})})]})});exports.Select=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../chunks/Icon-CWsA1W83.cjs");;/* empty css */const t=require("../Popover/index.cjs");let n=require("react"),r=require("react/jsx-runtime");function i(...e){return e.filter(Boolean).join(` `)}var a=(0,n.forwardRef)(function({options:a,value:o,defaultValue:s,onValueChange:c,placeholder:l=`Select an option`,size:u=`md`,isDisabled:d=!1,isInvalid:f=!1,menuPlacement:p=`bottom`,className:m,disabled:h,onClick:g,onKeyDown:_,...v},y){let[b,x]=(0,n.useState)(s??``),S=o??b,[C,w]=(0,n.useState)(!1),[T,E]=(0,n.useState)(0),D=(0,n.useRef)(null),O=(0,n.useRef)(null),k=(0,n.useRef)(null),A=(0,n.useId)(),j=d||h,M=C&&!j,N=a.find(e=>e.value===S),P=a.filter(e=>!e.isDisabled),F=(0,n.useCallback)(e=>{o===void 0&&x(e),c?.(e),w(!1)},[c,o]);(0,n.useEffect)(()=>{if(!M)return;let e=a.findIndex(e=>e.value===S&&!e.isDisabled);E(e<0?a.indexOf(P[0]):e);let t=e=>{let t=e.target;!D.current?.contains(t)&&!k.current?.contains(t)&&w(!1)};return document.addEventListener(`mousedown`,t),()=>document.removeEventListener(`mousedown`,t)},[M]),(0,n.useEffect)(()=>{M&&(k.current?.querySelectorAll(`[role='option']`)[T])?.scrollIntoView({block:`nearest`})},[T,M]);let I=e=>{let t=a.map((e,t)=>({option:e,index:t})).filter(e=>!e.option.isDisabled);if(t.length===0)return;let n=t[(t.findIndex(e=>e.index===T)+e+t.length)%t.length];E(n.index)},L=e=>{if(!j){if(e.key===`Escape`)w(!1),O.current?.focus();else if(!M&&(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `))e.preventDefault(),w(!0);else if(M){if(e.key===`Tab`)w(!1);else if(e.key===`ArrowDown`||e.key===`ArrowUp`)e.preventDefault(),I(e.key===`ArrowDown`?1:-1);else if(e.key===`Home`||e.key===`End`){e.preventDefault();let t=e.key===`Home`?P[0]:P[P.length-1];t&&E(a.indexOf(t))}else if(e.key===`Enter`||e.key===` `){e.preventDefault();let t=a[T];t&&!t.isDisabled&&F(t.value)}}}};return(0,r.jsxs)(`div`,{className:`ds-select-root`,ref:D,children:[(0,r.jsxs)(`button`,{ref:e=>{O.current=e,typeof y==`function`?y(e):y&&(y.current=e)},type:`button`,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":M,"aria-controls":M?A:void 0,"aria-activedescendant":M&&a[T]&&!a[T].isDisabled?`${A}-option-${T}`:void 0,"aria-invalid":f||void 0,disabled:j,"data-size":u,"data-placeholder":N?void 0:``,className:i(`ds-field-skin`,`ds-select`,m),onClick:e=>{g?.(e),e.defaultPrevented||w(e=>!e)},onKeyDown:e=>{_?.(e),e.defaultPrevented||L(e)},...v,children:[(0,r.jsx)(`span`,{className:`ds-select__value`,children:N?N.label:l}),(0,r.jsx)(e.t,{name:`chevron-down`,size:16,className:`ds-select__chevron`})]}),(0,r.jsx)(t.Popover,{anchorRef:O,isOpen:M,placement:p,matchAnchorWidth:!0,panelRef:k,id:A,role:`listbox`,"aria-label":v[`aria-labelledby`]?void 0:v[`aria-label`]??l,"aria-labelledby":v[`aria-labelledby`],className:`ds-surface-raised ds-select__menu`,children:(0,r.jsx)(`div`,{onKeyDown:L,children:a.map((t,n)=>(0,r.jsxs)(`div`,{id:`${A}-option-${n}`,role:`option`,"aria-selected":t.value===S,"aria-disabled":t.isDisabled||void 0,"data-active":n===T||void 0,className:`ds-select__option`,onMouseEnter:()=>!t.isDisabled&&E(n),onClick:()=>{t.isDisabled||(F(t.value),O.current?.focus())},children:[(0,r.jsxs)(`span`,{className:`ds-select__option-body`,children:[(0,r.jsx)(`span`,{className:`ds-select__option-label`,children:t.label}),t.description&&(0,r.jsx)(`span`,{className:`ds-select__option-description`,children:t.description})]}),t.value===S&&(0,r.jsx)(e.t,{name:`check`,size:16})]},t.value))})})]})});exports.Select=a;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["forwardRef","useState","useRef","useId","useCallback","Icon","Popover","require_Icon","require_components_Popover_index","react","react_jsx_runtime","cx","parts","Select","rest","internal","setInternal","defaultValue","current","value","isOpen","setOpen","activeIndex","setActiveIndex","rootRef","triggerRef","listRef","listId","effectiveDisabled","isDisabled","disabled","isVisible","selected","options","option","enabled","commit","next","onValueChange","index","onPointerDown","target","event","step","order","o","delta","handleKeyDown","pick","node","ref","isInvalid","size","className","onClick","open","onKeyDown","placeholder"],"sources":["../../../src/components/Select/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n} from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Popover } from \"../Popover\";\nimport type { FieldSize } from \"../Field\";\nimport \"../Field/style.css\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nexport interface SelectOption {\n value: string;\n label: string;\n /** Secondary line under the label. */\n description?: string;\n isDisabled?: boolean;\n}\n\nexport interface SelectProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"defaultValue\" | \"onChange\"> {\n options: SelectOption[];\n /** Controlled value. Leave undefined to let the select hold its own. */\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n placeholder?: string;\n size?: FieldSize;\n isDisabled?: boolean;\n isInvalid?: boolean;\n}\n\n/**\n * One value out of a known list. Wears the field skin, opens a listbox: arrows\n * walk the options, Enter commits, Escape closes without changing anything.\n */\nexport const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select(\n {\n options,\n value,\n defaultValue,\n onValueChange,\n placeholder = \"Select an option\",\n size = \"md\",\n isDisabled = false,\n isInvalid = false,\n className,\n disabled,\n onClick,\n onKeyDown,\n ...rest\n },\n ref,\n) {\n const [internal, setInternal] = useState(defaultValue ?? \"\");\n const current = value ?? internal;\n const [isOpen, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(0);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const listId = useId();\n const effectiveDisabled = isDisabled || disabled;\n const isVisible = isOpen && !effectiveDisabled;\n\n const selected = options.find((option) => option.value === current);\n const enabled = options.filter((option) => !option.isDisabled);\n\n const commit = useCallback(\n (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n setOpen(false);\n },\n [onValueChange, value],\n );\n\n useEffect(() => {\n if (!isVisible) return;\n const index = options.findIndex((option) => option.value === current && !option.isDisabled);\n setActiveIndex(index < 0 ? options.indexOf(enabled[0]!) : index);\n const onPointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (!rootRef.current?.contains(target) && !listRef.current?.contains(target)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isVisible]);\n\n useEffect(() => {\n if (!isVisible) return;\n const activeOption = listRef.current?.querySelectorAll<HTMLElement>(\"[role='option']\")[activeIndex];\n activeOption?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex, isVisible]);\n\n const step = (delta: number) => {\n const order = options.map((option, index) => ({ option, index })).filter((o) => !o.option.isDisabled);\n if (order.length === 0) return;\n const at = order.findIndex((o) => o.index === activeIndex);\n const next = order[(at + delta + order.length) % order.length]!;\n setActiveIndex(next.index);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (effectiveDisabled) return;\n if (event.key === \"Escape\") {\n setOpen(false);\n triggerRef.current?.focus();\n return;\n }\n if (!isVisible && (event.key === \"ArrowDown\" || event.key === \"ArrowUp\" || event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n setOpen(true);\n return;\n }\n if (!isVisible) return;\n if (event.key === \"Tab\") {\n setOpen(false);\n return;\n }\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n step(event.key === \"ArrowDown\" ? 1 : -1);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n const pick = event.key === \"Home\" ? enabled[0] : enabled[enabled.length - 1];\n if (pick) setActiveIndex(options.indexOf(pick));\n } else if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n const option = options[activeIndex];\n if (option && !option.isDisabled) commit(option.value);\n }\n };\n\n return (\n <div className=\"ds-select-root\" ref={rootRef}>\n <button\n ref={(node) => {\n triggerRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"button\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isVisible}\n aria-controls={isVisible ? listId : undefined}\n aria-activedescendant={isVisible && options[activeIndex] && !options[activeIndex].isDisabled ? `${listId}-option-${activeIndex}` : undefined}\n aria-invalid={isInvalid || undefined}\n disabled={effectiveDisabled}\n data-size={size}\n data-placeholder={selected ? undefined : \"\"}\n className={cx(\"ds-field-skin\", \"ds-select\", className)}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((open) => !open);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (!event.defaultPrevented) handleKeyDown(event);\n }}\n {...rest}\n >\n <span className=\"ds-select__value\">{selected ? selected.label : placeholder}</span>\n <Icon name=\"chevron-down\" size={16} className=\"ds-select__chevron\" />\n </button>\n <Popover\n anchorRef={triggerRef}\n isOpen={isVisible}\n matchAnchorWidth\n panelRef={listRef}\n id={listId}\n role=\"listbox\"\n aria-label={rest[\"aria-label\"] ?? placeholder}\n className=\"ds-surface-raised ds-select__menu\"\n >\n <div onKeyDown={handleKeyDown}>\n {options.map((option, index) => (\n <div\n key={option.value}\n id={`${listId}-option-${index}`}\n role=\"option\"\n aria-selected={option.value === current}\n aria-disabled={option.isDisabled || undefined}\n data-active={index === activeIndex || undefined}\n className=\"ds-select__option\"\n onMouseEnter={() => !option.isDisabled && setActiveIndex(index)}\n onClick={() => {\n if (!option.isDisabled) {\n commit(option.value);\n triggerRef.current?.focus();\n }\n }}\n >\n <span className=\"ds-select__option-body\">\n <span className=\"ds-select__option-label\">{option.label}</span>\n {option.description && (\n <span className=\"ds-select__option-description\">{option.description}</span>\n )}\n </span>\n {option.value === current && <Icon name=\"check\" size={16} />}\n </div>\n ))}\n </div>\n </Popover>\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["forwardRef","useState","useRef","useId","useCallback","Icon","Popover","require_Icon","require_components_Popover_index","react","react_jsx_runtime","cx","parts","Select","rest","internal","setInternal","defaultValue","current","value","isOpen","setOpen","activeIndex","setActiveIndex","rootRef","triggerRef","listRef","listId","effectiveDisabled","isDisabled","disabled","isVisible","selected","options","option","enabled","commit","next","onValueChange","index","onPointerDown","target","event","step","order","o","delta","handleKeyDown","pick","node","ref","isInvalid","size","className","onClick","open","onKeyDown","placeholder","menuPlacement"],"sources":["../../../src/components/Select/index.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n} from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Popover, type PopoverPlacement } from \"../Popover\";\nimport type { FieldSize } from \"../Field\";\nimport \"../Field/style.css\";\nimport \"./style.css\";\n\nfunction cx(...parts: (string | undefined | false)[]) {\n return parts.filter(Boolean).join(\" \");\n}\n\nexport interface SelectOption {\n value: string;\n label: string;\n /** Secondary line under the label. */\n description?: string;\n isDisabled?: boolean;\n}\n\nexport interface SelectProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"defaultValue\" | \"onChange\"> {\n options: SelectOption[];\n /** Controlled value. Leave undefined to let the select hold its own. */\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n placeholder?: string;\n size?: FieldSize;\n isDisabled?: boolean;\n isInvalid?: boolean;\n /** Preferred side of the menu; flips when space requires it. */\n menuPlacement?: PopoverPlacement;\n}\n\n/**\n * One value out of a known list. Wears the field skin, opens a listbox: arrows\n * walk the options, Enter commits, Escape closes without changing anything.\n */\nexport const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select(\n {\n options,\n value,\n defaultValue,\n onValueChange,\n placeholder = \"Select an option\",\n size = \"md\",\n isDisabled = false,\n isInvalid = false,\n menuPlacement = \"bottom\",\n className,\n disabled,\n onClick,\n onKeyDown,\n ...rest\n },\n ref,\n) {\n const [internal, setInternal] = useState(defaultValue ?? \"\");\n const current = value ?? internal;\n const [isOpen, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(0);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const listId = useId();\n const effectiveDisabled = isDisabled || disabled;\n const isVisible = isOpen && !effectiveDisabled;\n\n const selected = options.find((option) => option.value === current);\n const enabled = options.filter((option) => !option.isDisabled);\n\n const commit = useCallback(\n (next: string) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n setOpen(false);\n },\n [onValueChange, value],\n );\n\n useEffect(() => {\n if (!isVisible) return;\n const index = options.findIndex((option) => option.value === current && !option.isDisabled);\n setActiveIndex(index < 0 ? options.indexOf(enabled[0]!) : index);\n const onPointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (!rootRef.current?.contains(target) && !listRef.current?.contains(target)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isVisible]);\n\n useEffect(() => {\n if (!isVisible) return;\n const activeOption = listRef.current?.querySelectorAll<HTMLElement>(\"[role='option']\")[activeIndex];\n activeOption?.scrollIntoView({ block: \"nearest\" });\n }, [activeIndex, isVisible]);\n\n const step = (delta: number) => {\n const order = options.map((option, index) => ({ option, index })).filter((o) => !o.option.isDisabled);\n if (order.length === 0) return;\n const at = order.findIndex((o) => o.index === activeIndex);\n const next = order[(at + delta + order.length) % order.length]!;\n setActiveIndex(next.index);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (effectiveDisabled) return;\n if (event.key === \"Escape\") {\n setOpen(false);\n triggerRef.current?.focus();\n return;\n }\n if (!isVisible && (event.key === \"ArrowDown\" || event.key === \"ArrowUp\" || event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n setOpen(true);\n return;\n }\n if (!isVisible) return;\n if (event.key === \"Tab\") {\n setOpen(false);\n return;\n }\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n step(event.key === \"ArrowDown\" ? 1 : -1);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n const pick = event.key === \"Home\" ? enabled[0] : enabled[enabled.length - 1];\n if (pick) setActiveIndex(options.indexOf(pick));\n } else if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n const option = options[activeIndex];\n if (option && !option.isDisabled) commit(option.value);\n }\n };\n\n return (\n <div className=\"ds-select-root\" ref={rootRef}>\n <button\n ref={(node) => {\n triggerRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"button\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isVisible}\n aria-controls={isVisible ? listId : undefined}\n aria-activedescendant={isVisible && options[activeIndex] && !options[activeIndex].isDisabled ? `${listId}-option-${activeIndex}` : undefined}\n aria-invalid={isInvalid || undefined}\n disabled={effectiveDisabled}\n data-size={size}\n data-placeholder={selected ? undefined : \"\"}\n className={cx(\"ds-field-skin\", \"ds-select\", className)}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((open) => !open);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (!event.defaultPrevented) handleKeyDown(event);\n }}\n {...rest}\n >\n <span className=\"ds-select__value\">{selected ? selected.label : placeholder}</span>\n <Icon name=\"chevron-down\" size={16} className=\"ds-select__chevron\" />\n </button>\n <Popover\n anchorRef={triggerRef}\n isOpen={isVisible}\n placement={menuPlacement}\n matchAnchorWidth\n panelRef={listRef}\n id={listId}\n role=\"listbox\"\n aria-label={rest[\"aria-labelledby\"] ? undefined : rest[\"aria-label\"] ?? placeholder}\n aria-labelledby={rest[\"aria-labelledby\"]}\n className=\"ds-surface-raised ds-select__menu\"\n >\n <div onKeyDown={handleKeyDown}>\n {options.map((option, index) => (\n <div\n key={option.value}\n id={`${listId}-option-${index}`}\n role=\"option\"\n aria-selected={option.value === current}\n aria-disabled={option.isDisabled || undefined}\n data-active={index === activeIndex || undefined}\n className=\"ds-select__option\"\n onMouseEnter={() => !option.isDisabled && setActiveIndex(index)}\n onClick={() => {\n if (!option.isDisabled) {\n commit(option.value);\n triggerRef.current?.focus();\n }\n }}\n >\n <span className=\"ds-select__option-body\">\n <span className=\"ds-select__option-label\">{option.label}</span>\n {option.description && (\n <span className=\"ds-select__option-description\">{option.description}</span>\n )}\n </span>\n {option.value === current && <Icon name=\"check\" size={16} />}\n </div>\n ))}\n </div>\n </Popover>\n </div>\n );\n});\n"],"mappings":"A,8PAeA,SAASW,EAAG,GAAGC,EAAuC,CACpD,OAAOA,EAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACvC,CA6BA,IAAaC,GAAA,EAASb,EAAAA,WAAAA,CAA2C,SAC/D,CACE,UACA,QACA,eACA,gBACA,cAAc,mBACd,OAAO,KACP,aAAa,GACb,YAAY,GACZ,gBAAgB,SAChB,YACA,WACA,UACA,YACA,GAAGc,GAEL,EACA,CACA,GAAM,CAACC,EAAUC,IAAA,EAAef,EAAAA,SAAAA,CAASgB,GAAgB,EAAE,EACrDC,EAAUC,GAASJ,EACnB,CAACK,EAAQC,IAAA,EAAWpB,EAAAA,SAAAA,CAAS,EAAK,EAClC,CAACqB,EAAaC,IAAA,EAAkBtB,EAAAA,SAAAA,CAAS,CAAC,EAC1CuB,GAAA,EAAUtB,EAAAA,OAAAA,CAA8B,IAAI,EAC5CuB,GAAA,EAAavB,EAAAA,OAAAA,CAAiC,IAAI,EAClDwB,GAAA,EAAUxB,EAAAA,OAAAA,CAA8B,IAAI,EAC5CyB,GAAA,EAASxB,EAAAA,MAAAA,CAAM,EACfyB,EAAoBC,GAAcC,EAClCC,EAAYX,GAAU,CAACQ,EAEvBI,EAAWC,EAAQ,KAAM,GAAWC,EAAO,QAAUhB,CAAO,EAC5DiB,EAAUF,EAAQ,OAAQ,GAAW,CAACC,EAAO,UAAU,EAEvDE,GAAA,EAAShC,EAAAA,YAAAA,CACZ,GAAiB,CACZe,IAAU,IAAA,IAAWH,EAAYqB,CAAI,EACzCC,IAAgBD,CAAI,EACpBhB,EAAQ,EAAK,CACf,EACA,CAACiB,EAAenB,CAAK,CACvB,GAEA,EAAAV,EAAA,UAAA,KAAgB,CACd,GAAI,CAACsB,EAAW,OAChB,IAAMQ,EAAQN,EAAQ,UAAW,GAAWC,EAAO,QAAUhB,GAAW,CAACgB,EAAO,UAAU,EAC1FX,EAAegB,EAAQ,EAAIN,EAAQ,QAAQE,EAAQ,EAAG,EAAII,CAAK,EAC/D,IAAMC,EAAiB,GAAsB,CAC3C,IAAMC,EAASC,EAAM,OACjB,CAAClB,EAAQ,SAAS,SAASiB,CAAM,GAAK,CAACf,EAAQ,SAAS,SAASe,CAAM,GAAGpB,EAAQ,EAAK,CAC7F,EAEA,OADA,SAAS,iBAAiB,YAAamB,CAAa,MACvC,SAAS,oBAAoB,YAAaA,CAAa,CAEtE,EAAG,CAACT,CAAS,CAAC,GAEd,EAAAtB,EAAA,UAAA,KAAgB,CACTsB,IACgBL,EAAQ,SAAS,iBAA8B,iBAAiB,CAAC,CAACJ,GAAA,EACzE,eAAe,CAAE,MAAO,SAAU,CAAC,CACnD,EAAG,CAACA,EAAaS,CAAS,CAAC,EAE3B,IAAMY,EAAQ,GAAkB,CAC9B,IAAMC,EAAQX,EAAQ,KAAK,EAAQ,KAAW,CAAE,SAAQ,OAAM,EAAE,CAAC,CAAC,OAAQ,GAAM,CAACY,EAAE,OAAO,UAAU,EACpG,GAAID,EAAM,SAAW,EAAG,OAExB,IAAMP,EAAOO,GADFA,EAAM,UAAW,GAAMC,EAAE,QAAUvB,CAC1B,EAAKwB,EAAQF,EAAM,QAAUA,EAAM,QACvDrB,EAAec,EAAK,KAAK,CAC3B,EAEMU,EAAiB,GAA+B,CACpD,GAAI,GACJ,IAAIL,EAAM,MAAQ,SAChBrB,EAAQ,EAAK,EACbI,EAAW,SAAS,MAAM,OAG5B,GAAI,CAACM,IAAcW,EAAM,MAAQ,aAAeA,EAAM,MAAQ,WAAaA,EAAM,MAAQ,SAAWA,EAAM,MAAQ,KAChHA,EAAM,eAAe,EACrBrB,EAAQ,EAAI,OAGd,GAAKU,EACL,IAAIW,EAAM,MAAQ,MAChBrB,EAAQ,EAAK,OAGf,GAAIqB,EAAM,MAAQ,aAAeA,EAAM,MAAQ,UAC7CA,EAAM,eAAe,EACrBC,EAAKD,EAAM,MAAQ,YAAc,EAAI,EAAE,OAClC,GAAIA,EAAM,MAAQ,QAAUA,EAAM,MAAQ,MAAO,CACtDA,EAAM,eAAe,EACrB,IAAMM,EAAON,EAAM,MAAQ,OAASP,EAAQ,GAAKA,EAAQA,EAAQ,OAAS,GACtEa,GAAMzB,EAAeU,EAAQ,QAAQe,CAAI,CAAC,CAChD,MAAO,GAAIN,EAAM,MAAQ,SAAWA,EAAM,MAAQ,IAAK,CACrDA,EAAM,eAAe,EACrB,IAAMR,EAASD,EAAQX,GACnBY,GAAU,CAACA,EAAO,YAAYE,EAAOF,EAAO,KAAK,CACvD,CAZA,CAVA,CAuBF,EAEA,OACE,EAAAxB,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iBAAiB,IAAKc,EAArC,SAAA,EACE,EAAAd,EAAA,KAAA,CAAC,SAAD,CACE,IAAM,GAAS,CACb,EAAW,QAAUuC,EACjB,OAAOC,GAAQ,WAAYA,EAAID,CAAI,EAC9BC,IAAK,EAAI,QAAUD,EAC9B,EACA,KAAK,SACL,KAAK,WACL,gBAAc,UACd,gBAAelB,EACf,gBAAeA,EAAYJ,EAAS,IAAA,GACpC,wBAAuBI,GAAaE,EAAQX,IAAgB,CAACW,EAAQX,EAAY,CAAC,WAAa,GAAGK,EAAO,UAAUL,IAAgB,IAAA,GACnI,eAAc6B,GAAa,IAAA,GAC3B,SAAUvB,EACV,YAAWwB,EACX,mBAAkBpB,EAAW,IAAA,GAAY,GACzC,UAAWrB,EAAG,gBAAiB,YAAa0C,CAAS,EACrD,QAAU,GAAU,CAClBC,IAAUZ,CAAK,EACVA,EAAM,kBAAkBrB,EAAS,GAAS,CAACkC,CAAI,CACtD,EACA,UAAY,GAAU,CACpBC,IAAYd,CAAK,EACZA,EAAM,kBAAkBK,EAAcL,CAAK,CAClD,EACA,GAAI5B,EAzBN,SAAA,EA2BE,EAAAJ,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,mBAAoB,SAAAsB,EAAWA,EAAS,MAAQyB,CAAkB,CAAA,GAClF,EAAA/C,EAAA,IAAA,CAACL,EAAAA,EAAD,CAAM,KAAK,eAAe,KAAM,GAAI,UAAU,oBAAsB,CAAA,CAC9D,CACR,CAAA,GAAA,EAAAK,EAAA,IAAA,CAACJ,EAAAA,QAAD,CACE,UAAWmB,EACX,OAAQM,EACR,UAAW2B,EACX,iBAAA,GACA,SAAUhC,EACV,GAAIC,EACJ,KAAK,UACL,aAAYb,EAAK,mBAAqB,IAAA,GAAYA,EAAK,eAAiB2C,EACxE,kBAAiB3C,EAAK,mBACtB,UAAU,oCAEV,UAAA,EAAAJ,EAAA,IAAA,CAAC,MAAD,CAAK,UAAWqC,EACb,SAAAd,EAAQ,KAAK,EAAQ,KACpB,EAAAvB,EAAA,KAAA,CAAC,MAAD,CAEE,GAAI,GAAGiB,EAAO,UAAUY,IACxB,KAAK,SACL,gBAAeL,EAAO,QAAUhB,EAChC,gBAAegB,EAAO,YAAc,IAAA,GACpC,cAAaK,IAAUjB,GAAe,IAAA,GACtC,UAAU,oBACV,iBAAoB,CAACY,EAAO,YAAcX,EAAegB,CAAK,EAC9D,YAAe,CACRL,EAAO,aACVE,EAAOF,EAAO,KAAK,EACnBT,EAAW,SAAS,MAAM,EAE9B,EAdF,SAAA,EAgBE,EAAAf,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,yBAAhB,SAAA,EACE,EAAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,0BAA2B,SAAAwB,EAAO,KAAY,CAAA,EAC7DA,EAAO,cACN,EAAAxB,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,gCAAiC,SAAAwB,EAAO,WAAkB,CAAA,CAExE,CACL,CAAA,EAAAA,EAAO,QAAUhB,IAAW,EAAAR,EAAA,IAAA,CAACL,EAAAA,EAAD,CAAM,KAAK,QAAQ,KAAM,EAAK,CAAA,CACxD,CAtBE,EAAA6B,EAAO,KAsBT,CACN,CACE,CAAA,CACE,CAAA,CACN,C,EAET,CAAC,E"}
@@ -1,4 +1,5 @@
1
1
  import { type ButtonHTMLAttributes } from "react";
2
+ import { type PopoverPlacement } from "../Popover/index.cjs";
2
3
  import type { FieldSize } from "../Field/index.cjs";
3
4
  export interface SelectOption {
4
5
  value: string;
@@ -17,6 +18,8 @@ export interface SelectProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement
17
18
  size?: FieldSize;
18
19
  isDisabled?: boolean;
19
20
  isInvalid?: boolean;
21
+ /** Preferred side of the menu; flips when space requires it. */
22
+ menuPlacement?: PopoverPlacement;
20
23
  }
21
24
  /**
22
25
  * One value out of a known list. Wears the field skin, opens a listbox: arrows
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Select/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,oBAAoB,CAAC;AAC5B,OAAO,aAAa,CAAC;AAMrB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;IAC5F,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GA4KjB,CAAC"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/components/Select/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AAEf,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,oBAAoB,CAAC;AAC5B,OAAO,aAAa,CAAC;AAMrB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;IAC5F,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GA+KjB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { type ButtonHTMLAttributes } from "react";
2
+ import { type PopoverPlacement } from "../Popover/index.js";
2
3
  import type { FieldSize } from "../Field/index.js";
3
4
  export interface SelectOption {
4
5
  value: string;
@@ -17,6 +18,8 @@ export interface SelectProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement
17
18
  size?: FieldSize;
18
19
  isDisabled?: boolean;
19
20
  isInvalid?: boolean;
21
+ /** Preferred side of the menu; flips when space requires it. */
22
+ menuPlacement?: PopoverPlacement;
20
23
  }
21
24
  /**
22
25
  * One value out of a known list. Wears the field skin, opens a listbox: arrows
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Select/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,oBAAoB,CAAC;AAC5B,OAAO,aAAa,CAAC;AAMrB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;IAC5F,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GA4KjB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Select/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,oBAAoB,EAC1B,MAAM,OAAO,CAAC;AAEf,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,oBAAoB,CAAC;AAC5B,OAAO,aAAa,CAAC;AAMrB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC;IAC5F,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,2GA+KjB,CAAC"}