@fairmint/ui 0.4.11 → 0.4.12

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.
@@ -6,8 +6,8 @@ const colors = require("../../../theme/colors.cjs");
6
6
  const format = require("../../../utils/format.cjs");
7
7
  const layout = require("../../primitives/layout.cjs");
8
8
  const ThemeIcon = require("../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.cjs");
9
- const Group = require("../../../node_modules/@mantine/core/esm/components/Group/Group.cjs");
10
9
  const Text = require("../../primitives/Text/Text.cjs");
10
+ const Group = require("../../../node_modules/@mantine/core/esm/components/Group/Group.cjs");
11
11
  const UnstyledButton = require("../../../node_modules/@mantine/core/esm/components/UnstyledButton/UnstyledButton.cjs");
12
12
  const DefaultDocumentIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
13
13
  "svg",
@@ -45,6 +45,54 @@ const DefaultChevronIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
45
45
  children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" })
46
46
  }
47
47
  );
48
+ const NATIVE_CONTROL_SELECTOR = "a, button, input, select, textarea, label, summary, [contenteditable]:not([contenteditable='false'])";
49
+ const INTERACTIVE_ARIA_ROLES = /* @__PURE__ */ new Set([
50
+ "button",
51
+ "checkbox",
52
+ "combobox",
53
+ "gridcell",
54
+ "link",
55
+ "listbox",
56
+ "menu",
57
+ "menuitem",
58
+ "menuitemcheckbox",
59
+ "menuitemradio",
60
+ "option",
61
+ "radio",
62
+ "scrollbar",
63
+ "searchbox",
64
+ "slider",
65
+ "spinbutton",
66
+ "switch",
67
+ "tab",
68
+ "textbox",
69
+ "treeitem"
70
+ ]);
71
+ function clickLandedOnControl(target, root) {
72
+ if (!(target instanceof Element) || !(root instanceof Element)) {
73
+ return false;
74
+ }
75
+ const native = target.closest(NATIVE_CONTROL_SELECTOR);
76
+ if (native !== null && root.contains(native)) {
77
+ return true;
78
+ }
79
+ let node = target;
80
+ while (node !== null && node !== root && root.contains(node)) {
81
+ const role = node.getAttribute("role");
82
+ if (role !== null) {
83
+ for (const token of role.split(/\s+/)) {
84
+ if (INTERACTIVE_ARIA_ROLES.has(token)) {
85
+ return true;
86
+ }
87
+ }
88
+ }
89
+ node = node.parentElement;
90
+ }
91
+ return false;
92
+ }
93
+ function hasTrailingContent(node) {
94
+ return node != null && typeof node !== "boolean";
95
+ }
48
96
  function DocumentRow({
49
97
  name,
50
98
  caption,
@@ -74,15 +122,12 @@ function DocumentRow({
74
122
  children: /* @__PURE__ */ jsxRuntime.jsx(DefaultDocumentIcon, {})
75
123
  }
76
124
  );
77
- const content = /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { gap: "md", wrap: "nowrap", align: "center", children: [
125
+ const chevron = showChevron ? /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { c: index.fairmintVars.colorTextTertiary, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsxRuntime.jsx(DefaultChevronIcon, {}) }) : null;
126
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
78
127
  /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { style: { flexShrink: 0 }, children: leadingNode }),
79
128
  /* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { gap: 2, style: { minWidth: 0, flex: 1 }, children: [
80
129
  /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { fw: 500, size: "sm", lineClamp: 1, children: name }),
81
130
  resolvedCaption !== void 0 && resolvedCaption !== null && resolvedCaption !== "" ? typeof resolvedCaption === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { size: "xs", c: index.fairmintVars.colorTextSecondary, lineClamp: 1, children: resolvedCaption }) : resolvedCaption : null
82
- ] }),
83
- /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { gap: "xs", wrap: "nowrap", style: { flexShrink: 0 }, children: [
84
- rightSection,
85
- showChevron && /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { c: index.fairmintVars.colorTextTertiary, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsxRuntime.jsx(DefaultChevronIcon, {}) })
86
131
  ] })
87
132
  ] });
88
133
  const animationStyle = animate ? {
@@ -91,19 +136,51 @@ function DocumentRow({
91
136
  animationDelay: `${animationDelay}s`
92
137
  } : void 0;
93
138
  if (!isClickable) {
94
- return /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { py: "sm", px: "md", style: animationStyle, children: content });
139
+ return /* @__PURE__ */ jsxRuntime.jsx(layout.Box, { py: "sm", px: "md", w: "100%", style: animationStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { gap: "md", wrap: "nowrap", align: "center", children: [
140
+ body,
141
+ /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { gap: "xs", wrap: "nowrap", style: { flexShrink: 0 }, children: [
142
+ rightSection,
143
+ chevron
144
+ ] })
145
+ ] }) });
95
146
  }
96
- return /* @__PURE__ */ jsxRuntime.jsx(
97
- UnstyledButton.UnstyledButton,
147
+ const handleShellClick = (event) => {
148
+ if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) {
149
+ return;
150
+ }
151
+ if (clickLandedOnControl(event.target, event.currentTarget)) {
152
+ return;
153
+ }
154
+ onClick?.();
155
+ };
156
+ return /* @__PURE__ */ jsxRuntime.jsxs(
157
+ Group.Group,
98
158
  {
99
- onClick,
159
+ gap: "md",
160
+ wrap: "nowrap",
161
+ align: "center",
100
162
  className: "fairmint-list-row",
101
163
  w: "100%",
102
- py: "sm",
103
- px: "md",
104
164
  style: animationStyle,
105
- "aria-label": ariaLabel ?? name,
106
- children: content
165
+ onClick: handleShellClick,
166
+ children: [
167
+ /* @__PURE__ */ jsxRuntime.jsx(
168
+ UnstyledButton.UnstyledButton,
169
+ {
170
+ onClick,
171
+ py: "sm",
172
+ pl: "md",
173
+ pr: hasTrailingContent(rightSection) ? 0 : "md",
174
+ style: { flex: 1, minWidth: 0, display: "flex" },
175
+ "aria-label": ariaLabel ?? name,
176
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { gap: "md", wrap: "nowrap", align: "center", style: { flex: 1, minWidth: 0 }, children: [
177
+ body,
178
+ chevron
179
+ ] })
180
+ }
181
+ ),
182
+ hasTrailingContent(rightSection) ? /* @__PURE__ */ jsxRuntime.jsx(Group.Group, { gap: "xs", wrap: "nowrap", py: "sm", pr: "md", style: { flexShrink: 0 }, children: typeof rightSection === "string" || typeof rightSection === "number" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: rightSection }) : rightSection }) : null
183
+ ]
107
184
  }
