@fairmint/ui 0.3.35 → 0.3.37

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.
@@ -4,6 +4,7 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const index = require("../../../theme/index.cjs");
5
5
  const layout = require("../../primitives/layout.cjs");
6
6
  const Popover = require("../../primitives/Popover/Popover.cjs");
7
+ const zIndex = require("../../../theme/zIndex.cjs");
7
8
  const Text = require("../../../node_modules/@mantine/core/esm/components/Text/Text.cjs");
8
9
  const ScrollArea = require("../../../node_modules/@mantine/core/esm/components/ScrollArea/ScrollArea.cjs");
9
10
  const DEFAULT_EMPTY_MESSAGE = "There are no tasks to do right now. You'll see a badge on this icon when there are.";
@@ -17,7 +18,7 @@ function TaskInboxPopover({
17
18
  target,
18
19
  title = "Tasks",
19
20
  width = 420,
20
- zIndex
21
+ zIndex: zIndex$1 = zIndex.overlayZIndexAboveLegacyShell
21
22
  }) {
22
23
  const showEmpty = count === 0;
23
24
  const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;
@@ -33,7 +34,7 @@ function TaskInboxPopover({
33
34
  trapFocus: true,
34
35
  width: responsiveWidth,
35
36
  withinPortal: true,
36
- zIndex,
37
+ zIndex: zIndex$1,
37
38
  children: [
38
39
  /* @__PURE__ */ jsxRuntime.jsx(Popover.Popover.Target, { children: target }),
39
40
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1 +1 @@
1
- {"version":3,"file":"TaskInboxPopover.cjs","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { Box, ScrollArea, Stack, Text } from \"../../primitives/layout\";\nimport { Popover } from \"../../primitives/Popover/Popover\";\n\nexport interface TaskInboxPopoverProps {\n /** Controlled open state. */\n opened: boolean;\n /** Called when the popover requests close. */\n onClose: () => void;\n /** Bell or trigger element wrapped by `Popover.Target`. */\n target: ReactElement;\n /**\n * Unresolved actionable task count (header + empty-state source of truth).\n * Parent must derive this from the same list passed as `children`.\n */\n count: number;\n /** Header title. @default \"Tasks\" */\n title?: string;\n /** Empty-state copy when `count` is 0. */\n emptyMessage?: ReactNode;\n /** Task list body — typically studiov2 `<Tasks />`. Ignored when `count` is 0. */\n children: ReactNode;\n /**\n * Preferred popover width in px. Clamped to the viewport so mobile does not\n * clip. @default 420\n */\n width?: number;\n /** Portal stacking order — Studio shell menus use `SHELL_MENU_Z_INDEX`. */\n zIndex?: number;\n className?: string;\n}\n\nconst DEFAULT_EMPTY_MESSAGE =\n \"There are no tasks to do right now. You'll see a badge on this icon when there are.\";\n\n/**\n * Studio bell task inbox shell — Mantine popover chrome around a `TaskRow` list.\n *\n * Domain mapping (task type → copy, link, priority) stays in the consuming app.\n * This component owns layout, header, scroll region, and empty state framing.\n */\nexport function TaskInboxPopover({\n children,\n className,\n count,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n onClose,\n opened,\n target,\n title = \"Tasks\",\n width = 420,\n zIndex,\n}: TaskInboxPopoverProps) {\n const showEmpty = count === 0;\n const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;\n\n return (\n <Box className={className}>\n <Popover\n onChange={(next) => {\n if (!next) onClose();\n }}\n opened={opened}\n position=\"bottom-start\"\n returnFocus\n trapFocus\n width={responsiveWidth}\n withinPortal\n zIndex={zIndex}\n >\n <Popover.Target>{target}</Popover.Target>\n <Popover.Dropdown\n p={0}\n role=\"dialog\"\n aria-label={title}\n style={{ overflow: \"hidden\", maxWidth: \"100%\" }}\n >\n <Box\n px=\"md\"\n py=\"sm\"\n style={{ borderBottom: `1px solid ${fairmintVars.colorBorderDefault}` }}\n >\n <Text fw={600} size=\"md\">\n {title}\n {count > 0 ? ` (${count})` : \"\"}\n </Text>\n </Box>\n {showEmpty ? (\n <Box px=\"md\" py=\"sm\">\n <Text size=\"sm\">{emptyMessage}</Text>\n </Box>\n ) : (\n // Vertical-only hover scrollbar (no offset gutter): offsetScrollbars\n // reserved a permanent right pad that looked like empty padding.\n <ScrollArea.Autosize mah={360} scrollbars=\"y\" type=\"hover\">\n <Box maw=\"100%\" style={{ overflow: \"hidden\" }}>\n <Stack gap={0}>{children}</Stack>\n </Box>\n </ScrollArea.Autosize>\n )}\n </Popover.Dropdown>\n </Popover>\n </Box>\n );\n}\n"],"names":["jsx","Box","jsxs","Popover","fairmintVars","Text","ScrollArea","Stack"],"mappings":";;;;;;;;AAiCA,MAAM,wBACJ;AAQK,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AACF,GAA0B;AACxB,QAAM,YAAY,UAAU;AAC5B,QAAM,kBAAkB,OAAO,KAAK;AAEpC,SACEA,2BAAAA,IAACC,OAAAA,OAAI,WACH,UAAAC,2BAAAA;AAAAA,IAACC,QAAAA;AAAAA,IAAA;AAAA,MACC,UAAU,CAAC,SAAS;AAClB,YAAI,CAAC,KAAM,SAAA;AAAA,MACb;AAAA,MACA;AAAA,MACA,UAAS;AAAA,MACT,aAAW;AAAA,MACX,WAAS;AAAA,MACT,OAAO;AAAA,MACP,cAAY;AAAA,MACZ;AAAA,MAEA,UAAA;AAAA,QAAAH,2BAAAA,IAACG,QAAAA,QAAQ,QAAR,EAAgB,UAAA,OAAA,CAAO;AAAA,QACxBD,2BAAAA;AAAAA,UAACC,QAAAA,QAAQ;AAAA,UAAR;AAAA,YACC,GAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAY;AAAA,YACZ,OAAO,EAAE,UAAU,UAAU,UAAU,OAAA;AAAA,YAEvC,UAAA;AAAA,cAAAH,2BAAAA;AAAAA,gBAACC,OAAAA;AAAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,OAAO,EAAE,cAAc,aAAaG,MAAAA,aAAa,kBAAkB,GAAA;AAAA,kBAEnE,UAAAF,2BAAAA,KAACG,KAAAA,MAAA,EAAK,IAAI,KAAK,MAAK,MACjB,UAAA;AAAA,oBAAA;AAAA,oBACA,QAAQ,IAAI,KAAK,KAAK,MAAM;AAAA,kBAAA,EAAA,CAC/B;AAAA,gBAAA;AAAA,cAAA;AAAA,cAED,YACCL,2BAAAA,IAACC,YAAA,EAAI,IAAG,MAAK,IAAG,MACd,UAAAD,2BAAAA,IAACK,KAAAA,MAAA,EAAK,MAAK,MAAM,UAAA,aAAA,CAAa,GAChC;AAAA;AAAA;AAAA,gBAIAL,2BAAAA,IAACM,WAAAA,WAAW,UAAX,EAAoB,KAAK,KAAK,YAAW,KAAI,MAAK,SACjD,UAAAN,2BAAAA,IAACC,OAAAA,KAAA,EAAI,KAAI,QAAO,OAAO,EAAE,UAAU,SAAA,GACjC,UAAAD,2BAAAA,IAACO,OAAAA,OAAA,EAAM,KAAK,GAAI,SAAA,CAAS,EAAA,CAC3B,EAAA,CACF;AAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;;"}
1
+ {"version":3,"file":"TaskInboxPopover.cjs","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Box, ScrollArea, Stack, Text } from \"../../primitives/layout\";\nimport { Popover } from \"../../primitives/Popover/Popover\";\n\nexport interface TaskInboxPopoverProps {\n /** Controlled open state. */\n opened: boolean;\n /** Called when the popover requests close. */\n onClose: () => void;\n /** Bell or trigger element wrapped by `Popover.Target`. */\n target: ReactElement;\n /**\n * Unresolved actionable task count (header + empty-state source of truth).\n * Parent must derive this from the same list passed as `children`.\n */\n count: number;\n /** Header title. @default \"Tasks\" */\n title?: string;\n /** Empty-state copy when `count` is 0. */\n emptyMessage?: ReactNode;\n /** Task list body — typically studiov2 `<Tasks />`. Ignored when `count` is 0. */\n children: ReactNode;\n /**\n * Preferred popover width in px. Clamped to the viewport so mobile does not\n * clip. @default 420\n */\n width?: number;\n /** Portal stacking order. @default overlayZIndexAboveLegacyShell */\n zIndex?: number;\n className?: string;\n}\n\nconst DEFAULT_EMPTY_MESSAGE =\n \"There are no tasks to do right now. You'll see a badge on this icon when there are.\";\n\n/**\n * Studio bell task inbox shell — Mantine popover chrome around a `TaskRow` list.\n *\n * Domain mapping (task type → copy, link, priority) stays in the consuming app.\n * This component owns layout, header, scroll region, and empty state framing.\n */\nexport function TaskInboxPopover({\n children,\n className,\n count,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n onClose,\n opened,\n target,\n title = \"Tasks\",\n width = 420,\n zIndex = overlayZIndexAboveLegacyShell,\n}: TaskInboxPopoverProps) {\n const showEmpty = count === 0;\n const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;\n\n return (\n <Box className={className}>\n <Popover\n onChange={(next) => {\n if (!next) onClose();\n }}\n opened={opened}\n position=\"bottom-start\"\n returnFocus\n trapFocus\n width={responsiveWidth}\n withinPortal\n zIndex={zIndex}\n >\n <Popover.Target>{target}</Popover.Target>\n <Popover.Dropdown\n p={0}\n role=\"dialog\"\n aria-label={title}\n style={{ overflow: \"hidden\", maxWidth: \"100%\" }}\n >\n <Box\n px=\"md\"\n py=\"sm\"\n style={{ borderBottom: `1px solid ${fairmintVars.colorBorderDefault}` }}\n >\n <Text fw={600} size=\"md\">\n {title}\n {count > 0 ? ` (${count})` : \"\"}\n </Text>\n </Box>\n {showEmpty ? (\n <Box px=\"md\" py=\"sm\">\n <Text size=\"sm\">{emptyMessage}</Text>\n </Box>\n ) : (\n // Vertical-only hover scrollbar (no offset gutter): offsetScrollbars\n // reserved a permanent right pad that looked like empty padding.\n <ScrollArea.Autosize mah={360} scrollbars=\"y\" type=\"hover\">\n <Box maw=\"100%\" style={{ overflow: \"hidden\" }}>\n <Stack gap={0}>{children}</Stack>\n </Box>\n </ScrollArea.Autosize>\n )}\n </Popover.Dropdown>\n </Popover>\n </Box>\n );\n}\n"],"names":["zIndex","overlayZIndexAboveLegacyShell","jsx","Box","jsxs","Popover","fairmintVars","Text","ScrollArea","Stack"],"mappings":";;;;;;;;;AAiCA,MAAM,wBACJ;AAQK,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,EAAA,QACRA,WAASC,OAAAA;AACX,GAA0B;AACxB,QAAM,YAAY,UAAU;AAC5B,QAAM,kBAAkB,OAAO,KAAK;AAEpC,SACEC,2BAAAA,IAACC,OAAAA,OAAI,WACH,UAAAC,2BAAAA;AAAAA,IAACC,QAAAA;AAAAA,IAAA;AAAA,MACC,UAAU,CAAC,SAAS;AAClB,YAAI,CAAC,KAAM,SAAA;AAAA,MACb;AAAA,MACA;AAAA,MACA,UAAS;AAAA,MACT,aAAW;AAAA,MACX,WAAS;AAAA,MACT,OAAO;AAAA,MACP,cAAY;AAAA,MAAA,QACZL;AAAAA,MAEA,UAAA;AAAA,QAAAE,2BAAAA,IAACG,QAAAA,QAAQ,QAAR,EAAgB,UAAA,OAAA,CAAO;AAAA,QACxBD,2BAAAA;AAAAA,UAACC,QAAAA,QAAQ;AAAA,UAAR;AAAA,YACC,GAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAY;AAAA,YACZ,OAAO,EAAE,UAAU,UAAU,UAAU,OAAA;AAAA,YAEvC,UAAA;AAAA,cAAAH,2BAAAA;AAAAA,gBAACC,OAAAA;AAAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,OAAO,EAAE,cAAc,aAAaG,MAAAA,aAAa,kBAAkB,GAAA;AAAA,kBAEnE,UAAAF,2BAAAA,KAACG,KAAAA,MAAA,EAAK,IAAI,KAAK,MAAK,MACjB,UAAA;AAAA,oBAAA;AAAA,oBACA,QAAQ,IAAI,KAAK,KAAK,MAAM;AAAA,kBAAA,EAAA,CAC/B;AAAA,gBAAA;AAAA,cAAA;AAAA,cAED,YACCL,2BAAAA,IAACC,YAAA,EAAI,IAAG,MAAK,IAAG,MACd,UAAAD,2BAAAA,IAACK,KAAAA,MAAA,EAAK,MAAK,MAAM,UAAA,aAAA,CAAa,GAChC;AAAA;AAAA;AAAA,gBAIAL,2BAAAA,IAACM,WAAAA,WAAW,UAAX,EAAoB,KAAK,KAAK,YAAW,KAAI,MAAK,SACjD,UAAAN,2BAAAA,IAACC,OAAAA,KAAA,EAAI,KAAI,QAAO,OAAO,EAAE,UAAU,SAAA,GACjC,UAAAD,2BAAAA,IAACO,OAAAA,OAAA,EAAM,KAAK,GAAI,SAAA,CAAS,EAAA,CAC3B,EAAA,CACF;AAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;;"}
@@ -22,7 +22,7 @@ export interface TaskInboxPopoverProps {
22
22
  * clip. @default 420
23
23
  */
24
24
  width?: number;
25
- /** Portal stacking order — Studio shell menus use `SHELL_MENU_Z_INDEX`. */
25
+ /** Portal stacking order. @default overlayZIndexAboveLegacyShell */
26
26
  zIndex?: number;
27
27
  className?: string;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TaskInboxPopover.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKrD,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2DAA2D;IAC3D,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,kFAAkF;IAClF,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAoC,EACpC,OAAO,EACP,MAAM,EACN,MAAM,EACN,KAAe,EACf,KAAW,EACX,MAAM,GACP,EAAE,qBAAqB,+BAoDvB"}
1
+ {"version":3,"file":"TaskInboxPopover.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKrD,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2DAA2D;IAC3D,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,kFAAkF;IAClF,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,KAAK,EACL,YAAoC,EACpC,OAAO,EACP,MAAM,EACN,MAAM,EACN,KAAe,EACf,KAAW,EACX,MAAsC,GACvC,EAAE,qBAAqB,+BAoDvB"}
@@ -2,6 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { fairmintVars } from "../../../theme/index.js";
3
3
  import { Box, Stack } from "../../primitives/layout.js";
4
4
  import { Popover } from "../../primitives/Popover/Popover.js";
5
+ import { overlayZIndexAboveLegacyShell } from "../../../theme/zIndex.js";
5
6
  import { Text } from "../../../node_modules/@mantine/core/esm/components/Text/Text.js";
6
7
  import { ScrollArea } from "../../../node_modules/@mantine/core/esm/components/ScrollArea/ScrollArea.js";
7
8
  const DEFAULT_EMPTY_MESSAGE = "There are no tasks to do right now. You'll see a badge on this icon when there are.";
@@ -15,7 +16,7 @@ function TaskInboxPopover({
15
16
  target,
16
17
  title = "Tasks",
17
18
  width = 420,
18
- zIndex
19
+ zIndex = overlayZIndexAboveLegacyShell
19
20
  }) {
20
21
  const showEmpty = count === 0;
21
22
  const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;
@@ -1 +1 @@
1
- {"version":3,"file":"TaskInboxPopover.js","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { Box, ScrollArea, Stack, Text } from \"../../primitives/layout\";\nimport { Popover } from \"../../primitives/Popover/Popover\";\n\nexport interface TaskInboxPopoverProps {\n /** Controlled open state. */\n opened: boolean;\n /** Called when the popover requests close. */\n onClose: () => void;\n /** Bell or trigger element wrapped by `Popover.Target`. */\n target: ReactElement;\n /**\n * Unresolved actionable task count (header + empty-state source of truth).\n * Parent must derive this from the same list passed as `children`.\n */\n count: number;\n /** Header title. @default \"Tasks\" */\n title?: string;\n /** Empty-state copy when `count` is 0. */\n emptyMessage?: ReactNode;\n /** Task list body — typically studiov2 `<Tasks />`. Ignored when `count` is 0. */\n children: ReactNode;\n /**\n * Preferred popover width in px. Clamped to the viewport so mobile does not\n * clip. @default 420\n */\n width?: number;\n /** Portal stacking order — Studio shell menus use `SHELL_MENU_Z_INDEX`. */\n zIndex?: number;\n className?: string;\n}\n\nconst DEFAULT_EMPTY_MESSAGE =\n \"There are no tasks to do right now. You'll see a badge on this icon when there are.\";\n\n/**\n * Studio bell task inbox shell — Mantine popover chrome around a `TaskRow` list.\n *\n * Domain mapping (task type → copy, link, priority) stays in the consuming app.\n * This component owns layout, header, scroll region, and empty state framing.\n */\nexport function TaskInboxPopover({\n children,\n className,\n count,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n onClose,\n opened,\n target,\n title = \"Tasks\",\n width = 420,\n zIndex,\n}: TaskInboxPopoverProps) {\n const showEmpty = count === 0;\n const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;\n\n return (\n <Box className={className}>\n <Popover\n onChange={(next) => {\n if (!next) onClose();\n }}\n opened={opened}\n position=\"bottom-start\"\n returnFocus\n trapFocus\n width={responsiveWidth}\n withinPortal\n zIndex={zIndex}\n >\n <Popover.Target>{target}</Popover.Target>\n <Popover.Dropdown\n p={0}\n role=\"dialog\"\n aria-label={title}\n style={{ overflow: \"hidden\", maxWidth: \"100%\" }}\n >\n <Box\n px=\"md\"\n py=\"sm\"\n style={{ borderBottom: `1px solid ${fairmintVars.colorBorderDefault}` }}\n >\n <Text fw={600} size=\"md\">\n {title}\n {count > 0 ? ` (${count})` : \"\"}\n </Text>\n </Box>\n {showEmpty ? (\n <Box px=\"md\" py=\"sm\">\n <Text size=\"sm\">{emptyMessage}</Text>\n </Box>\n ) : (\n // Vertical-only hover scrollbar (no offset gutter): offsetScrollbars\n // reserved a permanent right pad that looked like empty padding.\n <ScrollArea.Autosize mah={360} scrollbars=\"y\" type=\"hover\">\n <Box maw=\"100%\" style={{ overflow: \"hidden\" }}>\n <Stack gap={0}>{children}</Stack>\n </Box>\n </ScrollArea.Autosize>\n )}\n </Popover.Dropdown>\n </Popover>\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;AAiCA,MAAM,wBACJ;AAQK,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AACF,GAA0B;AACxB,QAAM,YAAY,UAAU;AAC5B,QAAM,kBAAkB,OAAO,KAAK;AAEpC,SACE,oBAAC,OAAI,WACH,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,CAAC,SAAS;AAClB,YAAI,CAAC,KAAM,SAAA;AAAA,MACb;AAAA,MACA;AAAA,MACA,UAAS;AAAA,MACT,aAAW;AAAA,MACX,WAAS;AAAA,MACT,OAAO;AAAA,MACP,cAAY;AAAA,MACZ;AAAA,MAEA,UAAA;AAAA,QAAA,oBAAC,QAAQ,QAAR,EAAgB,UAAA,OAAA,CAAO;AAAA,QACxB;AAAA,UAAC,QAAQ;AAAA,UAAR;AAAA,YACC,GAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAY;AAAA,YACZ,OAAO,EAAE,UAAU,UAAU,UAAU,OAAA;AAAA,YAEvC,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,OAAO,EAAE,cAAc,aAAa,aAAa,kBAAkB,GAAA;AAAA,kBAEnE,UAAA,qBAAC,MAAA,EAAK,IAAI,KAAK,MAAK,MACjB,UAAA;AAAA,oBAAA;AAAA,oBACA,QAAQ,IAAI,KAAK,KAAK,MAAM;AAAA,kBAAA,EAAA,CAC/B;AAAA,gBAAA;AAAA,cAAA;AAAA,cAED,YACC,oBAAC,KAAA,EAAI,IAAG,MAAK,IAAG,MACd,UAAA,oBAAC,MAAA,EAAK,MAAK,MAAM,UAAA,aAAA,CAAa,GAChC;AAAA;AAAA;AAAA,gBAIA,oBAAC,WAAW,UAAX,EAAoB,KAAK,KAAK,YAAW,KAAI,MAAK,SACjD,UAAA,oBAAC,KAAA,EAAI,KAAI,QAAO,OAAO,EAAE,UAAU,SAAA,GACjC,UAAA,oBAAC,OAAA,EAAM,KAAK,GAAI,SAAA,CAAS,EAAA,CAC3B,EAAA,CACF;AAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"TaskInboxPopover.js","sources":["../../../../src/components/generic/TaskInboxPopover/TaskInboxPopover.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\nimport { fairmintVars, overlayZIndexAboveLegacyShell } from \"../../../theme\";\nimport { Box, ScrollArea, Stack, Text } from \"../../primitives/layout\";\nimport { Popover } from \"../../primitives/Popover/Popover\";\n\nexport interface TaskInboxPopoverProps {\n /** Controlled open state. */\n opened: boolean;\n /** Called when the popover requests close. */\n onClose: () => void;\n /** Bell or trigger element wrapped by `Popover.Target`. */\n target: ReactElement;\n /**\n * Unresolved actionable task count (header + empty-state source of truth).\n * Parent must derive this from the same list passed as `children`.\n */\n count: number;\n /** Header title. @default \"Tasks\" */\n title?: string;\n /** Empty-state copy when `count` is 0. */\n emptyMessage?: ReactNode;\n /** Task list body — typically studiov2 `<Tasks />`. Ignored when `count` is 0. */\n children: ReactNode;\n /**\n * Preferred popover width in px. Clamped to the viewport so mobile does not\n * clip. @default 420\n */\n width?: number;\n /** Portal stacking order. @default overlayZIndexAboveLegacyShell */\n zIndex?: number;\n className?: string;\n}\n\nconst DEFAULT_EMPTY_MESSAGE =\n \"There are no tasks to do right now. You'll see a badge on this icon when there are.\";\n\n/**\n * Studio bell task inbox shell — Mantine popover chrome around a `TaskRow` list.\n *\n * Domain mapping (task type → copy, link, priority) stays in the consuming app.\n * This component owns layout, header, scroll region, and empty state framing.\n */\nexport function TaskInboxPopover({\n children,\n className,\n count,\n emptyMessage = DEFAULT_EMPTY_MESSAGE,\n onClose,\n opened,\n target,\n title = \"Tasks\",\n width = 420,\n zIndex = overlayZIndexAboveLegacyShell,\n}: TaskInboxPopoverProps) {\n const showEmpty = count === 0;\n const responsiveWidth = `min(${width}px, calc(100vw - 32px))`;\n\n return (\n <Box className={className}>\n <Popover\n onChange={(next) => {\n if (!next) onClose();\n }}\n opened={opened}\n position=\"bottom-start\"\n returnFocus\n trapFocus\n width={responsiveWidth}\n withinPortal\n zIndex={zIndex}\n >\n <Popover.Target>{target}</Popover.Target>\n <Popover.Dropdown\n p={0}\n role=\"dialog\"\n aria-label={title}\n style={{ overflow: \"hidden\", maxWidth: \"100%\" }}\n >\n <Box\n px=\"md\"\n py=\"sm\"\n style={{ borderBottom: `1px solid ${fairmintVars.colorBorderDefault}` }}\n >\n <Text fw={600} size=\"md\">\n {title}\n {count > 0 ? ` (${count})` : \"\"}\n </Text>\n </Box>\n {showEmpty ? (\n <Box px=\"md\" py=\"sm\">\n <Text size=\"sm\">{emptyMessage}</Text>\n </Box>\n ) : (\n // Vertical-only hover scrollbar (no offset gutter): offsetScrollbars\n // reserved a permanent right pad that looked like empty padding.\n <ScrollArea.Autosize mah={360} scrollbars=\"y\" type=\"hover\">\n <Box maw=\"100%\" style={{ overflow: \"hidden\" }}>\n <Stack gap={0}>{children}</Stack>\n </Box>\n </ScrollArea.Autosize>\n )}\n </Popover.Dropdown>\n </Popover>\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAiCA,MAAM,wBACJ;AAQK,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX,GAA0B;AACxB,QAAM,YAAY,UAAU;AAC5B,QAAM,kBAAkB,OAAO,KAAK;AAEpC,SACE,oBAAC,OAAI,WACH,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,CAAC,SAAS;AAClB,YAAI,CAAC,KAAM,SAAA;AAAA,MACb;AAAA,MACA;AAAA,MACA,UAAS;AAAA,MACT,aAAW;AAAA,MACX,WAAS;AAAA,MACT,OAAO;AAAA,MACP,cAAY;AAAA,MACZ;AAAA,MAEA,UAAA;AAAA,QAAA,oBAAC,QAAQ,QAAR,EAAgB,UAAA,OAAA,CAAO;AAAA,QACxB;AAAA,UAAC,QAAQ;AAAA,UAAR;AAAA,YACC,GAAG;AAAA,YACH,MAAK;AAAA,YACL,cAAY;AAAA,YACZ,OAAO,EAAE,UAAU,UAAU,UAAU,OAAA;AAAA,YAEvC,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAG;AAAA,kBACH,IAAG;AAAA,kBACH,OAAO,EAAE,cAAc,aAAa,aAAa,kBAAkB,GAAA;AAAA,kBAEnE,UAAA,qBAAC,MAAA,EAAK,IAAI,KAAK,MAAK,MACjB,UAAA;AAAA,oBAAA;AAAA,oBACA,QAAQ,IAAI,KAAK,KAAK,MAAM;AAAA,kBAAA,EAAA,CAC/B;AAAA,gBAAA;AAAA,cAAA;AAAA,cAED,YACC,oBAAC,KAAA,EAAI,IAAG,MAAK,IAAG,MACd,UAAA,oBAAC,MAAA,EAAK,MAAK,MAAM,UAAA,aAAA,CAAa,GAChC;AAAA;AAAA;AAAA,gBAIA,oBAAC,WAAW,UAAX,EAAoB,KAAK,KAAK,YAAW,KAAI,MAAK,SACjD,UAAA,oBAAC,KAAA,EAAI,KAAI,QAAO,OAAO,EAAE,UAAU,SAAA,GACjC,UAAA,oBAAC,OAAA,EAAM,KAAK,GAAI,SAAA,CAAS,EAAA,CAC3B,EAAA,CACF;AAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -130,20 +130,12 @@ function TaskRow({
130
130
  ...actionProps,
131
131
  color: colors.colors.primary,
132
132
  size: "sm",
133
- variant: isCritical ? "filled" : "light",
134
- styles: {
135
- root: {
136
- // Keep CTA + dismiss inside the 420px inbox without x-scroll.
137
- maxWidth: 148,
138
- minWidth: 0,
139
- overflow: "hidden"
140
- },
141
- label: {
142
- overflow: "hidden",
143
- textOverflow: "ellipsis",
144
- whiteSpace: "nowrap"
145
- }
133
+ style: {
134
+ ...actionProps.style,
135
+ flexShrink: 0,
136
+ whiteSpace: "nowrap"
146
137
  },
138
+ variant: isCritical ? "filled" : "light",
147
139
  children: actionLabel
148
140
  }
149
141
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"TaskRow.cjs","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\n\nexport type TaskRowPriority = \"critical\" | \"high\" | \"medium\" | \"low\";\n\nexport type TaskRowVariant = \"standalone\" | \"list\";\n\nexport interface TaskRowActionProps\n extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\" | \"size\"> {\n /** Visible primary CTA label. */\n label: ReactNode;\n}\n\nexport interface TaskRowProps {\n /** Priority / urgency affordance. @default \"medium\" */\n priority?: TaskRowPriority;\n /**\n * Severity label shown above the title in uppercase plain text.\n * Defaults to the capitalized priority name (for example, \"Critical\", \"High\").\n */\n priorityLabel?: string;\n /** Task title. */\n title: string;\n /** Supporting description. */\n description: string;\n /**\n * Caller-formatted due date or age (for example, \"Due today\", \"3 days ago\").\n * Included in the accessible name when provided; not shown beside the CTA.\n */\n timingLabel?: string;\n /** Primary workflow CTA. */\n action: TaskRowActionProps;\n /**\n * Layout presentation. Use `list` inside a shared bordered stack so rows\n * sit flush with no card gaps. @default \"standalone\"\n */\n variant?: TaskRowVariant;\n /**\n * When `variant=\"list\"`, draw a bottom divider. Set false on the last row.\n * @default true\n */\n withDivider?: boolean;\n /** Optional dismiss or snooze handler. */\n onDismiss?: () => void;\n /** Accessible label for the dismiss control. @default \"Dismiss task\" */\n dismissLabel?: string;\n /** Accessible label for the row. Defaults to title plus timing when provided. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst PRIORITY_SEVERITY_COLORS = {\n critical: fairmintVars.colorErrorText,\n // Mid warning ramp (amber) — clearer than warning-text/solid brown vs error red.\n high: \"warning.5\",\n medium: \"warning.5\",\n low: fairmintVars.colorTextTertiary,\n} as const;\n\nconst DEFAULT_PRIORITY_LABELS: Record<TaskRowPriority, string> = {\n critical: \"Critical\",\n high: \"High\",\n medium: \"Medium\",\n low: \"Low\",\n};\n\n/** Soft critical tint that stays readable in Light and Dark (avoids solid error-bg in dark). */\nconst CRITICAL_ROW_BACKGROUND = `color-mix(in srgb, ${fairmintVars.colorErrorSolid} 18%, ${fairmintVars.colorBgSurface})`;\n\nfunction DefaultDismissIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * Presentational durable-task row for Studio Tasks and future Investor inbox work.\n *\n * Owns uppercase severity text above the title, description, a right-pinned\n * vertically centered `sm` primary CTA, and optional dismiss. Only `critical`\n * priority receives a semantic fill; non-critical rows stay on the neutral\n * list surface. The owning workflow resolves completion; this row does not\n * infer resolution from dismiss.\n */\nexport function TaskRow({\n action,\n ariaLabel,\n className,\n description,\n dismissLabel = \"Dismiss task\",\n onDismiss,\n priority = \"medium\",\n priorityLabel,\n timingLabel,\n title,\n variant = \"standalone\",\n withDivider = true,\n}: TaskRowProps) {\n const resolvedSeverityLabel = priorityLabel ?? DEFAULT_PRIORITY_LABELS[priority];\n const resolvedAriaLabel =\n ariaLabel ??\n (timingLabel\n ? `${title}. ${resolvedSeverityLabel} priority. ${timingLabel}`\n : `${title}. ${resolvedSeverityLabel} priority`);\n const isCritical = priority === \"critical\";\n const isList = variant === \"list\";\n const hasDescription = description.trim().length > 0;\n const { label: actionLabel, ...actionProps } = action;\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n role=\"group\"\n className={className}\n data-priority={priority}\n data-testid=\"task-row\"\n data-variant={variant}\n px=\"sm\"\n py={10}\n w=\"100%\"\n miw={0}\n maw=\"100%\"\n style={{\n background: isCritical ? CRITICAL_ROW_BACKGROUND : fairmintVars.colorBgSurface,\n border: isList ? \"none\" : `1px solid ${fairmintVars.colorBorderDefault}`,\n borderBottom:\n isList && withDivider ? `1px solid ${fairmintVars.colorBorderDefault}` : undefined,\n borderRadius: isList ? 0 : 10,\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n }}\n >\n <Group align=\"center\" gap=\"sm\" justify=\"space-between\" wrap=\"nowrap\" miw={0} w=\"100%\">\n <Stack gap={4} miw={0} style={{ flex: \"1 1 auto\", overflow: \"hidden\" }}>\n <Text\n aria-hidden\n c={PRIORITY_SEVERITY_COLORS[priority]}\n fw={650}\n size=\"xs\"\n style={{\n letterSpacing: \"0.03em\",\n lineHeight: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {resolvedSeverityLabel}\n </Text>\n\n <Text\n fw={600}\n lineClamp={2}\n size=\"sm\"\n c={fairmintVars.colorTextPrimary}\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n\n {hasDescription ? (\n <Text\n c={fairmintVars.colorTextSecondary}\n lineClamp={2}\n size=\"sm\"\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {description}\n </Text>\n ) : null}\n </Stack>\n\n <Group align=\"center\" gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n <Button\n {...actionProps}\n color={colors.primary}\n size=\"sm\"\n variant={isCritical ? \"filled\" : \"light\"}\n styles={{\n root: {\n // Keep CTA + dismiss inside the 420px inbox without x-scroll.\n maxWidth: 148,\n minWidth: 0,\n overflow: \"hidden\",\n },\n label: {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n }}\n >\n {actionLabel}\n </Button>\n {onDismiss ? (\n <ActionIcon\n aria-label={dismissLabel}\n color={colors.neutral}\n onClick={(event) => {\n // Keep the owning popover/dropdown open and make sure the\n // dismiss handler always receives the click (scroll overlays /\n // focus transfers can otherwise swallow it).\n event.preventDefault();\n event.stopPropagation();\n onDismiss();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n size=\"md\"\n style={{ flexShrink: 0 }}\n variant=\"subtle\"\n >\n <DefaultDismissIcon />\n </ActionIcon>\n ) : null}\n </Group>\n </Group>\n </Box>\n );\n}\n"],"names":["fairmintVars","jsxs","jsx","Box","Group","Stack","Text","Button","colors","ActionIcon"],"mappings":"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"}
1
+ {"version":3,"file":"TaskRow.cjs","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\n\nexport type TaskRowPriority = \"critical\" | \"high\" | \"medium\" | \"low\";\n\nexport type TaskRowVariant = \"standalone\" | \"list\";\n\nexport interface TaskRowActionProps\n extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\" | \"size\"> {\n /** Visible primary CTA label. */\n label: ReactNode;\n}\n\nexport interface TaskRowProps {\n /** Priority / urgency affordance. @default \"medium\" */\n priority?: TaskRowPriority;\n /**\n * Severity label shown above the title in uppercase plain text.\n * Defaults to the capitalized priority name (for example, \"Critical\", \"High\").\n */\n priorityLabel?: string;\n /** Task title. */\n title: string;\n /** Supporting description. */\n description: string;\n /**\n * Caller-formatted due date or age (for example, \"Due today\", \"3 days ago\").\n * Included in the accessible name when provided; not shown beside the CTA.\n */\n timingLabel?: string;\n /** Primary workflow CTA. */\n action: TaskRowActionProps;\n /**\n * Layout presentation. Use `list` inside a shared bordered stack so rows\n * sit flush with no card gaps. @default \"standalone\"\n */\n variant?: TaskRowVariant;\n /**\n * When `variant=\"list\"`, draw a bottom divider. Set false on the last row.\n * @default true\n */\n withDivider?: boolean;\n /** Optional dismiss or snooze handler. */\n onDismiss?: () => void;\n /** Accessible label for the dismiss control. @default \"Dismiss task\" */\n dismissLabel?: string;\n /** Accessible label for the row. Defaults to title plus timing when provided. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst PRIORITY_SEVERITY_COLORS = {\n critical: fairmintVars.colorErrorText,\n // Mid warning ramp (amber) — clearer than warning-text/solid brown vs error red.\n high: \"warning.5\",\n medium: \"warning.5\",\n low: fairmintVars.colorTextTertiary,\n} as const;\n\nconst DEFAULT_PRIORITY_LABELS: Record<TaskRowPriority, string> = {\n critical: \"Critical\",\n high: \"High\",\n medium: \"Medium\",\n low: \"Low\",\n};\n\n/** Soft critical tint that stays readable in Light and Dark (avoids solid error-bg in dark). */\nconst CRITICAL_ROW_BACKGROUND = `color-mix(in srgb, ${fairmintVars.colorErrorSolid} 18%, ${fairmintVars.colorBgSurface})`;\n\nfunction DefaultDismissIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * Presentational durable-task row for Studio Tasks and future Investor inbox work.\n *\n * Owns uppercase severity text above the title, description, a right-pinned\n * vertically centered `sm` primary CTA whose label is never ellipsis-truncated,\n * and optional dismiss. Only `critical` priority receives a semantic fill;\n * non-critical rows stay on the neutral list surface. The owning workflow\n * resolves completion; this row does not infer resolution from dismiss.\n */\nexport function TaskRow({\n action,\n ariaLabel,\n className,\n description,\n dismissLabel = \"Dismiss task\",\n onDismiss,\n priority = \"medium\",\n priorityLabel,\n timingLabel,\n title,\n variant = \"standalone\",\n withDivider = true,\n}: TaskRowProps) {\n const resolvedSeverityLabel = priorityLabel ?? DEFAULT_PRIORITY_LABELS[priority];\n const resolvedAriaLabel =\n ariaLabel ??\n (timingLabel\n ? `${title}. ${resolvedSeverityLabel} priority. ${timingLabel}`\n : `${title}. ${resolvedSeverityLabel} priority`);\n const isCritical = priority === \"critical\";\n const isList = variant === \"list\";\n const hasDescription = description.trim().length > 0;\n const { label: actionLabel, ...actionProps } = action;\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n role=\"group\"\n className={className}\n data-priority={priority}\n data-testid=\"task-row\"\n data-variant={variant}\n px=\"sm\"\n py={10}\n w=\"100%\"\n miw={0}\n maw=\"100%\"\n style={{\n background: isCritical ? CRITICAL_ROW_BACKGROUND : fairmintVars.colorBgSurface,\n border: isList ? \"none\" : `1px solid ${fairmintVars.colorBorderDefault}`,\n borderBottom:\n isList && withDivider ? `1px solid ${fairmintVars.colorBorderDefault}` : undefined,\n borderRadius: isList ? 0 : 10,\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n }}\n >\n <Group align=\"center\" gap=\"sm\" justify=\"space-between\" wrap=\"nowrap\" miw={0} w=\"100%\">\n <Stack gap={4} miw={0} style={{ flex: \"1 1 auto\", overflow: \"hidden\" }}>\n <Text\n aria-hidden\n c={PRIORITY_SEVERITY_COLORS[priority]}\n fw={650}\n size=\"xs\"\n style={{\n letterSpacing: \"0.03em\",\n lineHeight: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {resolvedSeverityLabel}\n </Text>\n\n <Text\n fw={600}\n lineClamp={2}\n size=\"sm\"\n c={fairmintVars.colorTextPrimary}\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n\n {hasDescription ? (\n <Text\n c={fairmintVars.colorTextSecondary}\n lineClamp={2}\n size=\"sm\"\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {description}\n </Text>\n ) : null}\n </Stack>\n\n <Group align=\"center\" gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n <Button\n {...actionProps}\n color={colors.primary}\n size=\"sm\"\n style={{\n ...actionProps.style,\n flexShrink: 0,\n whiteSpace: \"nowrap\",\n }}\n variant={isCritical ? \"filled\" : \"light\"}\n >\n {actionLabel}\n </Button>\n {onDismiss ? (\n <ActionIcon\n aria-label={dismissLabel}\n color={colors.neutral}\n onClick={(event) => {\n // Keep the owning popover/dropdown open and make sure the\n // dismiss handler always receives the click (scroll overlays /\n // focus transfers can otherwise swallow it).\n event.preventDefault();\n event.stopPropagation();\n onDismiss();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n size=\"md\"\n style={{ flexShrink: 0 }}\n variant=\"subtle\"\n >\n <DefaultDismissIcon />\n </ActionIcon>\n ) : null}\n </Group>\n </Group>\n </Box>\n );\n}\n"],"names":["fairmintVars","jsxs","jsx","Box","Group","Stack","Text","Button","colors","ActionIcon"],"mappings":"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"}
@@ -47,10 +47,10 @@ export interface TaskRowProps {
47
47
  * Presentational durable-task row for Studio Tasks and future Investor inbox work.
48
48
  *
49
49
  * Owns uppercase severity text above the title, description, a right-pinned
50
- * vertically centered `sm` primary CTA, and optional dismiss. Only `critical`
51
- * priority receives a semantic fill; non-critical rows stay on the neutral
52
- * list surface. The owning workflow resolves completion; this row does not
53
- * infer resolution from dismiss.
50
+ * vertically centered `sm` primary CTA whose label is never ellipsis-truncated,
51
+ * and optional dismiss. Only `critical` priority receives a semantic fill;
52
+ * non-critical rows stay on the neutral list surface. The owning workflow
53
+ * resolves completion; this row does not infer resolution from dismiss.
54
54
  */
55
55
  export declare function TaskRow({ action, ariaLabel, className, description, dismissLabel, onDismiss, priority, priorityLabel, timingLabel, title, variant, withDivider, }: TaskRowProps): import("react").JSX.Element;
56
56
  //# sourceMappingURL=TaskRow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TaskRow.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErE,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpE,iCAAiC;IACjC,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,MAAM,EAAE,kBAAkB,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,EACtB,MAAM,EACN,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAA6B,EAC7B,SAAS,EACT,QAAmB,EACnB,aAAa,EACb,WAAW,EACX,KAAK,EACL,OAAsB,EACtB,WAAkB,GACnB,EAAE,YAAY,+BA0Hd"}
1
+ {"version":3,"file":"TaskRow.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErE,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpE,iCAAiC;IACjC,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,MAAM,EAAE,kBAAkB,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,EACtB,MAAM,EACN,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAA6B,EAC7B,SAAS,EACT,QAAmB,EACnB,aAAa,EACb,WAAW,EACX,KAAK,EACL,OAAsB,EACtB,WAAkB,GACnB,EAAE,YAAY,+BAkHd"}
@@ -128,20 +128,12 @@ function TaskRow({
128
128
  ...actionProps,
129
129
  color: colors.primary,
130
130
  size: "sm",
131
- variant: isCritical ? "filled" : "light",
132
- styles: {
133
- root: {
134
- // Keep CTA + dismiss inside the 420px inbox without x-scroll.
135
- maxWidth: 148,
136
- minWidth: 0,
137
- overflow: "hidden"
138
- },
139
- label: {
140
- overflow: "hidden",
141
- textOverflow: "ellipsis",
142
- whiteSpace: "nowrap"
143
- }
131
+ style: {
132
+ ...actionProps.style,
133
+ flexShrink: 0,
134
+ whiteSpace: "nowrap"
144
135
  },
136
+ variant: isCritical ? "filled" : "light",
145
137
  children: actionLabel
146
138
  }
147
139
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"TaskRow.js","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\n\nexport type TaskRowPriority = \"critical\" | \"high\" | \"medium\" | \"low\";\n\nexport type TaskRowVariant = \"standalone\" | \"list\";\n\nexport interface TaskRowActionProps\n extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\" | \"size\"> {\n /** Visible primary CTA label. */\n label: ReactNode;\n}\n\nexport interface TaskRowProps {\n /** Priority / urgency affordance. @default \"medium\" */\n priority?: TaskRowPriority;\n /**\n * Severity label shown above the title in uppercase plain text.\n * Defaults to the capitalized priority name (for example, \"Critical\", \"High\").\n */\n priorityLabel?: string;\n /** Task title. */\n title: string;\n /** Supporting description. */\n description: string;\n /**\n * Caller-formatted due date or age (for example, \"Due today\", \"3 days ago\").\n * Included in the accessible name when provided; not shown beside the CTA.\n */\n timingLabel?: string;\n /** Primary workflow CTA. */\n action: TaskRowActionProps;\n /**\n * Layout presentation. Use `list` inside a shared bordered stack so rows\n * sit flush with no card gaps. @default \"standalone\"\n */\n variant?: TaskRowVariant;\n /**\n * When `variant=\"list\"`, draw a bottom divider. Set false on the last row.\n * @default true\n */\n withDivider?: boolean;\n /** Optional dismiss or snooze handler. */\n onDismiss?: () => void;\n /** Accessible label for the dismiss control. @default \"Dismiss task\" */\n dismissLabel?: string;\n /** Accessible label for the row. Defaults to title plus timing when provided. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst PRIORITY_SEVERITY_COLORS = {\n critical: fairmintVars.colorErrorText,\n // Mid warning ramp (amber) — clearer than warning-text/solid brown vs error red.\n high: \"warning.5\",\n medium: \"warning.5\",\n low: fairmintVars.colorTextTertiary,\n} as const;\n\nconst DEFAULT_PRIORITY_LABELS: Record<TaskRowPriority, string> = {\n critical: \"Critical\",\n high: \"High\",\n medium: \"Medium\",\n low: \"Low\",\n};\n\n/** Soft critical tint that stays readable in Light and Dark (avoids solid error-bg in dark). */\nconst CRITICAL_ROW_BACKGROUND = `color-mix(in srgb, ${fairmintVars.colorErrorSolid} 18%, ${fairmintVars.colorBgSurface})`;\n\nfunction DefaultDismissIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * Presentational durable-task row for Studio Tasks and future Investor inbox work.\n *\n * Owns uppercase severity text above the title, description, a right-pinned\n * vertically centered `sm` primary CTA, and optional dismiss. Only `critical`\n * priority receives a semantic fill; non-critical rows stay on the neutral\n * list surface. The owning workflow resolves completion; this row does not\n * infer resolution from dismiss.\n */\nexport function TaskRow({\n action,\n ariaLabel,\n className,\n description,\n dismissLabel = \"Dismiss task\",\n onDismiss,\n priority = \"medium\",\n priorityLabel,\n timingLabel,\n title,\n variant = \"standalone\",\n withDivider = true,\n}: TaskRowProps) {\n const resolvedSeverityLabel = priorityLabel ?? DEFAULT_PRIORITY_LABELS[priority];\n const resolvedAriaLabel =\n ariaLabel ??\n (timingLabel\n ? `${title}. ${resolvedSeverityLabel} priority. ${timingLabel}`\n : `${title}. ${resolvedSeverityLabel} priority`);\n const isCritical = priority === \"critical\";\n const isList = variant === \"list\";\n const hasDescription = description.trim().length > 0;\n const { label: actionLabel, ...actionProps } = action;\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n role=\"group\"\n className={className}\n data-priority={priority}\n data-testid=\"task-row\"\n data-variant={variant}\n px=\"sm\"\n py={10}\n w=\"100%\"\n miw={0}\n maw=\"100%\"\n style={{\n background: isCritical ? CRITICAL_ROW_BACKGROUND : fairmintVars.colorBgSurface,\n border: isList ? \"none\" : `1px solid ${fairmintVars.colorBorderDefault}`,\n borderBottom:\n isList && withDivider ? `1px solid ${fairmintVars.colorBorderDefault}` : undefined,\n borderRadius: isList ? 0 : 10,\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n }}\n >\n <Group align=\"center\" gap=\"sm\" justify=\"space-between\" wrap=\"nowrap\" miw={0} w=\"100%\">\n <Stack gap={4} miw={0} style={{ flex: \"1 1 auto\", overflow: \"hidden\" }}>\n <Text\n aria-hidden\n c={PRIORITY_SEVERITY_COLORS[priority]}\n fw={650}\n size=\"xs\"\n style={{\n letterSpacing: \"0.03em\",\n lineHeight: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {resolvedSeverityLabel}\n </Text>\n\n <Text\n fw={600}\n lineClamp={2}\n size=\"sm\"\n c={fairmintVars.colorTextPrimary}\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n\n {hasDescription ? (\n <Text\n c={fairmintVars.colorTextSecondary}\n lineClamp={2}\n size=\"sm\"\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {description}\n </Text>\n ) : null}\n </Stack>\n\n <Group align=\"center\" gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n <Button\n {...actionProps}\n color={colors.primary}\n size=\"sm\"\n variant={isCritical ? \"filled\" : \"light\"}\n styles={{\n root: {\n // Keep CTA + dismiss inside the 420px inbox without x-scroll.\n maxWidth: 148,\n minWidth: 0,\n overflow: \"hidden\",\n },\n label: {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n }}\n >\n {actionLabel}\n </Button>\n {onDismiss ? (\n <ActionIcon\n aria-label={dismissLabel}\n color={colors.neutral}\n onClick={(event) => {\n // Keep the owning popover/dropdown open and make sure the\n // dismiss handler always receives the click (scroll overlays /\n // focus transfers can otherwise swallow it).\n event.preventDefault();\n event.stopPropagation();\n onDismiss();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n size=\"md\"\n style={{ flexShrink: 0 }}\n variant=\"subtle\"\n >\n <DefaultDismissIcon />\n </ActionIcon>\n ) : null}\n </Group>\n </Group>\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskRow.js","sources":["../../../../src/components/generic/TaskRow/TaskRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { ActionIcon } from \"../../primitives/ActionIcon/ActionIcon\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, Text } from \"../../primitives/layout\";\n\nexport type TaskRowPriority = \"critical\" | \"high\" | \"medium\" | \"low\";\n\nexport type TaskRowVariant = \"standalone\" | \"list\";\n\nexport interface TaskRowActionProps\n extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\" | \"size\"> {\n /** Visible primary CTA label. */\n label: ReactNode;\n}\n\nexport interface TaskRowProps {\n /** Priority / urgency affordance. @default \"medium\" */\n priority?: TaskRowPriority;\n /**\n * Severity label shown above the title in uppercase plain text.\n * Defaults to the capitalized priority name (for example, \"Critical\", \"High\").\n */\n priorityLabel?: string;\n /** Task title. */\n title: string;\n /** Supporting description. */\n description: string;\n /**\n * Caller-formatted due date or age (for example, \"Due today\", \"3 days ago\").\n * Included in the accessible name when provided; not shown beside the CTA.\n */\n timingLabel?: string;\n /** Primary workflow CTA. */\n action: TaskRowActionProps;\n /**\n * Layout presentation. Use `list` inside a shared bordered stack so rows\n * sit flush with no card gaps. @default \"standalone\"\n */\n variant?: TaskRowVariant;\n /**\n * When `variant=\"list\"`, draw a bottom divider. Set false on the last row.\n * @default true\n */\n withDivider?: boolean;\n /** Optional dismiss or snooze handler. */\n onDismiss?: () => void;\n /** Accessible label for the dismiss control. @default \"Dismiss task\" */\n dismissLabel?: string;\n /** Accessible label for the row. Defaults to title plus timing when provided. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst PRIORITY_SEVERITY_COLORS = {\n critical: fairmintVars.colorErrorText,\n // Mid warning ramp (amber) — clearer than warning-text/solid brown vs error red.\n high: \"warning.5\",\n medium: \"warning.5\",\n low: fairmintVars.colorTextTertiary,\n} as const;\n\nconst DEFAULT_PRIORITY_LABELS: Record<TaskRowPriority, string> = {\n critical: \"Critical\",\n high: \"High\",\n medium: \"Medium\",\n low: \"Low\",\n};\n\n/** Soft critical tint that stays readable in Light and Dark (avoids solid error-bg in dark). */\nconst CRITICAL_ROW_BACKGROUND = `color-mix(in srgb, ${fairmintVars.colorErrorSolid} 18%, ${fairmintVars.colorBgSurface})`;\n\nfunction DefaultDismissIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n/**\n * Presentational durable-task row for Studio Tasks and future Investor inbox work.\n *\n * Owns uppercase severity text above the title, description, a right-pinned\n * vertically centered `sm` primary CTA whose label is never ellipsis-truncated,\n * and optional dismiss. Only `critical` priority receives a semantic fill;\n * non-critical rows stay on the neutral list surface. The owning workflow\n * resolves completion; this row does not infer resolution from dismiss.\n */\nexport function TaskRow({\n action,\n ariaLabel,\n className,\n description,\n dismissLabel = \"Dismiss task\",\n onDismiss,\n priority = \"medium\",\n priorityLabel,\n timingLabel,\n title,\n variant = \"standalone\",\n withDivider = true,\n}: TaskRowProps) {\n const resolvedSeverityLabel = priorityLabel ?? DEFAULT_PRIORITY_LABELS[priority];\n const resolvedAriaLabel =\n ariaLabel ??\n (timingLabel\n ? `${title}. ${resolvedSeverityLabel} priority. ${timingLabel}`\n : `${title}. ${resolvedSeverityLabel} priority`);\n const isCritical = priority === \"critical\";\n const isList = variant === \"list\";\n const hasDescription = description.trim().length > 0;\n const { label: actionLabel, ...actionProps } = action;\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n role=\"group\"\n className={className}\n data-priority={priority}\n data-testid=\"task-row\"\n data-variant={variant}\n px=\"sm\"\n py={10}\n w=\"100%\"\n miw={0}\n maw=\"100%\"\n style={{\n background: isCritical ? CRITICAL_ROW_BACKGROUND : fairmintVars.colorBgSurface,\n border: isList ? \"none\" : `1px solid ${fairmintVars.colorBorderDefault}`,\n borderBottom:\n isList && withDivider ? `1px solid ${fairmintVars.colorBorderDefault}` : undefined,\n borderRadius: isList ? 0 : 10,\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n }}\n >\n <Group align=\"center\" gap=\"sm\" justify=\"space-between\" wrap=\"nowrap\" miw={0} w=\"100%\">\n <Stack gap={4} miw={0} style={{ flex: \"1 1 auto\", overflow: \"hidden\" }}>\n <Text\n aria-hidden\n c={PRIORITY_SEVERITY_COLORS[priority]}\n fw={650}\n size=\"xs\"\n style={{\n letterSpacing: \"0.03em\",\n lineHeight: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {resolvedSeverityLabel}\n </Text>\n\n <Text\n fw={600}\n lineClamp={2}\n size=\"sm\"\n c={fairmintVars.colorTextPrimary}\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n\n {hasDescription ? (\n <Text\n c={fairmintVars.colorTextSecondary}\n lineClamp={2}\n size=\"sm\"\n style={{ minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {description}\n </Text>\n ) : null}\n </Stack>\n\n <Group align=\"center\" gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n <Button\n {...actionProps}\n color={colors.primary}\n size=\"sm\"\n style={{\n ...actionProps.style,\n flexShrink: 0,\n whiteSpace: \"nowrap\",\n }}\n variant={isCritical ? \"filled\" : \"light\"}\n >\n {actionLabel}\n </Button>\n {onDismiss ? (\n <ActionIcon\n aria-label={dismissLabel}\n color={colors.neutral}\n onClick={(event) => {\n // Keep the owning popover/dropdown open and make sure the\n // dismiss handler always receives the click (scroll overlays /\n // focus transfers can otherwise swallow it).\n event.preventDefault();\n event.stopPropagation();\n onDismiss();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n size=\"md\"\n style={{ flexShrink: 0 }}\n variant=\"subtle\"\n >\n <DefaultDismissIcon />\n </ActionIcon>\n ) : null}\n </Group>\n </Group>\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SideNav.cjs","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"sourcesContent":["import {\n ActionIcon,\n Box,\n Divider,\n Group,\n Menu,\n NavLink,\n type NavLinkProps,\n Stack,\n Tooltip,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { useUncontrolled } from \"@mantine/hooks\";\nimport { IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand } from \"@tabler/icons-react\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { fairmintVars, radii, spacing } from \"../../../theme\";\n\n/** Expanded product side-nav width (Brand System shell metric). */\nexport const SIDE_NAV_WIDTH = 260;\n\n/**\n * Collapsed icon-rail width.\n * Proposed shell metric for Dylan / Brand System review — not yet in Brand System v3.4.\n */\nexport const SIDE_NAV_COLLAPSED_WIDTH = 80;\n\n/**\n * Floating chrome (tooltips, nested flyouts) must clear Studio/Investor fixed\n * shell layers — side nav ≈1200, header ≈1201, menus ≥1300.\n */\nconst SIDE_NAV_FLOATING_Z_INDEX = 1300;\n\nexport interface SideNavItem {\n /** Unique identifier for this nav item (e.g., route path or slug). */\n id: string;\n /** Display label. */\n label: ReactNode;\n /**\n * Accessible name when `label` is not a plain string.\n * Also used for collapsed tooltips and letter-fallback derivation.\n */\n ariaLabel?: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Optional content rendered at the end of the item, such as a badge. */\n rightSection?: ReactNode;\n /** Whether this item is currently active. */\n active?: boolean;\n /** Whether the item is unavailable. */\n disabled?: boolean;\n /** Nested navigation items. */\n children?: SideNavItem[];\n /** Controlled expanded state for items with children. */\n open?: boolean;\n}\n\nexport interface SideNavSection {\n /** Unique identifier for the section. */\n id: string;\n /** Navigation items in this section. */\n items: SideNavItem[];\n}\n\nexport interface SideNavProps {\n /** Navigation items to render when section headings are not needed. */\n items?: SideNavItem[];\n /** Grouped navigation items. Sections are data-only — Fairmint product nav does not render section titles. */\n sections?: SideNavSection[];\n /** Callback when a nav item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n /** Active color. @default colors.primary */\n color?: string;\n /** Accessible label for the navigation landmark. @default \"Main navigation\" */\n ariaLabel?: string;\n /** Render a light right border when the parent shell does not already own the divider. @default false */\n withBorder?: boolean;\n /**\n * Logo or other chrome above the nav list.\n * Consumers own expanded wordmark vs collapsed mark switching.\n */\n header?: ReactNode;\n /**\n * Primary nav CTA pinned above the profile (Investor \"Add Investment\", Studio \"New\").\n * Prefer this over stuffing the CTA into `items`.\n */\n cta?: ReactNode;\n /**\n * Account / profile control pinned to the bottom of the rail.\n * Product shells keep profile here — not in the scrollable destination list or AppHeader.\n */\n profile?: ReactNode;\n /**\n * Custom bottom chrome. When set, replaces the standard `cta` + divider + `profile` composition.\n */\n footer?: ReactNode;\n /** Controlled collapsed (icon-rail) state. */\n collapsed?: boolean;\n /** Uncontrolled initial collapsed state. @default false */\n defaultCollapsed?: boolean;\n /** Called when the user toggles collapse. */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** When true, render a collapse/expand control beside the logo (visible on header hover). @default false */\n collapsible?: boolean;\n}\n\nfunction hasActiveDescendant(item: SideNavItem): boolean {\n return item.children?.some((child) => child.active || hasActiveDescendant(child)) ?? false;\n}\n\n/** Resolve a plain-text name for tooltips, aria-label, and letter fallback. */\nexport function getSideNavItemLabelText(item: Pick<SideNavItem, \"label\" | \"ariaLabel\">): string {\n if (item.ariaLabel) {\n return item.ariaLabel;\n }\n if (typeof item.label === \"string\") {\n return item.label;\n }\n if (typeof item.label === \"number\") {\n return String(item.label);\n }\n return \"Item\";\n}\n\n/** First letter/number monogram for icon-less items in the collapsed rail. */\nexport function getSideNavLetterFallback(labelText: string): string {\n const match = labelText.match(/[\\p{L}\\p{N}]/u);\n return match ? match[0].toUpperCase() : \"?\";\n}\n\nfunction LetterFallback({ letter, active = false }: { letter: string; active?: boolean }) {\n return (\n <Box\n component=\"span\"\n aria-hidden\n data-active={active || undefined}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 20,\n height: 20,\n flexShrink: 0,\n fontSize: 12,\n fontWeight: active ? 700 : 600,\n lineHeight: 1,\n // Selected chrome lives on the parent control — glyph matches icon sizing.\n color: active ? fairmintVars.colorIconOnSurfaceSelected : \"inherit\",\n }}\n >\n {letter}\n </Box>\n );\n}\n\nfunction CollapseToggle({\n collapsed,\n onToggle,\n visible,\n}: {\n collapsed: boolean;\n onToggle: () => void;\n /** When false, hide visually but keep focusable for keyboard users via opacity/focus styles. */\n visible: boolean;\n}) {\n const label = collapsed ? \"Expand navigation\" : \"Collapse navigation\";\n const Icon = collapsed ? IconLayoutSidebarLeftExpand : IconLayoutSidebarLeftCollapse;\n\n const button = (\n <UnstyledButton\n data-sidenav-collapse\n aria-label={label}\n aria-expanded={!collapsed}\n onClick={onToggle}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 32,\n flexShrink: 0,\n borderRadius: radii.md,\n color: fairmintVars.colorIconTertiary,\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? \"auto\" : \"none\",\n transition: \"opacity 120ms ease\",\n // Keep a layout slot when expanded so the wordmark does not shift on hover.\n // Collapsed: always a fixed control below the logo.\n width: 32,\n overflow: \"hidden\",\n padding: 0,\n }}\n >\n <Icon size={20} stroke={1.5} aria-hidden />\n </UnstyledButton>\n );\n\n if (!collapsed) {\n return button;\n }\n\n return (\n <Tooltip\n label={label}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n disabled={!visible}\n >\n {button}\n </Tooltip>\n );\n}\n\nfunction resolveLeftSection(\n item: SideNavItem,\n labelText: string,\n { requireIcon, active }: { requireIcon: boolean; active?: boolean },\n): ReactNode {\n if (item.icon) {\n return item.icon;\n }\n if (requireIcon) {\n return <LetterFallback letter={getSideNavLetterFallback(labelText)} active={Boolean(active)} />;\n }\n return undefined;\n}\n\n/** Collapsed rail control size — matches square CTA chrome. */\nconst COLLAPSED_ITEM_SIZE = 36;\n\n/**\n * Nested leaf indent so label text lines up with parent labels.\n * Parent rows use a 20px icon + `spacing.sm` section gap before the label.\n */\nconst NESTED_NAV_CHILDREN_OFFSET = `calc(20px + ${spacing.sm})`;\n\nconst navLinkStyles = (active: boolean | undefined): NavLinkProps[\"styles\"] => ({\n root: {\n color: active ? fairmintVars.colorTextPrimary : fairmintVars.colorTextSecondary,\n fontWeight: active ? 500 : 400,\n borderRadius: radii.md,\n // Prefer Fairmint selected surface over Mantine defaults for active chrome.\n ...(active\n ? {\n \"--nl-bg\": fairmintVars.colorSurfaceSelected,\n \"--nl-hover\": fairmintVars.colorSurfaceSelected,\n \"--nl-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n }\n : {}),\n },\n section: {\n color: active ? fairmintVars.colorIconOnSurfaceSelected : fairmintVars.colorIconTertiary,\n },\n});\n\ninterface SideNavNodeProps {\n color: string;\n item: SideNavItem;\n onItemClick: (id: string) => void;\n collapsed: boolean;\n}\n\nfunction ExpandedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const containsActiveItem = hasActiveDescendant(item);\n const [opened, setOpened] = useState(item.open ?? containsActiveItem);\n const labelText = getSideNavItemLabelText(item);\n\n useEffect(() => {\n if (item.open !== undefined) {\n setOpened(item.open);\n } else if (containsActiveItem) {\n setOpened(true);\n }\n }, [containsActiveItem, item.open]);\n\n const hasChildren = Boolean(item.children?.length);\n\n return (\n <NavLink\n component=\"button\"\n type=\"button\"\n label={item.label}\n leftSection={resolveLeftSection(item, labelText, {\n requireIcon: false,\n active: item.active,\n })}\n rightSection={item.rightSection}\n active={item.active}\n disabled={item.disabled}\n color={color}\n variant=\"light\"\n childrenOffset={NESTED_NAV_CHILDREN_OFFSET}\n opened={hasChildren ? opened : undefined}\n aria-label={item.ariaLabel}\n onClick={\n hasChildren\n ? () => setOpened((currentOpened) => !currentOpened)\n : () => onItemClick(item.id)\n }\n styles={navLinkStyles(item.active)}\n >\n {item.children?.map((child) => (\n <ExpandedSideNavNode key={child.id} item={child} color={color} onItemClick={onItemClick} />\n ))}\n </NavLink>\n );\n}\n\n/** Flatten nested groups to leaves for the collapsed flyout (one actionable list). */\nfunction collectCollapsedMenuLeaves(items: SideNavItem[]): SideNavItem[] {\n return items.flatMap((item) =>\n item.children?.length ? collectCollapsedMenuLeaves(item.children) : [item],\n );\n}\n\nfunction CollapsedNestedMenuItems({\n items,\n onItemClick,\n color,\n}: {\n items: SideNavItem[];\n onItemClick: (id: string) => void;\n color: string;\n}) {\n return collectCollapsedMenuLeaves(items).map((child) => {\n const childLabel = getSideNavItemLabelText(child);\n const isActive = Boolean(child.active);\n return (\n <Menu.Item\n key={child.id}\n disabled={child.disabled}\n // Flyout rows already show the full label — only keep a real icon, not a letter monogram.\n leftSection={resolveLeftSection(child, childLabel, {\n requireIcon: false,\n active: isActive,\n })}\n onClick={() => onItemClick(child.id)}\n // Only apply an explicit override — never stamp the generic \"Item\" fallback\n // over a React-node label's naturally derived accessible name.\n aria-label={child.ariaLabel}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n color={isActive ? color : undefined}\n style={\n isActive\n ? {\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n fontWeight: 600,\n }\n : undefined\n }\n >\n {child.label}\n </Menu.Item>\n );\n });\n}\n\nfunction CollapsedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const labelText = getSideNavItemLabelText(item);\n const hasChildren = Boolean(item.children?.length);\n const isActive = Boolean(item.active || hasActiveDescendant(item));\n const leftSection = resolveLeftSection(item, labelText, {\n requireIcon: true,\n active: isActive,\n });\n\n // ActionIcon (not NavLink): NavLink.css forces `width: 100%` and asymmetric\n // horizontal padding, which makes selected/hover chrome a wide pill.\n // Selected fill uses Fairmint surface/selected — Mantine `light` is too dim in dark mode.\n const link = (\n <ActionIcon\n type=\"button\"\n variant=\"subtle\"\n color={color}\n size={COLLAPSED_ITEM_SIZE}\n radius=\"md\"\n disabled={item.disabled}\n aria-label={labelText}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n onClick={hasChildren ? undefined : () => onItemClick(item.id)}\n style={{\n width: COLLAPSED_ITEM_SIZE,\n height: COLLAPSED_ITEM_SIZE,\n minWidth: COLLAPSED_ITEM_SIZE,\n minHeight: COLLAPSED_ITEM_SIZE,\n ...(isActive\n ? {\n \"--ai-bg\": fairmintVars.colorSurfaceSelected,\n \"--ai-hover\": fairmintVars.colorSurfaceSelected,\n \"--ai-color\": fairmintVars.colorIconOnSurfaceSelected,\n \"--ai-hover-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n }\n : {\n color: fairmintVars.colorIconTertiary,\n }),\n }}\n >\n {leftSection}\n </ActionIcon>\n );\n\n const control = hasChildren ? (\n <Menu position=\"right-start\" offset={8} withinPortal zIndex={SIDE_NAV_FLOATING_Z_INDEX}>\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n <Menu.Target>{link}</Menu.Target>\n </Tooltip>\n <Menu.Dropdown>\n <CollapsedNestedMenuItems\n items={item.children ?? []}\n onItemClick={onItemClick}\n color={color}\n />\n </Menu.Dropdown>\n </Menu>\n ) : (\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n {link}\n </Tooltip>\n );\n\n // Uniform Stack child so Menu vs Tooltip wrappers cannot skew item gaps.\n return <Box style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>{control}</Box>;\n}\n\nfunction SideNavNode(props: SideNavNodeProps) {\n if (props.collapsed) {\n return <CollapsedSideNavNode {...props} />;\n }\n return <ExpandedSideNavNode {...props} />;\n}\n\nexport function SideNav({\n items = [],\n sections,\n onItemClick,\n color = \"indigo\",\n ariaLabel = \"Main navigation\",\n withBorder = false,\n header,\n cta,\n profile,\n footer,\n collapsed,\n defaultCollapsed = false,\n onCollapsedChange,\n collapsible = false,\n}: SideNavProps) {\n const resolvedSections = sections ?? [{ id: \"main\", items }];\n const [collapsedState, setCollapsedState] = useUncontrolled({\n value: collapsed,\n defaultValue: defaultCollapsed,\n finalValue: false,\n onChange: onCollapsedChange,\n });\n\n const hasBottomChrome = Boolean(footer || cta || profile);\n const [headerHovered, setHeaderHovered] = useState(false);\n const showExpandedCollapseControl = headerHovered;\n const showHeaderChrome = Boolean(header) || collapsible;\n\n const collapseToggle = collapsible ? (\n <CollapseToggle\n collapsed={collapsedState}\n visible={collapsedState ? true : showExpandedCollapseControl}\n onToggle={() => setCollapsedState(!collapsedState)}\n />\n ) : null;\n\n return (\n <Stack\n component=\"nav\"\n gap=\"md\"\n h=\"100%\"\n p={collapsedState ? \"sm\" : \"md\"}\n aria-label={ariaLabel}\n data-collapsed={collapsedState || undefined}\n style={{\n borderRight: withBorder ? \"1px solid\" : undefined,\n borderRightColor: withBorder ? fairmintVars.colorBorderDefault : undefined,\n boxShadow: \"none\",\n }}\n >\n {showHeaderChrome ? (\n collapsedState ? (\n <Stack gap={6} align=\"center\">\n {header ? (\n <Box\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Stack>\n ) : (\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"xs\"\n align=\"center\"\n style={{ minHeight: 32 }}\n onMouseEnter={() => setHeaderHovered(true)}\n onMouseLeave={() => setHeaderHovered(false)}\n onFocusCapture={() => setHeaderHovered(true)}\n onBlurCapture={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n setHeaderHovered(false);\n }\n }}\n >\n {header ? (\n <Box\n style={{\n flex: 1,\n minWidth: 0,\n overflow: \"hidden\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-start\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Group>\n )\n ) : null}\n\n <Stack gap={4} style={{ flex: 1, minHeight: 0, overflow: \"auto\" }}>\n {resolvedSections.flatMap((section) =>\n section.items.map((item) => (\n <SideNavNode\n key={`${section.id}:${item.id}`}\n item={item}\n color={color}\n onItemClick={onItemClick}\n collapsed={collapsedState}\n />\n )),\n )}\n </Stack>\n\n {hasBottomChrome ? (\n <Stack gap=\"sm\" style={{ flexShrink: 0 }}>\n {footer ?? (\n <>\n {cta ? (\n <Box\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: collapsedState ? \"center\" : \"stretch\",\n }}\n >\n {cta}\n </Box>\n ) : null}\n {cta && profile ? <Divider color={fairmintVars.colorBorderDefault} /> : null}\n {profile ? <Box style={{ width: \"100%\" }}>{profile}</Box> : null}\n </>\n )}\n </Stack>\n ) : null}\n </Stack>\n );\n}\n"],"names":["jsx","Box","fairmintVars","IconLayoutSidebarLeftExpand","IconLayoutSidebarLeftCollapse","UnstyledButton","radii","Tooltip","spacing","useState","useEffect","NavLink","Menu","ActionIcon","jsxs","useUncontrolled","Stack","Group","Fragment","Divider"],"mappings":"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"}
1
+ {"version":3,"file":"SideNav.cjs","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"sourcesContent":["import {\n ActionIcon,\n Box,\n Divider,\n Group,\n Menu,\n NavLink,\n type NavLinkProps,\n Stack,\n Tooltip,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { useUncontrolled } from \"@mantine/hooks\";\nimport { IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand } from \"@tabler/icons-react\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { fairmintVars, radii, spacing } from \"../../../theme\";\n\n/** Expanded product side-nav width (Brand System shell metric). */\nexport const SIDE_NAV_WIDTH = 260;\n\n/**\n * Collapsed icon-rail width (Brand System v3.5+ shell metric).\n */\nexport const SIDE_NAV_COLLAPSED_WIDTH = 80;\n\n/**\n * Floating chrome (tooltips, nested flyouts) must clear Studio/Investor fixed\n * shell layers — side nav ≈1200, header ≈1201, menus ≥1300.\n */\nconst SIDE_NAV_FLOATING_Z_INDEX = 1300;\n\nexport interface SideNavItem {\n /** Unique identifier for this nav item (e.g., route path or slug). */\n id: string;\n /** Display label. */\n label: ReactNode;\n /**\n * Accessible name when `label` is not a plain string.\n * Also used for collapsed tooltips and letter-fallback derivation.\n */\n ariaLabel?: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Optional content rendered at the end of the item, such as a badge. */\n rightSection?: ReactNode;\n /** Whether this item is currently active. */\n active?: boolean;\n /** Whether the item is unavailable. */\n disabled?: boolean;\n /** Nested navigation items. */\n children?: SideNavItem[];\n /** Controlled expanded state for items with children. */\n open?: boolean;\n}\n\nexport interface SideNavSection {\n /** Unique identifier for the section. */\n id: string;\n /** Navigation items in this section. */\n items: SideNavItem[];\n}\n\nexport interface SideNavProps {\n /** Navigation items to render when section headings are not needed. */\n items?: SideNavItem[];\n /** Grouped navigation items. Sections are data-only — Fairmint product nav does not render section titles. */\n sections?: SideNavSection[];\n /** Callback when a nav item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n /** Active color. @default colors.primary */\n color?: string;\n /** Accessible label for the navigation landmark. @default \"Main navigation\" */\n ariaLabel?: string;\n /** Render a light right border when the parent shell does not already own the divider. @default false */\n withBorder?: boolean;\n /**\n * Logo or other chrome above the nav list.\n * Consumers own expanded wordmark vs collapsed mark switching.\n */\n header?: ReactNode;\n /**\n * Primary nav CTA pinned above the profile (Investor \"Add Investment\", Studio \"New\").\n * Prefer this over stuffing the CTA into `items`.\n */\n cta?: ReactNode;\n /**\n * Account / profile control pinned to the bottom of the rail.\n * Product shells keep profile here — not in the scrollable destination list or AppHeader.\n */\n profile?: ReactNode;\n /**\n * Custom bottom chrome. When set, replaces the standard `cta` + divider + `profile` composition.\n */\n footer?: ReactNode;\n /** Controlled collapsed (icon-rail) state. */\n collapsed?: boolean;\n /** Uncontrolled initial collapsed state. @default false */\n defaultCollapsed?: boolean;\n /** Called when the user toggles collapse. */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** When true, render a collapse/expand control beside the logo (visible on header hover). @default false */\n collapsible?: boolean;\n}\n\nfunction hasActiveDescendant(item: SideNavItem): boolean {\n return item.children?.some((child) => child.active || hasActiveDescendant(child)) ?? false;\n}\n\n/** Resolve a plain-text name for tooltips, aria-label, and letter fallback. */\nexport function getSideNavItemLabelText(item: Pick<SideNavItem, \"label\" | \"ariaLabel\">): string {\n if (item.ariaLabel) {\n return item.ariaLabel;\n }\n if (typeof item.label === \"string\") {\n return item.label;\n }\n if (typeof item.label === \"number\") {\n return String(item.label);\n }\n return \"Item\";\n}\n\n/** First letter/number monogram for icon-less items in the collapsed rail. */\nexport function getSideNavLetterFallback(labelText: string): string {\n const match = labelText.match(/[\\p{L}\\p{N}]/u);\n return match ? match[0].toUpperCase() : \"?\";\n}\n\nfunction LetterFallback({ letter, active = false }: { letter: string; active?: boolean }) {\n return (\n <Box\n component=\"span\"\n aria-hidden\n data-active={active || undefined}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 20,\n height: 20,\n flexShrink: 0,\n fontSize: 12,\n fontWeight: active ? 700 : 600,\n lineHeight: 1,\n // Selected chrome lives on the parent control — glyph matches icon sizing.\n color: active ? fairmintVars.colorIconOnSurfaceSelected : \"inherit\",\n }}\n >\n {letter}\n </Box>\n );\n}\n\nfunction CollapseToggle({\n collapsed,\n onToggle,\n visible,\n}: {\n collapsed: boolean;\n onToggle: () => void;\n /** When false, hide visually but keep focusable for keyboard users via opacity/focus styles. */\n visible: boolean;\n}) {\n const label = collapsed ? \"Expand navigation\" : \"Collapse navigation\";\n const Icon = collapsed ? IconLayoutSidebarLeftExpand : IconLayoutSidebarLeftCollapse;\n\n const button = (\n <UnstyledButton\n data-sidenav-collapse\n aria-label={label}\n aria-expanded={!collapsed}\n onClick={onToggle}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 32,\n flexShrink: 0,\n borderRadius: radii.md,\n color: fairmintVars.colorIconTertiary,\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? \"auto\" : \"none\",\n transition: \"opacity 120ms ease\",\n // Keep a layout slot when expanded so the wordmark does not shift on hover.\n // Collapsed: always a fixed control below the logo.\n width: 32,\n overflow: \"hidden\",\n padding: 0,\n }}\n >\n <Icon size={20} stroke={1.5} aria-hidden />\n </UnstyledButton>\n );\n\n if (!collapsed) {\n return button;\n }\n\n return (\n <Tooltip\n label={label}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n disabled={!visible}\n >\n {button}\n </Tooltip>\n );\n}\n\nfunction resolveLeftSection(\n item: SideNavItem,\n labelText: string,\n { requireIcon, active }: { requireIcon: boolean; active?: boolean },\n): ReactNode {\n if (item.icon) {\n return item.icon;\n }\n if (requireIcon) {\n return <LetterFallback letter={getSideNavLetterFallback(labelText)} active={Boolean(active)} />;\n }\n return undefined;\n}\n\n/** Collapsed rail control size — matches square CTA chrome. */\nconst COLLAPSED_ITEM_SIZE = 36;\n\n/**\n * Nested leaf indent so label text lines up with parent labels.\n * Parent rows use a 20px icon + `spacing.sm` section gap before the label.\n */\nconst NESTED_NAV_CHILDREN_OFFSET = `calc(20px + ${spacing.sm})`;\n\nconst navLinkStyles = (active: boolean | undefined): NavLinkProps[\"styles\"] => ({\n root: {\n color: active ? fairmintVars.colorTextPrimary : fairmintVars.colorTextSecondary,\n fontWeight: active ? 500 : 400,\n borderRadius: radii.md,\n // Prefer Fairmint selected surface over Mantine defaults for active chrome.\n ...(active\n ? {\n \"--nl-bg\": fairmintVars.colorSurfaceSelected,\n \"--nl-hover\": fairmintVars.colorSurfaceSelected,\n \"--nl-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n }\n : {}),\n },\n section: {\n color: active ? fairmintVars.colorIconOnSurfaceSelected : fairmintVars.colorIconTertiary,\n },\n});\n\ninterface SideNavNodeProps {\n color: string;\n item: SideNavItem;\n onItemClick: (id: string) => void;\n collapsed: boolean;\n}\n\nfunction ExpandedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const containsActiveItem = hasActiveDescendant(item);\n const [opened, setOpened] = useState(item.open ?? containsActiveItem);\n const labelText = getSideNavItemLabelText(item);\n\n useEffect(() => {\n if (item.open !== undefined) {\n setOpened(item.open);\n } else if (containsActiveItem) {\n setOpened(true);\n }\n }, [containsActiveItem, item.open]);\n\n const hasChildren = Boolean(item.children?.length);\n\n return (\n <NavLink\n component=\"button\"\n type=\"button\"\n label={item.label}\n leftSection={resolveLeftSection(item, labelText, {\n requireIcon: false,\n active: item.active,\n })}\n rightSection={item.rightSection}\n active={item.active}\n disabled={item.disabled}\n color={color}\n variant=\"light\"\n childrenOffset={NESTED_NAV_CHILDREN_OFFSET}\n opened={hasChildren ? opened : undefined}\n aria-label={item.ariaLabel}\n onClick={\n hasChildren\n ? () => setOpened((currentOpened) => !currentOpened)\n : () => onItemClick(item.id)\n }\n styles={navLinkStyles(item.active)}\n >\n {item.children?.map((child) => (\n <ExpandedSideNavNode key={child.id} item={child} color={color} onItemClick={onItemClick} />\n ))}\n </NavLink>\n );\n}\n\n/** Flatten nested groups to leaves for the collapsed flyout (one actionable list). */\nfunction collectCollapsedMenuLeaves(items: SideNavItem[]): SideNavItem[] {\n return items.flatMap((item) =>\n item.children?.length ? collectCollapsedMenuLeaves(item.children) : [item],\n );\n}\n\nfunction CollapsedNestedMenuItems({\n items,\n onItemClick,\n color,\n}: {\n items: SideNavItem[];\n onItemClick: (id: string) => void;\n color: string;\n}) {\n return collectCollapsedMenuLeaves(items).map((child) => {\n const childLabel = getSideNavItemLabelText(child);\n const isActive = Boolean(child.active);\n return (\n <Menu.Item\n key={child.id}\n disabled={child.disabled}\n // Flyout rows already show the full label — only keep a real icon, not a letter monogram.\n leftSection={resolveLeftSection(child, childLabel, {\n requireIcon: false,\n active: isActive,\n })}\n onClick={() => onItemClick(child.id)}\n // Only apply an explicit override — never stamp the generic \"Item\" fallback\n // over a React-node label's naturally derived accessible name.\n aria-label={child.ariaLabel}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n color={isActive ? color : undefined}\n style={\n isActive\n ? {\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n fontWeight: 600,\n }\n : undefined\n }\n >\n {child.label}\n </Menu.Item>\n );\n });\n}\n\nfunction CollapsedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const labelText = getSideNavItemLabelText(item);\n const hasChildren = Boolean(item.children?.length);\n const isActive = Boolean(item.active || hasActiveDescendant(item));\n const leftSection = resolveLeftSection(item, labelText, {\n requireIcon: true,\n active: isActive,\n });\n\n // ActionIcon (not NavLink): NavLink.css forces `width: 100%` and asymmetric\n // horizontal padding, which makes selected/hover chrome a wide pill.\n // Selected fill uses Fairmint surface/selected — Mantine `light` is too dim in dark mode.\n const link = (\n <ActionIcon\n type=\"button\"\n variant=\"subtle\"\n color={color}\n size={COLLAPSED_ITEM_SIZE}\n radius=\"md\"\n disabled={item.disabled}\n aria-label={labelText}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n onClick={hasChildren ? undefined : () => onItemClick(item.id)}\n style={{\n width: COLLAPSED_ITEM_SIZE,\n height: COLLAPSED_ITEM_SIZE,\n minWidth: COLLAPSED_ITEM_SIZE,\n minHeight: COLLAPSED_ITEM_SIZE,\n ...(isActive\n ? {\n \"--ai-bg\": fairmintVars.colorSurfaceSelected,\n \"--ai-hover\": fairmintVars.colorSurfaceSelected,\n \"--ai-color\": fairmintVars.colorIconOnSurfaceSelected,\n \"--ai-hover-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n }\n : {\n color: fairmintVars.colorIconTertiary,\n }),\n }}\n >\n {leftSection}\n </ActionIcon>\n );\n\n const control = hasChildren ? (\n <Menu position=\"right-start\" offset={8} withinPortal zIndex={SIDE_NAV_FLOATING_Z_INDEX}>\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n <Menu.Target>{link}</Menu.Target>\n </Tooltip>\n <Menu.Dropdown>\n <CollapsedNestedMenuItems\n items={item.children ?? []}\n onItemClick={onItemClick}\n color={color}\n />\n </Menu.Dropdown>\n </Menu>\n ) : (\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n {link}\n </Tooltip>\n );\n\n // Uniform Stack child so Menu vs Tooltip wrappers cannot skew item gaps.\n return <Box style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>{control}</Box>;\n}\n\nfunction SideNavNode(props: SideNavNodeProps) {\n if (props.collapsed) {\n return <CollapsedSideNavNode {...props} />;\n }\n return <ExpandedSideNavNode {...props} />;\n}\n\nexport function SideNav({\n items = [],\n sections,\n onItemClick,\n color = \"indigo\",\n ariaLabel = \"Main navigation\",\n withBorder = false,\n header,\n cta,\n profile,\n footer,\n collapsed,\n defaultCollapsed = false,\n onCollapsedChange,\n collapsible = false,\n}: SideNavProps) {\n const resolvedSections = sections ?? [{ id: \"main\", items }];\n const [collapsedState, setCollapsedState] = useUncontrolled({\n value: collapsed,\n defaultValue: defaultCollapsed,\n finalValue: false,\n onChange: onCollapsedChange,\n });\n\n const hasBottomChrome = Boolean(footer || cta || profile);\n const [headerHovered, setHeaderHovered] = useState(false);\n const showExpandedCollapseControl = headerHovered;\n const showHeaderChrome = Boolean(header) || collapsible;\n\n const collapseToggle = collapsible ? (\n <CollapseToggle\n collapsed={collapsedState}\n visible={collapsedState ? true : showExpandedCollapseControl}\n onToggle={() => setCollapsedState(!collapsedState)}\n />\n ) : null;\n\n return (\n <Stack\n component=\"nav\"\n gap=\"md\"\n h=\"100%\"\n p={collapsedState ? \"sm\" : \"md\"}\n aria-label={ariaLabel}\n data-collapsed={collapsedState || undefined}\n style={{\n borderRight: withBorder ? \"1px solid\" : undefined,\n borderRightColor: withBorder ? fairmintVars.colorBorderDefault : undefined,\n boxShadow: \"none\",\n }}\n >\n {showHeaderChrome ? (\n collapsedState ? (\n <Stack gap={6} align=\"center\">\n {header ? (\n <Box\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Stack>\n ) : (\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"xs\"\n align=\"center\"\n style={{ minHeight: 32 }}\n onMouseEnter={() => setHeaderHovered(true)}\n onMouseLeave={() => setHeaderHovered(false)}\n onFocusCapture={() => setHeaderHovered(true)}\n onBlurCapture={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n setHeaderHovered(false);\n }\n }}\n >\n {header ? (\n <Box\n style={{\n flex: 1,\n minWidth: 0,\n overflow: \"hidden\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-start\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Group>\n )\n ) : null}\n\n <Stack gap={4} style={{ flex: 1, minHeight: 0, overflow: \"auto\" }}>\n {resolvedSections.flatMap((section) =>\n section.items.map((item) => (\n <SideNavNode\n key={`${section.id}:${item.id}`}\n item={item}\n color={color}\n onItemClick={onItemClick}\n collapsed={collapsedState}\n />\n )),\n )}\n </Stack>\n\n {hasBottomChrome ? (\n <Stack gap=\"sm\" style={{ flexShrink: 0 }}>\n {footer ?? (\n <>\n {cta ? (\n <Box\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: collapsedState ? \"center\" : \"stretch\",\n }}\n >\n {cta}\n </Box>\n ) : null}\n {cta && profile ? <Divider color={fairmintVars.colorBorderDefault} /> : null}\n {profile ? <Box style={{ width: \"100%\" }}>{profile}</Box> : null}\n </>\n )}\n </Stack>\n ) : null}\n </Stack>\n );\n}\n"],"names":["jsx","Box","fairmintVars","IconLayoutSidebarLeftExpand","IconLayoutSidebarLeftCollapse","UnstyledButton","radii","Tooltip","spacing","useState","useEffect","NavLink","Menu","ActionIcon","jsxs","useUncontrolled","Stack","Group","Fragment","Divider"],"mappings":";;;;;;;;;;;;;;;;;;AAkBO,MAAM,iBAAiB;AAKvB,MAAM,2BAA2B;AAMxC,MAAM,4BAA4B;AA2ElC,SAAS,oBAAoB,MAA4B;AACvD,SAAO,KAAK,UAAU,KAAK,CAAC,UAAU,MAAM,UAAU,oBAAoB,KAAK,CAAC,KAAK;AACvF;AAGO,SAAS,wBAAwB,MAAwD;AAC9F,MAAI,KAAK,WAAW;AAClB,WAAO,KAAK;AAAA,EACd;AACA,MAAI,OAAO,KAAK,UAAU,UAAU;AAClC,WAAO,KAAK;AAAA,EACd;AACA,MAAI,OAAO,KAAK,UAAU,UAAU;AAClC,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B;AACA,SAAO;AACT;AAGO,SAAS,yBAAyB,WAA2B;AAClE,QAAM,QAAQ,UAAU,MAAM,eAAe;AAC7C,SAAO,QAAQ,MAAM,CAAC,EAAE,gBAAgB;AAC1C;AAEA,SAAS,eAAe,EAAE,QAAQ,SAAS,SAA+C;AACxF,SACEA,2BAAAA;AAAAA,IAACC,IAAAA;AAAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAW;AAAA,MACX,eAAa,UAAU;AAAA,MACvB,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY,SAAS,MAAM;AAAA,QAC3B,YAAY;AAAA;AAAA,QAEZ,OAAO,SAASC,MAAAA,aAAa,6BAA6B;AAAA,MAAA;AAAA,MAG3D,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQ,YAAY,sBAAsB;AAChD,QAAM,OAAO,YAAYC,4BAAAA,UAA8BC,8BAAAA;AAEvD,QAAM,SACJJ,2BAAAA;AAAAA,IAACK,eAAAA;AAAAA,IAAA;AAAA,MACC,yBAAqB;AAAA,MACrB,cAAY;AAAA,MACZ,iBAAe,CAAC;AAAA,MAChB,SAAS;AAAA,MACT,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,cAAcC,MAAAA,MAAM;AAAA,QACpB,OAAOJ,MAAAA,aAAa;AAAA,QACpB,SAAS,UAAU,IAAI;AAAA,QACvB,eAAe,UAAU,SAAS;AAAA,QAClC,YAAY;AAAA;AAAA;AAAA,QAGZ,OAAO;AAAA,QACP,UAAU;AAAA,QACV,SAAS;AAAA,MAAA;AAAA,MAGX,yCAAC,MAAA,EAAK,MAAM,IAAI,QAAQ,KAAK,eAAW,KAAA,CAAC;AAAA,IAAA;AAAA,EAAA;AAI7C,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,SACEF,2BAAAA;AAAAA,IAACO,QAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAS;AAAA,MACT,WAAS;AAAA,MACT,cAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ,EAAE,OAAO,MAAM,OAAO,MAAM,OAAO,KAAA;AAAA,MAC3C,UAAU,CAAC;AAAA,MAEV,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,SAAS,mBACP,MACA,WACA,EAAE,aAAa,UACJ;AACX,MAAI,KAAK,MAAM;AACb,WAAO,KAAK;AAAA,EACd;AACA,MAAI,aAAa;AACf,WAAOP,+BAAC,kBAAe,QAAQ,yBAAyB,SAAS,GAAG,QAAQ,QAAQ,MAAM,GAAG;AAAA,EAC/F;AACA,SAAO;AACT;AAGA,MAAM,sBAAsB;AAM5B,MAAM,6BAA6B,eAAeQ,gBAAQ,EAAE;AAE5D,MAAM,gBAAgB,CAAC,YAAyD;AAAA,EAC9E,MAAM;AAAA,IACJ,OAAO,SAASN,MAAAA,aAAa,mBAAmBA,MAAAA,aAAa;AAAA,IAC7D,YAAY,SAAS,MAAM;AAAA,IAC3B,cAAcI,MAAAA,MAAM;AAAA;AAAA,IAEpB,GAAI,SACA;AAAA,MACE,WAAWJ,MAAAA,aAAa;AAAA,MACxB,cAAcA,MAAAA,aAAa;AAAA,MAC3B,cAAcA,MAAAA,aAAa;AAAA,MAC3B,iBAAiBA,MAAAA,aAAa;AAAA,IAAA,IAEhC,CAAA;AAAA,EAAC;AAAA,EAEP,SAAS;AAAA,IACP,OAAO,SAASA,mBAAa,6BAA6BA,MAAAA,aAAa;AAAA,EAAA;AAE3E;AASA,SAAS,oBAAoB,EAAE,OAAO,MAAM,eAAoD;AAC9F,QAAM,qBAAqB,oBAAoB,IAAI;AACnD,QAAM,CAAC,QAAQ,SAAS,IAAIO,MAAAA,SAAS,KAAK,QAAQ,kBAAkB;AACpE,QAAM,YAAY,wBAAwB,IAAI;AAE9CC,QAAAA,UAAU,MAAM;AACd,QAAI,KAAK,SAAS,QAAW;AAC3B,gBAAU,KAAK,IAAI;AAAA,IACrB,WAAW,oBAAoB;AAC7B,gBAAU,IAAI;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,oBAAoB,KAAK,IAAI,CAAC;AAElC,QAAM,cAAc,QAAQ,KAAK,UAAU,MAAM;AAEjD,SACEV,2BAAAA;AAAAA,IAACW,QAAAA;AAAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,aAAa,mBAAmB,MAAM,WAAW;AAAA,QAC/C,aAAa;AAAA,QACb,QAAQ,KAAK;AAAA,MAAA,CACd;AAAA,MACD,cAAc,KAAK;AAAA,MACnB,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf;AAAA,MACA,SAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,QAAQ,cAAc,SAAS;AAAA,MAC/B,cAAY,KAAK;AAAA,MACjB,SACE,cACI,MAAM,UAAU,CAAC,kBAAkB,CAAC,aAAa,IACjD,MAAM,YAAY,KAAK,EAAE;AAAA,MAE/B,QAAQ,cAAc,KAAK,MAAM;AAAA,MAEhC,UAAA,KAAK,UAAU,IAAI,CAAC,UACnBX,2BAAAA,IAAC,qBAAA,EAAmC,MAAM,OAAO,OAAc,YAAA,GAArC,MAAM,EAAyD,CAC1F;AAAA,IAAA;AAAA,EAAA;AAGP;AAGA,SAAS,2BAA2B,OAAqC;AACvE,SAAO,MAAM;AAAA,IAAQ,CAAC,SACpB,KAAK,UAAU,SAAS,2BAA2B,KAAK,QAAQ,IAAI,CAAC,IAAI;AAAA,EAAA;AAE7E;AAEA,SAAS,yBAAyB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SAAO,2BAA2B,KAAK,EAAE,IAAI,CAAC,UAAU;AACtD,UAAM,aAAa,wBAAwB,KAAK;AAChD,UAAM,WAAW,QAAQ,MAAM,MAAM;AACrC,WACEA,2BAAAA;AAAAA,MAACY,KAAAA,KAAK;AAAA,MAAL;AAAA,QAEC,UAAU,MAAM;AAAA,QAEhB,aAAa,mBAAmB,OAAO,YAAY;AAAA,UACjD,aAAa;AAAA,UACb,QAAQ;AAAA,QAAA,CACT;AAAA,QACD,SAAS,MAAM,YAAY,MAAM,EAAE;AAAA,QAGnC,cAAY,MAAM;AAAA,QAClB,gBAAc,WAAW,SAAS;AAAA,QAClC,eAAa,YAAY;AAAA,QACzB,OAAO,WAAW,QAAQ;AAAA,QAC1B,OACE,WACI;AAAA,UACE,iBAAiBV,MAAAA,aAAa;AAAA,UAC9B,OAAOA,MAAAA,aAAa;AAAA,UACpB,YAAY;AAAA,QAAA,IAEd;AAAA,QAGL,UAAA,MAAM;AAAA,MAAA;AAAA,MAxBF,MAAM;AAAA,IAAA;AAAA,EA2BjB,CAAC;AACH;AAEA,SAAS,qBAAqB,EAAE,OAAO,MAAM,eAAoD;AAC/F,QAAM,YAAY,wBAAwB,IAAI;AAC9C,QAAM,cAAc,QAAQ,KAAK,UAAU,MAAM;AACjD,QAAM,WAAW,QAAQ,KAAK,UAAU,oBAAoB,IAAI,CAAC;AACjE,QAAM,cAAc,mBAAmB,MAAM,WAAW;AAAA,IACtD,aAAa;AAAA,IACb,QAAQ;AAAA,EAAA,CACT;AAKD,QAAM,OACJF,2BAAAA;AAAAA,IAACa,WAAAA;AAAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAQ;AAAA,MACR;AAAA,MACA,MAAM;AAAA,MACN,QAAO;AAAA,MACP,UAAU,KAAK;AAAA,MACf,cAAY;AAAA,MACZ,gBAAc,WAAW,SAAS;AAAA,MAClC,eAAa,YAAY;AAAA,MACzB,SAAS,cAAc,SAAY,MAAM,YAAY,KAAK,EAAE;AAAA,MAC5D,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW;AAAA,QACX,GAAI,WACA;AAAA,UACE,WAAWX,MAAAA,aAAa;AAAA,UACxB,cAAcA,MAAAA,aAAa;AAAA,UAC3B,cAAcA,MAAAA,aAAa;AAAA,UAC3B,oBAAoBA,MAAAA,aAAa;AAAA,UACjC,iBAAiBA,MAAAA,aAAa;AAAA,UAC9B,OAAOA,MAAAA,aAAa;AAAA,QAAA,IAEtB;AAAA,UACE,OAAOA,MAAAA,aAAa;AAAA,QAAA;AAAA,MACtB;AAAA,MAGL,UAAA;AAAA,IAAA;AAAA,EAAA;AAIL,QAAM,UAAU,cACdY,2BAAAA,KAACF,KAAAA,MAAA,EAAK,UAAS,eAAc,QAAQ,GAAG,cAAY,MAAC,QAAQ,2BAC3D,UAAA;AAAA,IAAAZ,2BAAAA;AAAAA,MAACO,QAAAA;AAAAA,MAAA;AAAA,QACC,OAAO;AAAA,QACP,UAAS;AAAA,QACT,WAAS;AAAA,QACT,cAAY;AAAA,QACZ,QAAQ;AAAA,QACR,QAAQ,EAAE,OAAO,MAAM,OAAO,MAAM,OAAO,KAAA;AAAA,QAE3C,UAAAP,2BAAAA,IAACY,KAAAA,KAAK,QAAL,EAAa,UAAA,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,IAErBZ,2BAAAA,IAACY,KAAAA,KAAK,UAAL,EACC,UAAAZ,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO,KAAK,YAAY,CAAA;AAAA,QACxB;AAAA,QACA;AAAA,MAAA;AAAA,IAAA,EACF,CACF;AAAA,EAAA,EAAA,CACF,IAEAA,2BAAAA;AAAAA,IAACO,QAAAA;AAAAA,IAAA;AAAA,MACC,OAAO;AAAA,MACP,UAAS;AAAA,MACT,WAAS;AAAA,MACT,cAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ,EAAE,OAAO,MAAM,OAAO,MAAM,OAAO,KAAA;AAAA,MAE1C,UAAA;AAAA,IAAA;AAAA,EAAA;AAKL,SAAOP,2BAAAA,IAACC,IAAAA,KAAA,EAAI,OAAO,EAAE,OAAO,QAAQ,SAAS,QAAQ,gBAAgB,SAAA,GAAa,UAAA,QAAA,CAAQ;AAC5F;AAEA,SAAS,YAAY,OAAyB;AAC5C,MAAI,MAAM,WAAW;AACnB,WAAOD,+BAAC,sBAAA,EAAsB,GAAG,MAAA,CAAO;AAAA,EAC1C;AACA,SAAOA,+BAAC,qBAAA,EAAqB,GAAG,MAAA,CAAO;AACzC;AAEO,SAAS,QAAQ;AAAA,EACtB,QAAQ,CAAA;AAAA,EACR;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA,cAAc;AAChB,GAAiB;AACf,QAAM,mBAAmB,YAAY,CAAC,EAAE,IAAI,QAAQ,OAAO;AAC3D,QAAM,CAAC,gBAAgB,iBAAiB,IAAIe,gCAAgB;AAAA,IAC1D,OAAO;AAAA,IACP,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,UAAU;AAAA,EAAA,CACX;AAED,QAAM,kBAAkB,QAAQ,UAAU,OAAO,OAAO;AACxD,QAAM,CAAC,eAAe,gBAAgB,IAAIN,MAAAA,SAAS,KAAK;AACxD,QAAM,8BAA8B;AACpC,QAAM,mBAAmB,QAAQ,MAAM,KAAK;AAE5C,QAAM,iBAAiB,cACrBT,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,MACX,SAAS,iBAAiB,OAAO;AAAA,MACjC,UAAU,MAAM,kBAAkB,CAAC,cAAc;AAAA,IAAA;AAAA,EAAA,IAEjD;AAEJ,SACEc,2BAAAA;AAAAA,IAACE,MAAAA;AAAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,KAAI;AAAA,MACJ,GAAE;AAAA,MACF,GAAG,iBAAiB,OAAO;AAAA,MAC3B,cAAY;AAAA,MACZ,kBAAgB,kBAAkB;AAAA,MAClC,OAAO;AAAA,QACL,aAAa,aAAa,cAAc;AAAA,QACxC,kBAAkB,aAAad,mBAAa,qBAAqB;AAAA,QACjE,WAAW;AAAA,MAAA;AAAA,MAGZ,UAAA;AAAA,QAAA,mBACC,iBACEY,2BAAAA,KAACE,aAAA,EAAM,KAAK,GAAG,OAAM,UAClB,UAAA;AAAA,UAAA,SACChB,2BAAAA;AAAAA,YAACC,IAAAA;AAAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,gBAAgB;AAAA,gBAChB,OAAO;AAAA,cAAA;AAAA,cAGR,UAAA;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,UACH;AAAA,QAAA,EAAA,CACH,IAEAa,2BAAAA;AAAAA,UAACG,MAAAA;AAAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,KAAI;AAAA,YACJ,OAAM;AAAA,YACN,OAAO,EAAE,WAAW,GAAA;AAAA,YACpB,cAAc,MAAM,iBAAiB,IAAI;AAAA,YACzC,cAAc,MAAM,iBAAiB,KAAK;AAAA,YAC1C,gBAAgB,MAAM,iBAAiB,IAAI;AAAA,YAC3C,eAAe,CAAC,UAAU;AACxB,kBAAI,CAAC,MAAM,cAAc,SAAS,MAAM,aAA4B,GAAG;AACrE,iCAAiB,KAAK;AAAA,cACxB;AAAA,YACF;AAAA,YAEC,UAAA;AAAA,cAAA,SACCjB,2BAAAA;AAAAA,gBAACC,IAAAA;AAAAA,gBAAA;AAAA,kBACC,OAAO;AAAA,oBACL,MAAM;AAAA,oBACN,UAAU;AAAA,oBACV,UAAU;AAAA,oBACV,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,gBAAgB;AAAA,kBAAA;AAAA,kBAGjB,UAAA;AAAA,gBAAA;AAAA,cAAA,IAED;AAAA,cACH;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,IAGH;AAAA,QAEJD,2BAAAA,IAACgB,MAAAA,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,OAAA,GACtD,UAAA,iBAAiB;AAAA,UAAQ,CAAC,YACzB,QAAQ,MAAM,IAAI,CAAC,SACjBhB,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW;AAAA,YAAA;AAAA,YAJN,GAAG,QAAQ,EAAE,IAAI,KAAK,EAAE;AAAA,UAAA,CAMhC;AAAA,QAAA,GAEL;AAAA,QAEC,kBACCA,2BAAAA,IAACgB,MAAAA,OAAA,EAAM,KAAI,MAAK,OAAO,EAAE,YAAY,EAAA,GAClC,UAAA,UACCF,2BAAAA,KAAAI,WAAAA,UAAA,EACG,UAAA;AAAA,UAAA,MACClB,2BAAAA;AAAAA,YAACC,IAAAA;AAAAA,YAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO;AAAA,gBACP,SAAS;AAAA,gBACT,gBAAgB,iBAAiB,WAAW;AAAA,cAAA;AAAA,cAG7C,UAAA;AAAA,YAAA;AAAA,UAAA,IAED;AAAA,UACH,OAAO,UAAUD,2BAAAA,IAACmB,QAAAA,WAAQ,OAAOjB,MAAAA,aAAa,oBAAoB,IAAK;AAAA,UACvE,yCAAWD,SAAA,EAAI,OAAO,EAAE,OAAO,UAAW,UAAA,QAAA,CAAQ,IAAS;AAAA,QAAA,EAAA,CAC9D,GAEJ,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;;;;;;"}
@@ -2,8 +2,7 @@ import { ReactNode } from 'react';
2
2
  /** Expanded product side-nav width (Brand System shell metric). */
3
3
  export declare const SIDE_NAV_WIDTH = 260;
4
4
  /**
5
- * Collapsed icon-rail width.
6
- * Proposed shell metric for Dylan / Brand System review — not yet in Brand System v3.4.
5
+ * Collapsed icon-rail width (Brand System v3.5+ shell metric).
7
6
  */
8
7
  export declare const SIDE_NAV_COLLAPSED_WIDTH = 80;
9
8
  export interface SideNavItem {
@@ -1 +1 @@
1
- {"version":3,"file":"SideNav.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAG5D,mEAAmE;AACnE,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAQ3C,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,yEAAyE;IACzE,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,qEAAqE;IACrE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yGAAyG;IACzG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,4GAA4G;IAC5G,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAMD,+EAA+E;AAC/E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,CAAC,GAAG,MAAM,CAW9F;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGlE;AAqUD,wBAAgB,OAAO,CAAC,EACtB,KAAU,EACV,QAAQ,EACR,WAAW,EACX,KAAgB,EAChB,SAA6B,EAC7B,UAAkB,EAClB,MAAM,EACN,GAAG,EACH,OAAO,EACP,MAAM,EACN,SAAS,EACT,gBAAwB,EACxB,iBAAiB,EACjB,WAAmB,GACpB,EAAE,YAAY,+BA6Hd"}
1
+ {"version":3,"file":"SideNav.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAG5D,mEAAmE;AACnE,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC;;GAEG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAQ3C,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,yEAAyE;IACzE,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,8GAA8G;IAC9G,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,qEAAqE;IACrE,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yGAAyG;IACzG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,4GAA4G;IAC5G,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAMD,+EAA+E;AAC/E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,CAAC,GAAG,MAAM,CAW9F;AAED,8EAA8E;AAC9E,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGlE;AAqUD,wBAAgB,OAAO,CAAC,EACtB,KAAU,EACV,QAAQ,EACR,WAAW,EACX,KAAgB,EAChB,SAA6B,EAC7B,UAAkB,EAClB,MAAM,EACN,GAAG,EACH,OAAO,EACP,MAAM,EACN,SAAS,EACT,gBAAwB,EACxB,iBAAiB,EACjB,WAAmB,GACpB,EAAE,YAAY,+BA6Hd"}
@@ -1 +1 @@
1
- {"version":3,"file":"SideNav.js","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"sourcesContent":["import {\n ActionIcon,\n Box,\n Divider,\n Group,\n Menu,\n NavLink,\n type NavLinkProps,\n Stack,\n Tooltip,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { useUncontrolled } from \"@mantine/hooks\";\nimport { IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand } from \"@tabler/icons-react\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { fairmintVars, radii, spacing } from \"../../../theme\";\n\n/** Expanded product side-nav width (Brand System shell metric). */\nexport const SIDE_NAV_WIDTH = 260;\n\n/**\n * Collapsed icon-rail width.\n * Proposed shell metric for Dylan / Brand System review — not yet in Brand System v3.4.\n */\nexport const SIDE_NAV_COLLAPSED_WIDTH = 80;\n\n/**\n * Floating chrome (tooltips, nested flyouts) must clear Studio/Investor fixed\n * shell layers — side nav ≈1200, header ≈1201, menus ≥1300.\n */\nconst SIDE_NAV_FLOATING_Z_INDEX = 1300;\n\nexport interface SideNavItem {\n /** Unique identifier for this nav item (e.g., route path or slug). */\n id: string;\n /** Display label. */\n label: ReactNode;\n /**\n * Accessible name when `label` is not a plain string.\n * Also used for collapsed tooltips and letter-fallback derivation.\n */\n ariaLabel?: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Optional content rendered at the end of the item, such as a badge. */\n rightSection?: ReactNode;\n /** Whether this item is currently active. */\n active?: boolean;\n /** Whether the item is unavailable. */\n disabled?: boolean;\n /** Nested navigation items. */\n children?: SideNavItem[];\n /** Controlled expanded state for items with children. */\n open?: boolean;\n}\n\nexport interface SideNavSection {\n /** Unique identifier for the section. */\n id: string;\n /** Navigation items in this section. */\n items: SideNavItem[];\n}\n\nexport interface SideNavProps {\n /** Navigation items to render when section headings are not needed. */\n items?: SideNavItem[];\n /** Grouped navigation items. Sections are data-only — Fairmint product nav does not render section titles. */\n sections?: SideNavSection[];\n /** Callback when a nav item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n /** Active color. @default colors.primary */\n color?: string;\n /** Accessible label for the navigation landmark. @default \"Main navigation\" */\n ariaLabel?: string;\n /** Render a light right border when the parent shell does not already own the divider. @default false */\n withBorder?: boolean;\n /**\n * Logo or other chrome above the nav list.\n * Consumers own expanded wordmark vs collapsed mark switching.\n */\n header?: ReactNode;\n /**\n * Primary nav CTA pinned above the profile (Investor \"Add Investment\", Studio \"New\").\n * Prefer this over stuffing the CTA into `items`.\n */\n cta?: ReactNode;\n /**\n * Account / profile control pinned to the bottom of the rail.\n * Product shells keep profile here — not in the scrollable destination list or AppHeader.\n */\n profile?: ReactNode;\n /**\n * Custom bottom chrome. When set, replaces the standard `cta` + divider + `profile` composition.\n */\n footer?: ReactNode;\n /** Controlled collapsed (icon-rail) state. */\n collapsed?: boolean;\n /** Uncontrolled initial collapsed state. @default false */\n defaultCollapsed?: boolean;\n /** Called when the user toggles collapse. */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** When true, render a collapse/expand control beside the logo (visible on header hover). @default false */\n collapsible?: boolean;\n}\n\nfunction hasActiveDescendant(item: SideNavItem): boolean {\n return item.children?.some((child) => child.active || hasActiveDescendant(child)) ?? false;\n}\n\n/** Resolve a plain-text name for tooltips, aria-label, and letter fallback. */\nexport function getSideNavItemLabelText(item: Pick<SideNavItem, \"label\" | \"ariaLabel\">): string {\n if (item.ariaLabel) {\n return item.ariaLabel;\n }\n if (typeof item.label === \"string\") {\n return item.label;\n }\n if (typeof item.label === \"number\") {\n return String(item.label);\n }\n return \"Item\";\n}\n\n/** First letter/number monogram for icon-less items in the collapsed rail. */\nexport function getSideNavLetterFallback(labelText: string): string {\n const match = labelText.match(/[\\p{L}\\p{N}]/u);\n return match ? match[0].toUpperCase() : \"?\";\n}\n\nfunction LetterFallback({ letter, active = false }: { letter: string; active?: boolean }) {\n return (\n <Box\n component=\"span\"\n aria-hidden\n data-active={active || undefined}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 20,\n height: 20,\n flexShrink: 0,\n fontSize: 12,\n fontWeight: active ? 700 : 600,\n lineHeight: 1,\n // Selected chrome lives on the parent control — glyph matches icon sizing.\n color: active ? fairmintVars.colorIconOnSurfaceSelected : \"inherit\",\n }}\n >\n {letter}\n </Box>\n );\n}\n\nfunction CollapseToggle({\n collapsed,\n onToggle,\n visible,\n}: {\n collapsed: boolean;\n onToggle: () => void;\n /** When false, hide visually but keep focusable for keyboard users via opacity/focus styles. */\n visible: boolean;\n}) {\n const label = collapsed ? \"Expand navigation\" : \"Collapse navigation\";\n const Icon = collapsed ? IconLayoutSidebarLeftExpand : IconLayoutSidebarLeftCollapse;\n\n const button = (\n <UnstyledButton\n data-sidenav-collapse\n aria-label={label}\n aria-expanded={!collapsed}\n onClick={onToggle}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 32,\n flexShrink: 0,\n borderRadius: radii.md,\n color: fairmintVars.colorIconTertiary,\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? \"auto\" : \"none\",\n transition: \"opacity 120ms ease\",\n // Keep a layout slot when expanded so the wordmark does not shift on hover.\n // Collapsed: always a fixed control below the logo.\n width: 32,\n overflow: \"hidden\",\n padding: 0,\n }}\n >\n <Icon size={20} stroke={1.5} aria-hidden />\n </UnstyledButton>\n );\n\n if (!collapsed) {\n return button;\n }\n\n return (\n <Tooltip\n label={label}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n disabled={!visible}\n >\n {button}\n </Tooltip>\n );\n}\n\nfunction resolveLeftSection(\n item: SideNavItem,\n labelText: string,\n { requireIcon, active }: { requireIcon: boolean; active?: boolean },\n): ReactNode {\n if (item.icon) {\n return item.icon;\n }\n if (requireIcon) {\n return <LetterFallback letter={getSideNavLetterFallback(labelText)} active={Boolean(active)} />;\n }\n return undefined;\n}\n\n/** Collapsed rail control size — matches square CTA chrome. */\nconst COLLAPSED_ITEM_SIZE = 36;\n\n/**\n * Nested leaf indent so label text lines up with parent labels.\n * Parent rows use a 20px icon + `spacing.sm` section gap before the label.\n */\nconst NESTED_NAV_CHILDREN_OFFSET = `calc(20px + ${spacing.sm})`;\n\nconst navLinkStyles = (active: boolean | undefined): NavLinkProps[\"styles\"] => ({\n root: {\n color: active ? fairmintVars.colorTextPrimary : fairmintVars.colorTextSecondary,\n fontWeight: active ? 500 : 400,\n borderRadius: radii.md,\n // Prefer Fairmint selected surface over Mantine defaults for active chrome.\n ...(active\n ? {\n \"--nl-bg\": fairmintVars.colorSurfaceSelected,\n \"--nl-hover\": fairmintVars.colorSurfaceSelected,\n \"--nl-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n }\n : {}),\n },\n section: {\n color: active ? fairmintVars.colorIconOnSurfaceSelected : fairmintVars.colorIconTertiary,\n },\n});\n\ninterface SideNavNodeProps {\n color: string;\n item: SideNavItem;\n onItemClick: (id: string) => void;\n collapsed: boolean;\n}\n\nfunction ExpandedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const containsActiveItem = hasActiveDescendant(item);\n const [opened, setOpened] = useState(item.open ?? containsActiveItem);\n const labelText = getSideNavItemLabelText(item);\n\n useEffect(() => {\n if (item.open !== undefined) {\n setOpened(item.open);\n } else if (containsActiveItem) {\n setOpened(true);\n }\n }, [containsActiveItem, item.open]);\n\n const hasChildren = Boolean(item.children?.length);\n\n return (\n <NavLink\n component=\"button\"\n type=\"button\"\n label={item.label}\n leftSection={resolveLeftSection(item, labelText, {\n requireIcon: false,\n active: item.active,\n })}\n rightSection={item.rightSection}\n active={item.active}\n disabled={item.disabled}\n color={color}\n variant=\"light\"\n childrenOffset={NESTED_NAV_CHILDREN_OFFSET}\n opened={hasChildren ? opened : undefined}\n aria-label={item.ariaLabel}\n onClick={\n hasChildren\n ? () => setOpened((currentOpened) => !currentOpened)\n : () => onItemClick(item.id)\n }\n styles={navLinkStyles(item.active)}\n >\n {item.children?.map((child) => (\n <ExpandedSideNavNode key={child.id} item={child} color={color} onItemClick={onItemClick} />\n ))}\n </NavLink>\n );\n}\n\n/** Flatten nested groups to leaves for the collapsed flyout (one actionable list). */\nfunction collectCollapsedMenuLeaves(items: SideNavItem[]): SideNavItem[] {\n return items.flatMap((item) =>\n item.children?.length ? collectCollapsedMenuLeaves(item.children) : [item],\n );\n}\n\nfunction CollapsedNestedMenuItems({\n items,\n onItemClick,\n color,\n}: {\n items: SideNavItem[];\n onItemClick: (id: string) => void;\n color: string;\n}) {\n return collectCollapsedMenuLeaves(items).map((child) => {\n const childLabel = getSideNavItemLabelText(child);\n const isActive = Boolean(child.active);\n return (\n <Menu.Item\n key={child.id}\n disabled={child.disabled}\n // Flyout rows already show the full label — only keep a real icon, not a letter monogram.\n leftSection={resolveLeftSection(child, childLabel, {\n requireIcon: false,\n active: isActive,\n })}\n onClick={() => onItemClick(child.id)}\n // Only apply an explicit override — never stamp the generic \"Item\" fallback\n // over a React-node label's naturally derived accessible name.\n aria-label={child.ariaLabel}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n color={isActive ? color : undefined}\n style={\n isActive\n ? {\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n fontWeight: 600,\n }\n : undefined\n }\n >\n {child.label}\n </Menu.Item>\n );\n });\n}\n\nfunction CollapsedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const labelText = getSideNavItemLabelText(item);\n const hasChildren = Boolean(item.children?.length);\n const isActive = Boolean(item.active || hasActiveDescendant(item));\n const leftSection = resolveLeftSection(item, labelText, {\n requireIcon: true,\n active: isActive,\n });\n\n // ActionIcon (not NavLink): NavLink.css forces `width: 100%` and asymmetric\n // horizontal padding, which makes selected/hover chrome a wide pill.\n // Selected fill uses Fairmint surface/selected — Mantine `light` is too dim in dark mode.\n const link = (\n <ActionIcon\n type=\"button\"\n variant=\"subtle\"\n color={color}\n size={COLLAPSED_ITEM_SIZE}\n radius=\"md\"\n disabled={item.disabled}\n aria-label={labelText}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n onClick={hasChildren ? undefined : () => onItemClick(item.id)}\n style={{\n width: COLLAPSED_ITEM_SIZE,\n height: COLLAPSED_ITEM_SIZE,\n minWidth: COLLAPSED_ITEM_SIZE,\n minHeight: COLLAPSED_ITEM_SIZE,\n ...(isActive\n ? {\n \"--ai-bg\": fairmintVars.colorSurfaceSelected,\n \"--ai-hover\": fairmintVars.colorSurfaceSelected,\n \"--ai-color\": fairmintVars.colorIconOnSurfaceSelected,\n \"--ai-hover-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n }\n : {\n color: fairmintVars.colorIconTertiary,\n }),\n }}\n >\n {leftSection}\n </ActionIcon>\n );\n\n const control = hasChildren ? (\n <Menu position=\"right-start\" offset={8} withinPortal zIndex={SIDE_NAV_FLOATING_Z_INDEX}>\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n <Menu.Target>{link}</Menu.Target>\n </Tooltip>\n <Menu.Dropdown>\n <CollapsedNestedMenuItems\n items={item.children ?? []}\n onItemClick={onItemClick}\n color={color}\n />\n </Menu.Dropdown>\n </Menu>\n ) : (\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n {link}\n </Tooltip>\n );\n\n // Uniform Stack child so Menu vs Tooltip wrappers cannot skew item gaps.\n return <Box style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>{control}</Box>;\n}\n\nfunction SideNavNode(props: SideNavNodeProps) {\n if (props.collapsed) {\n return <CollapsedSideNavNode {...props} />;\n }\n return <ExpandedSideNavNode {...props} />;\n}\n\nexport function SideNav({\n items = [],\n sections,\n onItemClick,\n color = \"indigo\",\n ariaLabel = \"Main navigation\",\n withBorder = false,\n header,\n cta,\n profile,\n footer,\n collapsed,\n defaultCollapsed = false,\n onCollapsedChange,\n collapsible = false,\n}: SideNavProps) {\n const resolvedSections = sections ?? [{ id: \"main\", items }];\n const [collapsedState, setCollapsedState] = useUncontrolled({\n value: collapsed,\n defaultValue: defaultCollapsed,\n finalValue: false,\n onChange: onCollapsedChange,\n });\n\n const hasBottomChrome = Boolean(footer || cta || profile);\n const [headerHovered, setHeaderHovered] = useState(false);\n const showExpandedCollapseControl = headerHovered;\n const showHeaderChrome = Boolean(header) || collapsible;\n\n const collapseToggle = collapsible ? (\n <CollapseToggle\n collapsed={collapsedState}\n visible={collapsedState ? true : showExpandedCollapseControl}\n onToggle={() => setCollapsedState(!collapsedState)}\n />\n ) : null;\n\n return (\n <Stack\n component=\"nav\"\n gap=\"md\"\n h=\"100%\"\n p={collapsedState ? \"sm\" : \"md\"}\n aria-label={ariaLabel}\n data-collapsed={collapsedState || undefined}\n style={{\n borderRight: withBorder ? \"1px solid\" : undefined,\n borderRightColor: withBorder ? fairmintVars.colorBorderDefault : undefined,\n boxShadow: \"none\",\n }}\n >\n {showHeaderChrome ? (\n collapsedState ? (\n <Stack gap={6} align=\"center\">\n {header ? (\n <Box\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Stack>\n ) : (\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"xs\"\n align=\"center\"\n style={{ minHeight: 32 }}\n onMouseEnter={() => setHeaderHovered(true)}\n onMouseLeave={() => setHeaderHovered(false)}\n onFocusCapture={() => setHeaderHovered(true)}\n onBlurCapture={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n setHeaderHovered(false);\n }\n }}\n >\n {header ? (\n <Box\n style={{\n flex: 1,\n minWidth: 0,\n overflow: \"hidden\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-start\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Group>\n )\n ) : null}\n\n <Stack gap={4} style={{ flex: 1, minHeight: 0, overflow: \"auto\" }}>\n {resolvedSections.flatMap((section) =>\n section.items.map((item) => (\n <SideNavNode\n key={`${section.id}:${item.id}`}\n item={item}\n color={color}\n onItemClick={onItemClick}\n collapsed={collapsedState}\n />\n )),\n )}\n </Stack>\n\n {hasBottomChrome ? (\n <Stack gap=\"sm\" style={{ flexShrink: 0 }}>\n {footer ?? (\n <>\n {cta ? (\n <Box\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: collapsedState ? \"center\" : \"stretch\",\n }}\n >\n {cta}\n </Box>\n ) : null}\n {cta && profile ? <Divider color={fairmintVars.colorBorderDefault} /> : null}\n {profile ? <Box style={{ width: \"100%\" }}>{profile}</Box> : null}\n </>\n )}\n </Stack>\n ) : null}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SideNav.js","sources":["../../../../src/components/layout/SideNav/SideNav.tsx"],"sourcesContent":["import {\n ActionIcon,\n Box,\n Divider,\n Group,\n Menu,\n NavLink,\n type NavLinkProps,\n Stack,\n Tooltip,\n UnstyledButton,\n} from \"@mantine/core\";\nimport { useUncontrolled } from \"@mantine/hooks\";\nimport { IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand } from \"@tabler/icons-react\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { fairmintVars, radii, spacing } from \"../../../theme\";\n\n/** Expanded product side-nav width (Brand System shell metric). */\nexport const SIDE_NAV_WIDTH = 260;\n\n/**\n * Collapsed icon-rail width (Brand System v3.5+ shell metric).\n */\nexport const SIDE_NAV_COLLAPSED_WIDTH = 80;\n\n/**\n * Floating chrome (tooltips, nested flyouts) must clear Studio/Investor fixed\n * shell layers — side nav ≈1200, header ≈1201, menus ≥1300.\n */\nconst SIDE_NAV_FLOATING_Z_INDEX = 1300;\n\nexport interface SideNavItem {\n /** Unique identifier for this nav item (e.g., route path or slug). */\n id: string;\n /** Display label. */\n label: ReactNode;\n /**\n * Accessible name when `label` is not a plain string.\n * Also used for collapsed tooltips and letter-fallback derivation.\n */\n ariaLabel?: string;\n /** Icon element. */\n icon?: ReactNode;\n /** Optional content rendered at the end of the item, such as a badge. */\n rightSection?: ReactNode;\n /** Whether this item is currently active. */\n active?: boolean;\n /** Whether the item is unavailable. */\n disabled?: boolean;\n /** Nested navigation items. */\n children?: SideNavItem[];\n /** Controlled expanded state for items with children. */\n open?: boolean;\n}\n\nexport interface SideNavSection {\n /** Unique identifier for the section. */\n id: string;\n /** Navigation items in this section. */\n items: SideNavItem[];\n}\n\nexport interface SideNavProps {\n /** Navigation items to render when section headings are not needed. */\n items?: SideNavItem[];\n /** Grouped navigation items. Sections are data-only — Fairmint product nav does not render section titles. */\n sections?: SideNavSection[];\n /** Callback when a nav item is clicked. Receives the item's `id`. */\n onItemClick: (id: string) => void;\n /** Active color. @default colors.primary */\n color?: string;\n /** Accessible label for the navigation landmark. @default \"Main navigation\" */\n ariaLabel?: string;\n /** Render a light right border when the parent shell does not already own the divider. @default false */\n withBorder?: boolean;\n /**\n * Logo or other chrome above the nav list.\n * Consumers own expanded wordmark vs collapsed mark switching.\n */\n header?: ReactNode;\n /**\n * Primary nav CTA pinned above the profile (Investor \"Add Investment\", Studio \"New\").\n * Prefer this over stuffing the CTA into `items`.\n */\n cta?: ReactNode;\n /**\n * Account / profile control pinned to the bottom of the rail.\n * Product shells keep profile here — not in the scrollable destination list or AppHeader.\n */\n profile?: ReactNode;\n /**\n * Custom bottom chrome. When set, replaces the standard `cta` + divider + `profile` composition.\n */\n footer?: ReactNode;\n /** Controlled collapsed (icon-rail) state. */\n collapsed?: boolean;\n /** Uncontrolled initial collapsed state. @default false */\n defaultCollapsed?: boolean;\n /** Called when the user toggles collapse. */\n onCollapsedChange?: (collapsed: boolean) => void;\n /** When true, render a collapse/expand control beside the logo (visible on header hover). @default false */\n collapsible?: boolean;\n}\n\nfunction hasActiveDescendant(item: SideNavItem): boolean {\n return item.children?.some((child) => child.active || hasActiveDescendant(child)) ?? false;\n}\n\n/** Resolve a plain-text name for tooltips, aria-label, and letter fallback. */\nexport function getSideNavItemLabelText(item: Pick<SideNavItem, \"label\" | \"ariaLabel\">): string {\n if (item.ariaLabel) {\n return item.ariaLabel;\n }\n if (typeof item.label === \"string\") {\n return item.label;\n }\n if (typeof item.label === \"number\") {\n return String(item.label);\n }\n return \"Item\";\n}\n\n/** First letter/number monogram for icon-less items in the collapsed rail. */\nexport function getSideNavLetterFallback(labelText: string): string {\n const match = labelText.match(/[\\p{L}\\p{N}]/u);\n return match ? match[0].toUpperCase() : \"?\";\n}\n\nfunction LetterFallback({ letter, active = false }: { letter: string; active?: boolean }) {\n return (\n <Box\n component=\"span\"\n aria-hidden\n data-active={active || undefined}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 20,\n height: 20,\n flexShrink: 0,\n fontSize: 12,\n fontWeight: active ? 700 : 600,\n lineHeight: 1,\n // Selected chrome lives on the parent control — glyph matches icon sizing.\n color: active ? fairmintVars.colorIconOnSurfaceSelected : \"inherit\",\n }}\n >\n {letter}\n </Box>\n );\n}\n\nfunction CollapseToggle({\n collapsed,\n onToggle,\n visible,\n}: {\n collapsed: boolean;\n onToggle: () => void;\n /** When false, hide visually but keep focusable for keyboard users via opacity/focus styles. */\n visible: boolean;\n}) {\n const label = collapsed ? \"Expand navigation\" : \"Collapse navigation\";\n const Icon = collapsed ? IconLayoutSidebarLeftExpand : IconLayoutSidebarLeftCollapse;\n\n const button = (\n <UnstyledButton\n data-sidenav-collapse\n aria-label={label}\n aria-expanded={!collapsed}\n onClick={onToggle}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 32,\n flexShrink: 0,\n borderRadius: radii.md,\n color: fairmintVars.colorIconTertiary,\n opacity: visible ? 1 : 0,\n pointerEvents: visible ? \"auto\" : \"none\",\n transition: \"opacity 120ms ease\",\n // Keep a layout slot when expanded so the wordmark does not shift on hover.\n // Collapsed: always a fixed control below the logo.\n width: 32,\n overflow: \"hidden\",\n padding: 0,\n }}\n >\n <Icon size={20} stroke={1.5} aria-hidden />\n </UnstyledButton>\n );\n\n if (!collapsed) {\n return button;\n }\n\n return (\n <Tooltip\n label={label}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n disabled={!visible}\n >\n {button}\n </Tooltip>\n );\n}\n\nfunction resolveLeftSection(\n item: SideNavItem,\n labelText: string,\n { requireIcon, active }: { requireIcon: boolean; active?: boolean },\n): ReactNode {\n if (item.icon) {\n return item.icon;\n }\n if (requireIcon) {\n return <LetterFallback letter={getSideNavLetterFallback(labelText)} active={Boolean(active)} />;\n }\n return undefined;\n}\n\n/** Collapsed rail control size — matches square CTA chrome. */\nconst COLLAPSED_ITEM_SIZE = 36;\n\n/**\n * Nested leaf indent so label text lines up with parent labels.\n * Parent rows use a 20px icon + `spacing.sm` section gap before the label.\n */\nconst NESTED_NAV_CHILDREN_OFFSET = `calc(20px + ${spacing.sm})`;\n\nconst navLinkStyles = (active: boolean | undefined): NavLinkProps[\"styles\"] => ({\n root: {\n color: active ? fairmintVars.colorTextPrimary : fairmintVars.colorTextSecondary,\n fontWeight: active ? 500 : 400,\n borderRadius: radii.md,\n // Prefer Fairmint selected surface over Mantine defaults for active chrome.\n ...(active\n ? {\n \"--nl-bg\": fairmintVars.colorSurfaceSelected,\n \"--nl-hover\": fairmintVars.colorSurfaceSelected,\n \"--nl-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n }\n : {}),\n },\n section: {\n color: active ? fairmintVars.colorIconOnSurfaceSelected : fairmintVars.colorIconTertiary,\n },\n});\n\ninterface SideNavNodeProps {\n color: string;\n item: SideNavItem;\n onItemClick: (id: string) => void;\n collapsed: boolean;\n}\n\nfunction ExpandedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const containsActiveItem = hasActiveDescendant(item);\n const [opened, setOpened] = useState(item.open ?? containsActiveItem);\n const labelText = getSideNavItemLabelText(item);\n\n useEffect(() => {\n if (item.open !== undefined) {\n setOpened(item.open);\n } else if (containsActiveItem) {\n setOpened(true);\n }\n }, [containsActiveItem, item.open]);\n\n const hasChildren = Boolean(item.children?.length);\n\n return (\n <NavLink\n component=\"button\"\n type=\"button\"\n label={item.label}\n leftSection={resolveLeftSection(item, labelText, {\n requireIcon: false,\n active: item.active,\n })}\n rightSection={item.rightSection}\n active={item.active}\n disabled={item.disabled}\n color={color}\n variant=\"light\"\n childrenOffset={NESTED_NAV_CHILDREN_OFFSET}\n opened={hasChildren ? opened : undefined}\n aria-label={item.ariaLabel}\n onClick={\n hasChildren\n ? () => setOpened((currentOpened) => !currentOpened)\n : () => onItemClick(item.id)\n }\n styles={navLinkStyles(item.active)}\n >\n {item.children?.map((child) => (\n <ExpandedSideNavNode key={child.id} item={child} color={color} onItemClick={onItemClick} />\n ))}\n </NavLink>\n );\n}\n\n/** Flatten nested groups to leaves for the collapsed flyout (one actionable list). */\nfunction collectCollapsedMenuLeaves(items: SideNavItem[]): SideNavItem[] {\n return items.flatMap((item) =>\n item.children?.length ? collectCollapsedMenuLeaves(item.children) : [item],\n );\n}\n\nfunction CollapsedNestedMenuItems({\n items,\n onItemClick,\n color,\n}: {\n items: SideNavItem[];\n onItemClick: (id: string) => void;\n color: string;\n}) {\n return collectCollapsedMenuLeaves(items).map((child) => {\n const childLabel = getSideNavItemLabelText(child);\n const isActive = Boolean(child.active);\n return (\n <Menu.Item\n key={child.id}\n disabled={child.disabled}\n // Flyout rows already show the full label — only keep a real icon, not a letter monogram.\n leftSection={resolveLeftSection(child, childLabel, {\n requireIcon: false,\n active: isActive,\n })}\n onClick={() => onItemClick(child.id)}\n // Only apply an explicit override — never stamp the generic \"Item\" fallback\n // over a React-node label's naturally derived accessible name.\n aria-label={child.ariaLabel}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n color={isActive ? color : undefined}\n style={\n isActive\n ? {\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n fontWeight: 600,\n }\n : undefined\n }\n >\n {child.label}\n </Menu.Item>\n );\n });\n}\n\nfunction CollapsedSideNavNode({ color, item, onItemClick }: Omit<SideNavNodeProps, \"collapsed\">) {\n const labelText = getSideNavItemLabelText(item);\n const hasChildren = Boolean(item.children?.length);\n const isActive = Boolean(item.active || hasActiveDescendant(item));\n const leftSection = resolveLeftSection(item, labelText, {\n requireIcon: true,\n active: isActive,\n });\n\n // ActionIcon (not NavLink): NavLink.css forces `width: 100%` and asymmetric\n // horizontal padding, which makes selected/hover chrome a wide pill.\n // Selected fill uses Fairmint surface/selected — Mantine `light` is too dim in dark mode.\n const link = (\n <ActionIcon\n type=\"button\"\n variant=\"subtle\"\n color={color}\n size={COLLAPSED_ITEM_SIZE}\n radius=\"md\"\n disabled={item.disabled}\n aria-label={labelText}\n aria-current={isActive ? \"page\" : undefined}\n data-active={isActive || undefined}\n onClick={hasChildren ? undefined : () => onItemClick(item.id)}\n style={{\n width: COLLAPSED_ITEM_SIZE,\n height: COLLAPSED_ITEM_SIZE,\n minWidth: COLLAPSED_ITEM_SIZE,\n minHeight: COLLAPSED_ITEM_SIZE,\n ...(isActive\n ? {\n \"--ai-bg\": fairmintVars.colorSurfaceSelected,\n \"--ai-hover\": fairmintVars.colorSurfaceSelected,\n \"--ai-color\": fairmintVars.colorIconOnSurfaceSelected,\n \"--ai-hover-color\": fairmintVars.colorIconOnSurfaceSelected,\n backgroundColor: fairmintVars.colorSurfaceSelected,\n color: fairmintVars.colorIconOnSurfaceSelected,\n }\n : {\n color: fairmintVars.colorIconTertiary,\n }),\n }}\n >\n {leftSection}\n </ActionIcon>\n );\n\n const control = hasChildren ? (\n <Menu position=\"right-start\" offset={8} withinPortal zIndex={SIDE_NAV_FLOATING_Z_INDEX}>\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n <Menu.Target>{link}</Menu.Target>\n </Tooltip>\n <Menu.Dropdown>\n <CollapsedNestedMenuItems\n items={item.children ?? []}\n onItemClick={onItemClick}\n color={color}\n />\n </Menu.Dropdown>\n </Menu>\n ) : (\n <Tooltip\n label={labelText}\n position=\"right\"\n withArrow\n withinPortal\n zIndex={SIDE_NAV_FLOATING_Z_INDEX}\n events={{ hover: true, focus: true, touch: true }}\n >\n {link}\n </Tooltip>\n );\n\n // Uniform Stack child so Menu vs Tooltip wrappers cannot skew item gaps.\n return <Box style={{ width: \"100%\", display: \"flex\", justifyContent: \"center\" }}>{control}</Box>;\n}\n\nfunction SideNavNode(props: SideNavNodeProps) {\n if (props.collapsed) {\n return <CollapsedSideNavNode {...props} />;\n }\n return <ExpandedSideNavNode {...props} />;\n}\n\nexport function SideNav({\n items = [],\n sections,\n onItemClick,\n color = \"indigo\",\n ariaLabel = \"Main navigation\",\n withBorder = false,\n header,\n cta,\n profile,\n footer,\n collapsed,\n defaultCollapsed = false,\n onCollapsedChange,\n collapsible = false,\n}: SideNavProps) {\n const resolvedSections = sections ?? [{ id: \"main\", items }];\n const [collapsedState, setCollapsedState] = useUncontrolled({\n value: collapsed,\n defaultValue: defaultCollapsed,\n finalValue: false,\n onChange: onCollapsedChange,\n });\n\n const hasBottomChrome = Boolean(footer || cta || profile);\n const [headerHovered, setHeaderHovered] = useState(false);\n const showExpandedCollapseControl = headerHovered;\n const showHeaderChrome = Boolean(header) || collapsible;\n\n const collapseToggle = collapsible ? (\n <CollapseToggle\n collapsed={collapsedState}\n visible={collapsedState ? true : showExpandedCollapseControl}\n onToggle={() => setCollapsedState(!collapsedState)}\n />\n ) : null;\n\n return (\n <Stack\n component=\"nav\"\n gap=\"md\"\n h=\"100%\"\n p={collapsedState ? \"sm\" : \"md\"}\n aria-label={ariaLabel}\n data-collapsed={collapsedState || undefined}\n style={{\n borderRight: withBorder ? \"1px solid\" : undefined,\n borderRightColor: withBorder ? fairmintVars.colorBorderDefault : undefined,\n boxShadow: \"none\",\n }}\n >\n {showHeaderChrome ? (\n collapsedState ? (\n <Stack gap={6} align=\"center\">\n {header ? (\n <Box\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"100%\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Stack>\n ) : (\n <Group\n justify=\"space-between\"\n wrap=\"nowrap\"\n gap=\"xs\"\n align=\"center\"\n style={{ minHeight: 32 }}\n onMouseEnter={() => setHeaderHovered(true)}\n onMouseLeave={() => setHeaderHovered(false)}\n onFocusCapture={() => setHeaderHovered(true)}\n onBlurCapture={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) {\n setHeaderHovered(false);\n }\n }}\n >\n {header ? (\n <Box\n style={{\n flex: 1,\n minWidth: 0,\n overflow: \"hidden\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-start\",\n }}\n >\n {header}\n </Box>\n ) : null}\n {collapseToggle}\n </Group>\n )\n ) : null}\n\n <Stack gap={4} style={{ flex: 1, minHeight: 0, overflow: \"auto\" }}>\n {resolvedSections.flatMap((section) =>\n section.items.map((item) => (\n <SideNavNode\n key={`${section.id}:${item.id}`}\n item={item}\n color={color}\n onItemClick={onItemClick}\n collapsed={collapsedState}\n />\n )),\n )}\n </Stack>\n\n {hasBottomChrome ? (\n <Stack gap=\"sm\" style={{ flexShrink: 0 }}>\n {footer ?? (\n <>\n {cta ? (\n <Box\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: collapsedState ? \"center\" : \"stretch\",\n }}\n >\n {cta}\n </Box>\n ) : null}\n {cta && profile ? <Divider color={fairmintVars.colorBorderDefault} /> : null}\n {profile ? <Box style={{ width: \"100%\" }}>{profile}</Box> : null}\n </>\n )}\n </Stack>\n ) : null}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairmint/ui",
3
- "version": "0.3.35",
3
+ "version": "0.3.37",
4
4
  "type": "module",
5
5
  "description": "Fairmint design system and UI component library",
6
6
  "license": "UNLICENSED",