108
185
  );
109
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentRow.cjs","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { formatDate } from \"../../../utils/format\";\nimport { Box, Group, Stack, Text, ThemeIcon, UnstyledButton } from \"../../primitives/layout\";\n\n/**\n * Default file-glyph SVG. Inlined so the library doesn't depend on\n * `@tabler/icons-react` (per the icon-injection rule). Consumers can\n * override the leading slot via the `icon` prop when a different glyph\n * (or a stacked badge) is more appropriate.\n */\nconst DefaultDocumentIcon = () => (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n);\n\nconst DefaultChevronIcon = () => (\n <svg\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 aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nexport interface DocumentRowProps {\n /** Primary title — usually the file or agreement name. */\n name: string;\n /**\n * Description below the title. Accepts a `ReactNode` so consumers can mix\n * Badges, Text, dates, and inline metadata (companyName, seriesName, etc.)\n * without working around a single-string subtitle slot.\n */\n caption?: ReactNode;\n /**\n * @deprecated Use `caption` directly. When `caption` is omitted and\n * `type` and/or `date` is supplied, they are joined with \" · \" to\n * produce a string caption. Preserved for backwards compatibility\n * with the previous, ListRow-backed API.\n */\n type?: string;\n /**\n * @deprecated Use `caption` directly. The date is now consumer-\n * formatted; pass a formatted string via `caption` instead. Preserved\n * for backwards compatibility.\n */\n date?: string;\n /**\n * Leading visual — defaults to a tinted file-icon `ThemeIcon`. Pass a\n * custom node (an icon, a badge, a small Avatar, etc.) when you want\n * a different leading affordance.\n */\n icon?: ReactNode;\n /** Right-side content — download button, lock badge, preview link, etc. */\n rightSection?: ReactNode;\n /**\n * Drill-in chevron. Defaults to `false` — the right-side glyph (a\n * download icon, a preview link, a status badge) usually conveys the\n * affordance and the chevron is visual noise. Set to `true` for \"row\n * that opens a detail view\" patterns.\n */\n showChevron?: boolean;\n /** Click handler. */\n onClick?: () => void;\n /** Entrance animation delay in seconds. Omit to skip animation. */\n animationDelay?: number;\n /** aria-label for the clickable wrapper. Defaults to `name`. */\n ariaLabel?: string;\n}\n\n/**\n * Document list item — title, free-form caption, optional leading icon,\n * optional right-side affordance, optional drill-in chevron.\n *\n * Designed against three real consumers (investorv2's `OpportunityDocuments`,\n * `SignSection` legal-doc list, and the mobile card view on `/documents`)\n * so the shape covers the actual patterns rather than an imagined one.\n *\n * Backwards-compat note: the previous `type` + `date` API still works.\n * When `caption` is omitted, the legacy props are joined with \" · \" into\n * a string caption.\n */\nexport function DocumentRow({\n name,\n caption,\n type,\n date,\n icon,\n rightSection,\n onClick,\n showChevron = false,\n animationDelay,\n ariaLabel,\n}: DocumentRowProps) {\n const isClickable = Boolean(onClick);\n const animate = animationDelay !== undefined;\n\n const resolvedCaption: ReactNode =\n caption ??\n (type || date\n ? [type, date ? formatDate(date) : undefined].filter(Boolean).join(\" · \")\n : undefined);\n\n const leadingNode = icon ?? (\n <ThemeIcon\n size={36}\n radius=\"md\"\n variant=\"light\"\n color={colors.primary}\n style={{\n backgroundColor: fairmintVars.colorBgBrandSubtle,\n color: fairmintVars.colorBrandPrimary,\n }}\n >\n <DefaultDocumentIcon />\n </ThemeIcon>\n );\n\n const content = (\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\">\n <Box style={{ flexShrink: 0 }}>{leadingNode}</Box>\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Text fw={500} size=\"sm\" lineClamp={1}>\n {name}\n </Text>\n {resolvedCaption !== undefined && resolvedCaption !== null && resolvedCaption !== \"\" ? (\n typeof resolvedCaption === \"string\" ? (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lineClamp={1}>\n {resolvedCaption}\n </Text>\n ) : (\n resolvedCaption\n )\n ) : null}\n </Stack>\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {rightSection}\n {showChevron && (\n <Box c={fairmintVars.colorTextTertiary} style={{ display: \"inline-flex\" }}>\n <DefaultChevronIcon />\n </Box>\n )}\n </Group>\n </Group>\n );\n\n const animationStyle = animate\n ? ({\n opacity: 0 as const,\n animation: \"rowSlideIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards\",\n animationDelay: `${animationDelay}s`,\n } as const)\n : undefined;\n\n if (!isClickable) {\n return (\n <Box py=\"sm\" px=\"md\" style={animationStyle}>\n {content}\n </Box>\n );\n }\n\n return (\n <UnstyledButton\n onClick={onClick}\n className=\"fairmint-list-row\"\n w=\"100%\"\n py=\"sm\"\n px=\"md\"\n style={animationStyle}\n aria-label={ariaLabel ?? name}\n >\n {content}\n </UnstyledButton>\n );\n}\n"],"names":["jsxs","jsx","formatDate","ThemeIcon","colors","fairmintVars","Group","Box","Stack","Text","UnstyledButton"],"mappings":";;;;;;;;;;;AAYA,MAAM,sBAAsB,MAC1BA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,OAAM;AAAA,IACN,QAAO;AAAA,IACP,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA,IACf,eAAY;AAAA,IAEZ,UAAA;AAAA,MAAAC,2BAAAA,IAAC,QAAA,EAAK,GAAE,6DAAA,CAA6D;AAAA,MACrEA,2BAAAA,IAAC,YAAA,EAAS,QAAO,iBAAA,CAAiB;AAAA,MAClCA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,MACrCA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,MACrCA,2BAAAA,IAAC,YAAA,EAAS,QAAO,eAAA,CAAe;AAAA,IAAA;AAAA,EAAA;AAClC;AAGF,MAAM,qBAAqB,MACzBA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,OAAM;AAAA,IACN,QAAO;AAAA,IACP,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA,IACf,eAAY;AAAA,IAEZ,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EAAA;AAC1B;AA4DK,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,cAAc,QAAQ,OAAO;AACnC,QAAM,UAAU,mBAAmB;AAEnC,QAAM,kBACJ,YACC,QAAQ,OACL,CAAC,MAAM,OAAOC,OAAAA,WAAW,IAAI,IAAI,MAAS,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,IACtE;AAEN,QAAM,cAAc,QAClBD,2BAAAA;AAAAA,IAACE,UAAAA;AAAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,OAAOC,OAAAA,OAAO;AAAA,MACd,OAAO;AAAA,QACL,iBAAiBC,MAAAA,aAAa;AAAA,QAC9B,OAAOA,MAAAA,aAAa;AAAA,MAAA;AAAA,MAGtB,yCAAC,qBAAA,CAAA,CAAoB;AAAA,IAAA;AAAA,EAAA;AAIzB,QAAM,0CACHC,MAAAA,OAAA,EAAM,KAAI,MAAK,MAAK,UAAS,OAAM,UAClC,UAAA;AAAA,IAAAL,+BAACM,OAAAA,OAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,aAAY;AAAA,IAC5CP,2BAAAA,KAACQ,OAAAA,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,MAAAP,2BAAAA,IAACQ,KAAAA,QAAK,IAAI,KAAK,MAAK,MAAK,WAAW,GACjC,UAAA,KAAA,CACH;AAAA,MACC,oBAAoB,UAAa,oBAAoB,QAAQ,oBAAoB,KAChF,OAAO,oBAAoB,WACzBR,2BAAAA,IAACQ,KAAAA,QAAK,MAAK,MAAK,GAAGJ,MAAAA,aAAa,oBAAoB,WAAW,GAC5D,UAAA,iBACH,IAEA,kBAEA;AAAA,IAAA,GACN;AAAA,IACAL,2BAAAA,KAACM,MAAAA,OAAA,EAAM,KAAI,MAAK,MAAK,UAAS,OAAO,EAAE,YAAY,EAAA,GAChD,UAAA;AAAA,MAAA;AAAA,MACA,eACCL,2BAAAA,IAACM,OAAAA,KAAA,EAAI,GAAGF,MAAAA,aAAa,mBAAmB,OAAO,EAAE,SAAS,cAAA,GACxD,UAAAJ,2BAAAA,IAAC,sBAAmB,EAAA,CACtB;AAAA,IAAA,EAAA,CAEJ;AAAA,EAAA,GACF;AAGF,QAAM,iBAAiB,UAClB;AAAA,IACC,SAAS;AAAA,IACT,WAAW;AAAA,IACX,gBAAgB,GAAG,cAAc;AAAA,EAAA,IAEnC;AAEJ,MAAI,CAAC,aAAa;AAChB,WACEA,+BAACM,OAAAA,OAAI,IAAG,MAAK,IAAG,MAAK,OAAO,gBACzB,UAAA,QAAA,CACH;AAAA,EAEJ;AAEA,SACEN,2BAAAA;AAAAA,IAACS,eAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MACV,GAAE;AAAA,MACF,IAAG;AAAA,MACH,IAAG;AAAA,MACH,OAAO;AAAA,MACP,cAAY,aAAa;AAAA,MAExB,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;;"}
1
+ {"version":3,"file":"DocumentRow.cjs","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"sourcesContent":["import type { MouseEvent, ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { formatDate } from \"../../../utils/format\";\nimport { Box, Group, Stack, Text, ThemeIcon, UnstyledButton } from \"../../primitives/layout\";\n\n/**\n * Default file-glyph SVG. Inlined so the library doesn't depend on\n * `@tabler/icons-react` (per the icon-injection rule). Consumers can\n * override the leading slot via the `icon` prop when a different glyph\n * (or a stacked badge) is more appropriate.\n */\nconst DefaultDocumentIcon = () => (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n);\n\nconst DefaultChevronIcon = () => (\n <svg\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 aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst NATIVE_CONTROL_SELECTOR =\n \"a, button, input, select, textarea, label, summary, [contenteditable]:not([contenteditable='false'])\";\n\nconst INTERACTIVE_ARIA_ROLES = new Set([\n \"button\",\n \"checkbox\",\n \"combobox\",\n \"gridcell\",\n \"link\",\n \"listbox\",\n \"menu\",\n \"menuitem\",\n \"menuitemcheckbox\",\n \"menuitemradio\",\n \"option\",\n \"radio\",\n \"scrollbar\",\n \"searchbox\",\n \"slider\",\n \"spinbutton\",\n \"switch\",\n \"tab\",\n \"textbox\",\n \"treeitem\",\n]);\n\nfunction clickLandedOnControl(target: EventTarget | null, root: EventTarget): boolean {\n if (!(target instanceof Element) || !(root instanceof Element)) {\n return false;\n }\n const native = target.closest(NATIVE_CONTROL_SELECTOR);\n if (native !== null && root.contains(native)) {\n return true;\n }\n let node: Element | null = target;\n while (node !== null && node !== root && root.contains(node)) {\n const role = node.getAttribute(\"role\");\n if (role !== null) {\n for (const token of role.split(/\\s+/)) {\n if (INTERACTIVE_ARIA_ROLES.has(token)) {\n return true;\n }\n }\n }\n node = node.parentElement;\n }\n return false;\n}\n\nfunction hasTrailingContent(node: ReactNode): boolean {\n return node != null && typeof node !== \"boolean\";\n}\n\nexport interface DocumentRowProps {\n /** Primary title — usually the file or agreement name. */\n name: string;\n /**\n * Description below the title. Accepts a `ReactNode` so consumers can mix\n * Badges, Text, dates, and inline metadata (companyName, seriesName, etc.)\n * without working around a single-string subtitle slot.\n */\n caption?: ReactNode;\n /**\n * @deprecated Use `caption` directly. When `caption` is omitted and\n * `type` and/or `date` is supplied, they are joined with \" · \" to\n * produce a string caption. Preserved for backwards compatibility\n * with the previous, ListRow-backed API.\n */\n type?: string;\n /**\n * @deprecated Use `caption` directly. The date is now consumer-\n * formatted; pass a formatted string via `caption` instead. Preserved\n * for backwards compatibility.\n */\n date?: string;\n /**\n * Leading visual — defaults to a tinted file-icon `ThemeIcon`. Pass a\n * custom node (an icon, a badge, a small Avatar, etc.) when you want\n * a different leading affordance.\n */\n icon?: ReactNode;\n /**\n * Right-side content — download button, lock badge, preview link, etc.\n *\n * On a clickable row this is a sibling of the row button (never nested).\n * Clicks on decorative trailing content still fire `onClick`; clicks on\n * buttons, links, and other controls do not.\n */\n rightSection?: ReactNode;\n /**\n * Drill-in chevron. Defaults to `false` — the right-side glyph (a\n * download icon, a preview link, a status badge) usually conveys the\n * affordance and the chevron is visual noise. Set to `true` for \"row\n * that opens a detail view\" patterns.\n */\n showChevron?: boolean;\n /** Click handler. */\n onClick?: () => void;\n /** Entrance animation delay in seconds. Omit to skip animation. */\n animationDelay?: number;\n /** aria-label for the clickable wrapper. Defaults to `name`. */\n ariaLabel?: string;\n}\n\n/**\n * Document list item — title, free-form caption, optional leading icon,\n * optional right-side affordance, optional drill-in chevron.\n *\n * Designed against three real consumers (investorv2's `OpportunityDocuments`,\n * `SignSection` legal-doc list, and the mobile card view on `/documents`)\n * so the shape covers the actual patterns rather than an imagined one.\n *\n * Backwards-compat note: the previous `type` + `date` API still works.\n * When `caption` is omitted, the legacy props are joined with \" · \" into\n * a string caption.\n */\nexport function DocumentRow({\n name,\n caption,\n type,\n date,\n icon,\n rightSection,\n onClick,\n showChevron = false,\n animationDelay,\n ariaLabel,\n}: DocumentRowProps) {\n const isClickable = Boolean(onClick);\n const animate = animationDelay !== undefined;\n\n const resolvedCaption: ReactNode =\n caption ??\n (type || date\n ? [type, date ? formatDate(date) : undefined].filter(Boolean).join(\" · \")\n : undefined);\n\n const leadingNode = icon ?? (\n <ThemeIcon\n size={36}\n radius=\"md\"\n variant=\"light\"\n color={colors.primary}\n style={{\n backgroundColor: fairmintVars.colorBgBrandSubtle,\n color: fairmintVars.colorBrandPrimary,\n }}\n >\n <DefaultDocumentIcon />\n </ThemeIcon>\n );\n\n const chevron = showChevron ? (\n <Box c={fairmintVars.colorTextTertiary} style={{ display: \"inline-flex\" }}>\n <DefaultChevronIcon />\n </Box>\n ) : null;\n\n // Leading icon + name/caption. On a clickable row this sits in the button\n // with padding and the optional chevron; `rightSection` is a sibling.\n const body = (\n <>\n <Box style={{ flexShrink: 0 }}>{leadingNode}</Box>\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Text fw={500} size=\"sm\" lineClamp={1}>\n {name}\n </Text>\n {resolvedCaption !== undefined && resolvedCaption !== null && resolvedCaption !== \"\" ? (\n typeof resolvedCaption === \"string\" ? (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lineClamp={1}>\n {resolvedCaption}\n </Text>\n ) : (\n resolvedCaption\n )\n ) : null}\n </Stack>\n </>\n );\n\n const animationStyle = animate\n ? ({\n opacity: 0 as const,\n animation: \"rowSlideIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards\",\n animationDelay: `${animationDelay}s`,\n } as const)\n : undefined;\n\n if (!isClickable) {\n return (\n <Box py=\"sm\" px=\"md\" w=\"100%\" style={animationStyle}>\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\">\n {body}\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {rightSection}\n {chevron}\n </Group>\n </Group>\n </Box>\n );\n }\n\n const handleShellClick = (event: MouseEvent<HTMLDivElement>) => {\n if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) {\n return;\n }\n if (clickLandedOnControl(event.target, event.currentTarget)) {\n return;\n }\n onClick?.();\n };\n\n // Primary button: padding, body, chevron. `rightSection` is always a sibling\n // so trailing controls never nest. Shell clicks (gap, decorative trailers)\n // still fire `onClick`. `fairmint-list-row` is only on the shell.\n return (\n <Group\n gap=\"md\"\n wrap=\"nowrap\"\n align=\"center\"\n className=\"fairmint-list-row\"\n w=\"100%\"\n style={animationStyle}\n onClick={handleShellClick}\n >\n <UnstyledButton\n onClick={onClick}\n py=\"sm\"\n pl=\"md\"\n pr={hasTrailingContent(rightSection) ? 0 : \"md\"}\n style={{ flex: 1, minWidth: 0, display: \"flex\" }}\n aria-label={ariaLabel ?? name}\n >\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\" style={{ flex: 1, minWidth: 0 }}>\n {body}\n {chevron}\n </Group>\n </UnstyledButton>\n {hasTrailingContent(rightSection) ? (\n <Group gap=\"xs\" wrap=\"nowrap\" py=\"sm\" pr=\"md\" style={{ flexShrink: 0 }}>\n {typeof rightSection === \"string\" || typeof rightSection === \"number\" ? (\n <span>{rightSection}</span>\n ) : (\n rightSection\n )}\n </Group>\n ) : null}\n </Group>\n );\n}\n"],"names":["jsxs","jsx","formatDate","ThemeIcon","colors","fairmintVars","Box","Fragment","Stack","Text","Group","UnstyledButton"],"mappings":";;;;;;;;;;;AAYA,MAAM,sBAAsB,MAC1BA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,OAAM;AAAA,IACN,QAAO;AAAA,IACP,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA,IACf,eAAY;AAAA,IAEZ,UAAA;AAAA,MAAAC,2BAAAA,IAAC,QAAA,EAAK,GAAE,6DAAA,CAA6D;AAAA,MACrEA,2BAAAA,IAAC,YAAA,EAAS,QAAO,iBAAA,CAAiB;AAAA,MAClCA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,MACrCA,2BAAAA,IAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,MACrCA,2BAAAA,IAAC,YAAA,EAAS,QAAO,eAAA,CAAe;AAAA,IAAA;AAAA,EAAA;AAClC;AAGF,MAAM,qBAAqB,MACzBA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,OAAM;AAAA,IACN,QAAO;AAAA,IACP,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA,IACf,eAAY;AAAA,IAEZ,UAAAA,2BAAAA,IAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EAAA;AAC1B;AAGF,MAAM,0BACJ;AAEF,MAAM,6CAA6B,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,qBAAqB,QAA4B,MAA4B;AACpF,MAAI,EAAE,kBAAkB,YAAY,EAAE,gBAAgB,UAAU;AAC9D,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,QAAQ,uBAAuB;AACrD,MAAI,WAAW,QAAQ,KAAK,SAAS,MAAM,GAAG;AAC5C,WAAO;AAAA,EACT;AACA,MAAI,OAAuB;AAC3B,SAAO,SAAS,QAAQ,SAAS,QAAQ,KAAK,SAAS,IAAI,GAAG;AAC5D,UAAM,OAAO,KAAK,aAAa,MAAM;AACrC,QAAI,SAAS,MAAM;AACjB,iBAAW,SAAS,KAAK,MAAM,KAAK,GAAG;AACrC,YAAI,uBAAuB,IAAI,KAAK,GAAG;AACrC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,MAA0B;AACpD,SAAO,QAAQ,QAAQ,OAAO,SAAS;AACzC;AAiEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,cAAc,QAAQ,OAAO;AACnC,QAAM,UAAU,mBAAmB;AAEnC,QAAM,kBACJ,YACC,QAAQ,OACL,CAAC,MAAM,OAAOC,OAAAA,WAAW,IAAI,IAAI,MAAS,EAAE,OAAO,OAAO,EAAE,KAAK,KAAK,IACtE;AAEN,QAAM,cAAc,QAClBD,2BAAAA;AAAAA,IAACE,UAAAA;AAAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,OAAOC,OAAAA,OAAO;AAAA,MACd,OAAO;AAAA,QACL,iBAAiBC,MAAAA,aAAa;AAAA,QAC9B,OAAOA,MAAAA,aAAa;AAAA,MAAA;AAAA,MAGtB,yCAAC,qBAAA,CAAA,CAAoB;AAAA,IAAA;AAAA,EAAA;AAIzB,QAAM,UAAU,cACdJ,2BAAAA,IAACK,OAAAA,KAAA,EAAI,GAAGD,MAAAA,aAAa,mBAAmB,OAAO,EAAE,SAAS,cAAA,GACxD,UAAAJ,2BAAAA,IAAC,oBAAA,CAAA,CAAmB,GACtB,IACE;AAIJ,QAAM,OACJD,2BAAAA,KAAAO,WAAAA,UAAA,EACE,UAAA;AAAA,IAAAN,+BAACK,OAAAA,OAAI,OAAO,EAAE,YAAY,EAAA,GAAM,UAAA,aAAY;AAAA,IAC5CN,2BAAAA,KAACQ,OAAAA,OAAA,EAAM,KAAK,GAAG,OAAO,EAAE,UAAU,GAAG,MAAM,EAAA,GACzC,UAAA;AAAA,MAAAP,2BAAAA,IAACQ,KAAAA,QAAK,IAAI,KAAK,MAAK,MAAK,WAAW,GACjC,UAAA,KAAA,CACH;AAAA,MACC,oBAAoB,UAAa,oBAAoB,QAAQ,oBAAoB,KAChF,OAAO,oBAAoB,WACzBR,2BAAAA,IAACQ,KAAAA,QAAK,MAAK,MAAK,GAAGJ,MAAAA,aAAa,oBAAoB,WAAW,GAC5D,UAAA,iBACH,IAEA,kBAEA;AAAA,IAAA,EAAA,CACN;AAAA,EAAA,GACF;AAGF,QAAM,iBAAiB,UAClB;AAAA,IACC,SAAS;AAAA,IACT,WAAW;AAAA,IACX,gBAAgB,GAAG,cAAc;AAAA,EAAA,IAEnC;AAEJ,MAAI,CAAC,aAAa;AAChB,0CACGC,YAAA,EAAI,IAAG,MAAK,IAAG,MAAK,GAAE,QAAO,OAAO,gBACnC,0CAACI,aAAA,EAAM,KAAI,MAAK,MAAK,UAAS,OAAM,UACjC,UAAA;AAAA,MAAA;AAAA,MACDV,2BAAAA,KAACU,MAAAA,OAAA,EAAM,KAAI,MAAK,MAAK,UAAS,OAAO,EAAE,YAAY,EAAA,GAChD,UAAA;AAAA,QAAA;AAAA,QACA;AAAA,MAAA,EAAA,CACH;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAEJ;AAEA,QAAM,mBAAmB,CAAC,UAAsC;AAC9D,QAAI,EAAE,MAAM,kBAAkB,SAAS,CAAC,MAAM,cAAc,SAAS,MAAM,MAAM,GAAG;AAClF;AAAA,IACF;AACA,QAAI,qBAAqB,MAAM,QAAQ,MAAM,aAAa,GAAG;AAC3D;AAAA,IACF;AACA,cAAA;AAAA,EACF;AAKA,SACEV,2BAAAA;AAAAA,IAACU,MAAAA;AAAAA,IAAA;AAAA,MACC,KAAI;AAAA,MACJ,MAAK;AAAA,MACL,OAAM;AAAA,MACN,WAAU;AAAA,MACV,GAAE;AAAA,MACF,OAAO;AAAA,MACP,SAAS;AAAA,MAET,UAAA;AAAA,QAAAT,2BAAAA;AAAAA,UAACU,eAAAA;AAAAA,UAAA;AAAA,YACC;AAAA,YACA,IAAG;AAAA,YACH,IAAG;AAAA,YACH,IAAI,mBAAmB,YAAY,IAAI,IAAI;AAAA,YAC3C,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,OAAA;AAAA,YACxC,cAAY,aAAa;AAAA,YAEzB,UAAAX,2BAAAA,KAACU,aAAA,EAAM,KAAI,MAAK,MAAK,UAAS,OAAM,UAAS,OAAO,EAAE,MAAM,GAAG,UAAU,KACtE,UAAA;AAAA,cAAA;AAAA,cACA;AAAA,YAAA,EAAA,CACH;AAAA,UAAA;AAAA,QAAA;AAAA,QAED,mBAAmB,YAAY,IAC9BT,2BAAAA,IAACS,MAAAA,OAAA,EAAM,KAAI,MAAK,MAAK,UAAS,IAAG,MAAK,IAAG,MAAK,OAAO,EAAE,YAAY,EAAA,GAChE,UAAA,OAAO,iBAAiB,YAAY,OAAO,iBAAiB,WAC3DT,2BAAAA,IAAC,QAAA,EAAM,UAAA,aAAA,CAAa,IAEpB,cAEJ,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;;"}
@@ -27,7 +27,13 @@ export interface DocumentRowProps {
27
27
  * a different leading affordance.
28
28
  */
29
29
  icon?: ReactNode;
30
- /** Right-side content — download button, lock badge, preview link, etc. */
30
+ /**
31
+ * Right-side content — download button, lock badge, preview link, etc.
32
+ *
33
+ * On a clickable row this is a sibling of the row button (never nested).
34
+ * Clicks on decorative trailing content still fire `onClick`; clicks on
35
+ * buttons, links, and other controls do not.
36
+ */
31
37
  rightSection?: ReactNode;
32
38
  /**
33
39
  * Drill-in chevron. Defaults to `false` — the right-side glyph (a
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentRow.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAgDvC,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,WAAmB,EACnB,cAAc,EACd,SAAS,GACV,EAAE,gBAAgB,+BAkFlB"}
1
+ {"version":3,"file":"DocumentRow.d.ts","sourceRoot":"","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,OAAO,CAAC;AAqGnD,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,WAAmB,EACnB,cAAc,EACd,SAAS,GACV,EAAE,gBAAgB,+BA0HlB"}
@@ -1,11 +1,11 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { fairmintVars } from "../../../theme/index.js";
3
3
  import { colors } from "../../../theme/colors.js";
4
4
  import { formatDate } from "../../../utils/format.js";
5
5
  import { Box, Stack } from "../../primitives/layout.js";
6
6
  import { ThemeIcon } from "../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.js";
7
- import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
8
7
  import { Text } from "../../primitives/Text/Text.js";
8
+ import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
9
9
  import { UnstyledButton } from "../../../node_modules/@mantine/core/esm/components/UnstyledButton/UnstyledButton.js";
10
10
  const DefaultDocumentIcon = () => /* @__PURE__ */ jsxs(
11
11
  "svg",
@@ -43,6 +43,54 @@ const DefaultChevronIcon = () => /* @__PURE__ */ jsx(
43
43
  children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
44
44
  }
45
45
  );
46
+ const NATIVE_CONTROL_SELECTOR = "a, button, input, select, textarea, label, summary, [contenteditable]:not([contenteditable='false'])";
47
+ const INTERACTIVE_ARIA_ROLES = /* @__PURE__ */ new Set([
48
+ "button",
49
+ "checkbox",
50
+ "combobox",
51
+ "gridcell",
52
+ "link",
53
+ "listbox",
54
+ "menu",
55
+ "menuitem",
56
+ "menuitemcheckbox",
57
+ "menuitemradio",
58
+ "option",
59
+ "radio",
60
+ "scrollbar",
61
+ "searchbox",
62
+ "slider",
63
+ "spinbutton",
64
+ "switch",
65
+ "tab",
66
+ "textbox",
67
+ "treeitem"
68
+ ]);
69
+ function clickLandedOnControl(target, root) {
70
+ if (!(target instanceof Element) || !(root instanceof Element)) {
71
+ return false;
72
+ }
73
+ const native = target.closest(NATIVE_CONTROL_SELECTOR);
74
+ if (native !== null && root.contains(native)) {
75
+ return true;
76
+ }
77
+ let node = target;
78
+ while (node !== null && node !== root && root.contains(node)) {
79
+ const role = node.getAttribute("role");
80
+ if (role !== null) {
81
+ for (const token of role.split(/\s+/)) {
82
+ if (INTERACTIVE_ARIA_ROLES.has(token)) {
83
+ return true;
84
+ }
85
+ }
86
+ }
87
+ node = node.parentElement;
88
+ }
89
+ return false;
90
+ }
91
+ function hasTrailingContent(node) {
92
+ return node != null && typeof node !== "boolean";
93
+ }
46
94
  function DocumentRow({
47
95
  name,
48
96
  caption,
@@ -72,15 +120,12 @@ function DocumentRow({
72
120
  children: /* @__PURE__ */ jsx(DefaultDocumentIcon, {})
73
121
  }
74
122
  );
75
- const content = /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", align: "center", children: [
123
+ const chevron = showChevron ? /* @__PURE__ */ jsx(Box, { c: fairmintVars.colorTextTertiary, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx(DefaultChevronIcon, {}) }) : null;
124
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
76
125
  /* @__PURE__ */ jsx(Box, { style: { flexShrink: 0 }, children: leadingNode }),
77
126
  /* @__PURE__ */ jsxs(Stack, { gap: 2, style: { minWidth: 0, flex: 1 }, children: [
78
127
  /* @__PURE__ */ jsx(Text, { fw: 500, size: "sm", lineClamp: 1, children: name }),
79
128
  resolvedCaption !== void 0 && resolvedCaption !== null && resolvedCaption !== "" ? typeof resolvedCaption === "string" ? /* @__PURE__ */ jsx(Text, { size: "xs", c: fairmintVars.colorTextSecondary, lineClamp: 1, children: resolvedCaption }) : resolvedCaption : null
80
- ] }),
81
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { flexShrink: 0 }, children: [
82
- rightSection,
83
- showChevron && /* @__PURE__ */ jsx(Box, { c: fairmintVars.colorTextTertiary, style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx(DefaultChevronIcon, {}) })
84
129
  ] })
85
130
  ] });
86
131
  const animationStyle = animate ? {
@@ -89,19 +134,51 @@ function DocumentRow({
89
134
  animationDelay: `${animationDelay}s`
90
135
  } : void 0;
91
136
  if (!isClickable) {
92
- return /* @__PURE__ */ jsx(Box, { py: "sm", px: "md", style: animationStyle, children: content });
137
+ return /* @__PURE__ */ jsx(Box, { py: "sm", px: "md", w: "100%", style: animationStyle, children: /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", align: "center", children: [
138
+ body,
139
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { flexShrink: 0 }, children: [
140
+ rightSection,
141
+ chevron
142
+ ] })
143
+ ] }) });
93
144
  }
94
- return /* @__PURE__ */ jsx(
95
- UnstyledButton,
145
+ const handleShellClick = (event) => {
146
+ if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) {
147
+ return;
148
+ }
149
+ if (clickLandedOnControl(event.target, event.currentTarget)) {
150
+ return;
151
+ }
152
+ onClick?.();
153
+ };
154
+ return /* @__PURE__ */ jsxs(
155
+ Group,
96
156
  {
97
- onClick,
157
+ gap: "md",
158
+ wrap: "nowrap",
159
+ align: "center",
98
160
  className: "fairmint-list-row",
99
161
  w: "100%",
100
- py: "sm",
101
- px: "md",
102
162
  style: animationStyle,
103
- "aria-label": ariaLabel ?? name,
104
- children: content
163
+ onClick: handleShellClick,
164
+ children: [
165
+ /* @__PURE__ */ jsx(
166
+ UnstyledButton,
167
+ {
168
+ onClick,
169
+ py: "sm",
170
+ pl: "md",
171
+ pr: hasTrailingContent(rightSection) ? 0 : "md",
172
+ style: { flex: 1, minWidth: 0, display: "flex" },
173
+ "aria-label": ariaLabel ?? name,
174
+ children: /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", align: "center", style: { flex: 1, minWidth: 0 }, children: [
175
+ body,
176
+ chevron
177
+ ] })
178
+ }
179
+ ),
180
+ hasTrailingContent(rightSection) ? /* @__PURE__ */ jsx(Group, { gap: "xs", wrap: "nowrap", py: "sm", pr: "md", style: { flexShrink: 0 }, children: typeof rightSection === "string" || typeof rightSection === "number" ? /* @__PURE__ */ jsx("span", { children: rightSection }) : rightSection }) : null
181
+ ]
105
182
  }
106
183
  );
107
184
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentRow.js","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { formatDate } from \"../../../utils/format\";\nimport { Box, Group, Stack, Text, ThemeIcon, UnstyledButton } from \"../../primitives/layout\";\n\n/**\n * Default file-glyph SVG. Inlined so the library doesn't depend on\n * `@tabler/icons-react` (per the icon-injection rule). Consumers can\n * override the leading slot via the `icon` prop when a different glyph\n * (or a stacked badge) is more appropriate.\n */\nconst DefaultDocumentIcon = () => (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n);\n\nconst DefaultChevronIcon = () => (\n <svg\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 aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nexport interface DocumentRowProps {\n /** Primary title — usually the file or agreement name. */\n name: string;\n /**\n * Description below the title. Accepts a `ReactNode` so consumers can mix\n * Badges, Text, dates, and inline metadata (companyName, seriesName, etc.)\n * without working around a single-string subtitle slot.\n */\n caption?: ReactNode;\n /**\n * @deprecated Use `caption` directly. When `caption` is omitted and\n * `type` and/or `date` is supplied, they are joined with \" · \" to\n * produce a string caption. Preserved for backwards compatibility\n * with the previous, ListRow-backed API.\n */\n type?: string;\n /**\n * @deprecated Use `caption` directly. The date is now consumer-\n * formatted; pass a formatted string via `caption` instead. Preserved\n * for backwards compatibility.\n */\n date?: string;\n /**\n * Leading visual — defaults to a tinted file-icon `ThemeIcon`. Pass a\n * custom node (an icon, a badge, a small Avatar, etc.) when you want\n * a different leading affordance.\n */\n icon?: ReactNode;\n /** Right-side content — download button, lock badge, preview link, etc. */\n rightSection?: ReactNode;\n /**\n * Drill-in chevron. Defaults to `false` — the right-side glyph (a\n * download icon, a preview link, a status badge) usually conveys the\n * affordance and the chevron is visual noise. Set to `true` for \"row\n * that opens a detail view\" patterns.\n */\n showChevron?: boolean;\n /** Click handler. */\n onClick?: () => void;\n /** Entrance animation delay in seconds. Omit to skip animation. */\n animationDelay?: number;\n /** aria-label for the clickable wrapper. Defaults to `name`. */\n ariaLabel?: string;\n}\n\n/**\n * Document list item — title, free-form caption, optional leading icon,\n * optional right-side affordance, optional drill-in chevron.\n *\n * Designed against three real consumers (investorv2's `OpportunityDocuments`,\n * `SignSection` legal-doc list, and the mobile card view on `/documents`)\n * so the shape covers the actual patterns rather than an imagined one.\n *\n * Backwards-compat note: the previous `type` + `date` API still works.\n * When `caption` is omitted, the legacy props are joined with \" · \" into\n * a string caption.\n */\nexport function DocumentRow({\n name,\n caption,\n type,\n date,\n icon,\n rightSection,\n onClick,\n showChevron = false,\n animationDelay,\n ariaLabel,\n}: DocumentRowProps) {\n const isClickable = Boolean(onClick);\n const animate = animationDelay !== undefined;\n\n const resolvedCaption: ReactNode =\n caption ??\n (type || date\n ? [type, date ? formatDate(date) : undefined].filter(Boolean).join(\" · \")\n : undefined);\n\n const leadingNode = icon ?? (\n <ThemeIcon\n size={36}\n radius=\"md\"\n variant=\"light\"\n color={colors.primary}\n style={{\n backgroundColor: fairmintVars.colorBgBrandSubtle,\n color: fairmintVars.colorBrandPrimary,\n }}\n >\n <DefaultDocumentIcon />\n </ThemeIcon>\n );\n\n const content = (\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\">\n <Box style={{ flexShrink: 0 }}>{leadingNode}</Box>\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Text fw={500} size=\"sm\" lineClamp={1}>\n {name}\n </Text>\n {resolvedCaption !== undefined && resolvedCaption !== null && resolvedCaption !== \"\" ? (\n typeof resolvedCaption === \"string\" ? (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lineClamp={1}>\n {resolvedCaption}\n </Text>\n ) : (\n resolvedCaption\n )\n ) : null}\n </Stack>\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {rightSection}\n {showChevron && (\n <Box c={fairmintVars.colorTextTertiary} style={{ display: \"inline-flex\" }}>\n <DefaultChevronIcon />\n </Box>\n )}\n </Group>\n </Group>\n );\n\n const animationStyle = animate\n ? ({\n opacity: 0 as const,\n animation: \"rowSlideIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards\",\n animationDelay: `${animationDelay}s`,\n } as const)\n : undefined;\n\n if (!isClickable) {\n return (\n <Box py=\"sm\" px=\"md\" style={animationStyle}>\n {content}\n </Box>\n );\n }\n\n return (\n <UnstyledButton\n onClick={onClick}\n className=\"fairmint-list-row\"\n w=\"100%\"\n py=\"sm\"\n px=\"md\"\n style={animationStyle}\n aria-label={ariaLabel ?? name}\n >\n {content}\n </UnstyledButton>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DocumentRow.js","sources":["../../../../src/components/specific/DocumentRow/DocumentRow.tsx"],"sourcesContent":["import type { MouseEvent, ReactNode } from \"react\";\nimport { fairmintVars } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { formatDate } from \"../../../utils/format\";\nimport { Box, Group, Stack, Text, ThemeIcon, UnstyledButton } from \"../../primitives/layout\";\n\n/**\n * Default file-glyph SVG. Inlined so the library doesn't depend on\n * `@tabler/icons-react` (per the icon-injection rule). Consumers can\n * override the leading slot via the `icon` prop when a different glyph\n * (or a stacked badge) is more appropriate.\n */\nconst DefaultDocumentIcon = () => (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n);\n\nconst DefaultChevronIcon = () => (\n <svg\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 aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst NATIVE_CONTROL_SELECTOR =\n \"a, button, input, select, textarea, label, summary, [contenteditable]:not([contenteditable='false'])\";\n\nconst INTERACTIVE_ARIA_ROLES = new Set([\n \"button\",\n \"checkbox\",\n \"combobox\",\n \"gridcell\",\n \"link\",\n \"listbox\",\n \"menu\",\n \"menuitem\",\n \"menuitemcheckbox\",\n \"menuitemradio\",\n \"option\",\n \"radio\",\n \"scrollbar\",\n \"searchbox\",\n \"slider\",\n \"spinbutton\",\n \"switch\",\n \"tab\",\n \"textbox\",\n \"treeitem\",\n]);\n\nfunction clickLandedOnControl(target: EventTarget | null, root: EventTarget): boolean {\n if (!(target instanceof Element) || !(root instanceof Element)) {\n return false;\n }\n const native = target.closest(NATIVE_CONTROL_SELECTOR);\n if (native !== null && root.contains(native)) {\n return true;\n }\n let node: Element | null = target;\n while (node !== null && node !== root && root.contains(node)) {\n const role = node.getAttribute(\"role\");\n if (role !== null) {\n for (const token of role.split(/\\s+/)) {\n if (INTERACTIVE_ARIA_ROLES.has(token)) {\n return true;\n }\n }\n }\n node = node.parentElement;\n }\n return false;\n}\n\nfunction hasTrailingContent(node: ReactNode): boolean {\n return node != null && typeof node !== \"boolean\";\n}\n\nexport interface DocumentRowProps {\n /** Primary title — usually the file or agreement name. */\n name: string;\n /**\n * Description below the title. Accepts a `ReactNode` so consumers can mix\n * Badges, Text, dates, and inline metadata (companyName, seriesName, etc.)\n * without working around a single-string subtitle slot.\n */\n caption?: ReactNode;\n /**\n * @deprecated Use `caption` directly. When `caption` is omitted and\n * `type` and/or `date` is supplied, they are joined with \" · \" to\n * produce a string caption. Preserved for backwards compatibility\n * with the previous, ListRow-backed API.\n */\n type?: string;\n /**\n * @deprecated Use `caption` directly. The date is now consumer-\n * formatted; pass a formatted string via `caption` instead. Preserved\n * for backwards compatibility.\n */\n date?: string;\n /**\n * Leading visual — defaults to a tinted file-icon `ThemeIcon`. Pass a\n * custom node (an icon, a badge, a small Avatar, etc.) when you want\n * a different leading affordance.\n */\n icon?: ReactNode;\n /**\n * Right-side content — download button, lock badge, preview link, etc.\n *\n * On a clickable row this is a sibling of the row button (never nested).\n * Clicks on decorative trailing content still fire `onClick`; clicks on\n * buttons, links, and other controls do not.\n */\n rightSection?: ReactNode;\n /**\n * Drill-in chevron. Defaults to `false` — the right-side glyph (a\n * download icon, a preview link, a status badge) usually conveys the\n * affordance and the chevron is visual noise. Set to `true` for \"row\n * that opens a detail view\" patterns.\n */\n showChevron?: boolean;\n /** Click handler. */\n onClick?: () => void;\n /** Entrance animation delay in seconds. Omit to skip animation. */\n animationDelay?: number;\n /** aria-label for the clickable wrapper. Defaults to `name`. */\n ariaLabel?: string;\n}\n\n/**\n * Document list item — title, free-form caption, optional leading icon,\n * optional right-side affordance, optional drill-in chevron.\n *\n * Designed against three real consumers (investorv2's `OpportunityDocuments`,\n * `SignSection` legal-doc list, and the mobile card view on `/documents`)\n * so the shape covers the actual patterns rather than an imagined one.\n *\n * Backwards-compat note: the previous `type` + `date` API still works.\n * When `caption` is omitted, the legacy props are joined with \" · \" into\n * a string caption.\n */\nexport function DocumentRow({\n name,\n caption,\n type,\n date,\n icon,\n rightSection,\n onClick,\n showChevron = false,\n animationDelay,\n ariaLabel,\n}: DocumentRowProps) {\n const isClickable = Boolean(onClick);\n const animate = animationDelay !== undefined;\n\n const resolvedCaption: ReactNode =\n caption ??\n (type || date\n ? [type, date ? formatDate(date) : undefined].filter(Boolean).join(\" · \")\n : undefined);\n\n const leadingNode = icon ?? (\n <ThemeIcon\n size={36}\n radius=\"md\"\n variant=\"light\"\n color={colors.primary}\n style={{\n backgroundColor: fairmintVars.colorBgBrandSubtle,\n color: fairmintVars.colorBrandPrimary,\n }}\n >\n <DefaultDocumentIcon />\n </ThemeIcon>\n );\n\n const chevron = showChevron ? (\n <Box c={fairmintVars.colorTextTertiary} style={{ display: \"inline-flex\" }}>\n <DefaultChevronIcon />\n </Box>\n ) : null;\n\n // Leading icon + name/caption. On a clickable row this sits in the button\n // with padding and the optional chevron; `rightSection` is a sibling.\n const body = (\n <>\n <Box style={{ flexShrink: 0 }}>{leadingNode}</Box>\n <Stack gap={2} style={{ minWidth: 0, flex: 1 }}>\n <Text fw={500} size=\"sm\" lineClamp={1}>\n {name}\n </Text>\n {resolvedCaption !== undefined && resolvedCaption !== null && resolvedCaption !== \"\" ? (\n typeof resolvedCaption === \"string\" ? (\n <Text size=\"xs\" c={fairmintVars.colorTextSecondary} lineClamp={1}>\n {resolvedCaption}\n </Text>\n ) : (\n resolvedCaption\n )\n ) : null}\n </Stack>\n </>\n );\n\n const animationStyle = animate\n ? ({\n opacity: 0 as const,\n animation: \"rowSlideIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards\",\n animationDelay: `${animationDelay}s`,\n } as const)\n : undefined;\n\n if (!isClickable) {\n return (\n <Box py=\"sm\" px=\"md\" w=\"100%\" style={animationStyle}>\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\">\n {body}\n <Group gap=\"xs\" wrap=\"nowrap\" style={{ flexShrink: 0 }}>\n {rightSection}\n {chevron}\n </Group>\n </Group>\n </Box>\n );\n }\n\n const handleShellClick = (event: MouseEvent<HTMLDivElement>) => {\n if (!(event.target instanceof Node) || !event.currentTarget.contains(event.target)) {\n return;\n }\n if (clickLandedOnControl(event.target, event.currentTarget)) {\n return;\n }\n onClick?.();\n };\n\n // Primary button: padding, body, chevron. `rightSection` is always a sibling\n // so trailing controls never nest. Shell clicks (gap, decorative trailers)\n // still fire `onClick`. `fairmint-list-row` is only on the shell.\n return (\n <Group\n gap=\"md\"\n wrap=\"nowrap\"\n align=\"center\"\n className=\"fairmint-list-row\"\n w=\"100%\"\n style={animationStyle}\n onClick={handleShellClick}\n >\n <UnstyledButton\n onClick={onClick}\n py=\"sm\"\n pl=\"md\"\n pr={hasTrailingContent(rightSection) ? 0 : \"md\"}\n style={{ flex: 1, minWidth: 0, display: \"flex\" }}\n aria-label={ariaLabel ?? name}\n >\n <Group gap=\"md\" wrap=\"nowrap\" align=\"center\" style={{ flex: 1, minWidth: 0 }}>\n {body}\n {chevron}\n </Group>\n </UnstyledButton>\n {hasTrailingContent(rightSection) ? (\n <Group gap=\"xs\" wrap=\"nowrap\" py=\"sm\" pr=\"md\" style={{ flexShrink: 0 }}>\n {typeof rightSection === \"string\" || typeof rightSection === \"number\" ? (\n <span>{rightSection}</span>\n ) : (\n rightSection\n )}\n </Group>\n ) : null}\n </Group>\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.4.11",
3
+ "version": "0.4.12",
4
4
  "type": "module",
5
5
  "description": "Fairmint design system and UI component library",
6
6
  "license": "SEE LICENSE IN LICENSE",