@fairmint/ui 0.4.18 → 0.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- var propTypes = { exports: {} };
4
- exports.__module = propTypes;
2
+ const _commonjsHelpers = require("./_commonjsHelpers.cjs");
3
+ const index = require("../node_modules/fast-deep-equal/index.cjs");
4
+ var fastDeepEqualExports = index.__require();
5
+ const isEqual = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(fastDeepEqualExports);
6
+ module.exports = isEqual;
5
7
  //# sourceMappingURL=index3.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index3.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index3.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,5 +1,8 @@
1
- var propTypes = { exports: {} };
1
+ import { getDefaultExportFromCjs } from "./_commonjsHelpers.js";
2
+ import { __require as requireFastDeepEqual } from "../node_modules/fast-deep-equal/index.js";
3
+ var fastDeepEqualExports = requireFastDeepEqual();
4
+ const isEqual = /* @__PURE__ */ getDefaultExportFromCjs(fastDeepEqualExports);
2
5
  export {
3
- propTypes as __module
6
+ isEqual as default
4
7
  };
5
8
  //# sourceMappingURL=index3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
- const _commonjsHelpers = require("./_commonjsHelpers.cjs");
3
- const index = require("../node_modules/fast-deep-equal/index.cjs");
4
- var fastDeepEqualExports = index.__require();
5
- const isEqual = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(fastDeepEqualExports);
6
- module.exports = isEqual;
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ var propTypes = { exports: {} };
4
+ exports.__module = propTypes;
7
5
  //# sourceMappingURL=index4.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index4.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index4.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,8 +1,5 @@
1
- import { getDefaultExportFromCjs } from "./_commonjsHelpers.js";
2
- import { __require as requireFastDeepEqual } from "../node_modules/fast-deep-equal/index.js";
3
- var fastDeepEqualExports = requireFastDeepEqual();
4
- const isEqual = /* @__PURE__ */ getDefaultExportFromCjs(fastDeepEqualExports);
1
+ var propTypes = { exports: {} };
5
2
  export {
6
- isEqual as default
3
+ propTypes as __module
7
4
  };
8
5
  //# sourceMappingURL=index4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -130,7 +130,7 @@ const getBannerLayout = ({
130
130
  desktopContentColumns.push("minmax(0, 1fr)");
131
131
  }
132
132
  if (hasActions) {
133
- desktopContentColumns.push("auto");
133
+ desktopContentColumns.push("max-content");
134
134
  }
135
135
  const mobileRows = [];
136
136
  if (hasIcon && hasTitle) mobileRows.push('"icon title"');
@@ -288,10 +288,11 @@ function Banner({
288
288
  sx: {
289
289
  display: "flex",
290
290
  flexDirection: { base: "column", sm: "row" },
291
- alignItems: "stretch",
291
+ alignItems: { base: "stretch", sm: "center" },
292
292
  justifyContent: "flex-end",
293
293
  gap: spacing.spacing.xs,
294
- minWidth: 0,
294
+ flexShrink: { sm: 0 },
295
+ minWidth: { base: 0, sm: "max-content" },
295
296
  width: { base: "100%", sm: "max-content" },
296
297
  maxWidth: "100%"
297
298
  },
@@ -303,15 +304,16 @@ function Banner({
303
304
  color,
304
305
  size: size ?? "sm",
305
306
  variant: actionVariant(tone, index2 < resolvedActions.length - 1),
306
- style: {
307
- ...buttonProps.style,
307
+ sx: {
308
308
  boxSizing: "border-box",
309
- flex: "0 1 auto",
310
- maxWidth: "100%",
309
+ flex: { base: "0 1 auto", sm: "0 0 auto" },
310
+ maxWidth: { base: "100%", sm: "none" },
311
311
  overflowWrap: "anywhere",
312
- whiteSpace: "normal",
313
- width: "100%"
312
+ whiteSpace: { base: "normal", sm: "nowrap" },
313
+ width: { base: "100%", sm: "auto" },
314
+ ...buttonProps.sx
314
315
  },
316
+ style: buttonProps.style,
315
317
  children: label
316
318
  },
317
319
  buttonProps.id ?? (typeof label === "string" ? label : `banner-action-${index2}`)
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.cjs","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fairmintVars, fontSizes, radii, spacing } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport type BannerActions =\n | readonly [BannerActionProps]\n | readonly [BannerActionProps, BannerActionProps];\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown beside the title. Pass `null` to hide. Default is a 20px tone icon. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Up to two CTAs in visual order: secondary first, primary last. */\n actions?: BannerActions;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst TONE_TOKENS = {\n brand: {\n background: fairmintVars.colorBgBrandSubtle,\n border: fairmintVars.colorBorderFocus,\n icon: fairmintVars.colorBrandPrimary,\n },\n neutral: {\n background: fairmintVars.colorBgSurfaceSecondary,\n border: fairmintVars.colorBorderDefault,\n icon: fairmintVars.colorIconSecondary,\n },\n info: {\n background: fairmintVars.colorInfoBg,\n border: fairmintVars.colorInfoBorder,\n icon: fairmintVars.colorInfoText,\n },\n success: {\n background: fairmintVars.colorSuccessBg,\n border: fairmintVars.colorSuccessBorder,\n icon: fairmintVars.colorSuccessText,\n },\n warning: {\n background: fairmintVars.colorWarningBg,\n border: fairmintVars.colorWarningBorder,\n icon: fairmintVars.colorWarningText,\n },\n error: {\n background: fairmintVars.colorErrorBg,\n border: fairmintVars.colorErrorBorder,\n icon: fairmintVars.colorErrorText,\n },\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const tokens = TONE_TOKENS[tone];\n\n if (presentation === \"page-level\") {\n return {\n style: {\n backgroundColor: tokens.background,\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n return {\n style: {\n backgroundColor: tokens.background,\n border: `1px solid ${tokens.border}`,\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Banner titles always use primary text color regardless of tone or\n * presentation — tinted semantic shades are reserved for the fill/border/icon,\n * keeping title contrast consistent (and WCAG AA) across color schemes.\n */\nconst titleColor = () => fairmintVars.colorTextPrimary;\n\nconst actionVariant = (tone: BannerTone, isSecondary: boolean): ButtonProps[\"variant\"] => {\n if (isSecondary) return \"outline\";\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\ninterface BannerLayoutOptions {\n hasIcon: boolean;\n hasTitle: boolean;\n hasDescription: boolean;\n hasActions: boolean;\n}\n\nconst getBannerLayout = ({\n hasActions,\n hasDescription,\n hasIcon,\n hasTitle,\n}: BannerLayoutOptions) => {\n const mobileColumns = hasIcon ? \"20px minmax(0, 1fr)\" : \"minmax(0, 1fr)\";\n const desktopContentColumns = hasIcon ? [\"20px\"] : [];\n\n if (hasTitle || hasDescription) {\n desktopContentColumns.push(\"minmax(0, 1fr)\");\n }\n\n if (hasActions) {\n desktopContentColumns.push(\"auto\");\n }\n\n const mobileRows: string[] = [];\n if (hasIcon && hasTitle) mobileRows.push('\"icon title\"');\n else if (hasIcon) mobileRows.push('\"icon icon\"');\n else if (hasTitle) mobileRows.push('\"title\"');\n\n if (hasDescription) mobileRows.push(hasIcon ? '\"description description\"' : '\"description\"');\n if (hasActions) mobileRows.push(hasIcon ? '\"actions actions\"' : '\"actions\"');\n\n const desktopRows: string[] = [];\n const actionCell = hasActions ? \" actions\" : \"\";\n if (hasIcon && hasTitle && hasDescription) {\n desktopRows.push(`\"icon title${actionCell}\"`, `\"icon description${actionCell}\"`);\n } else if (hasIcon && hasTitle) {\n desktopRows.push(`\"icon title${actionCell}\"`);\n } else if (hasIcon && hasDescription) {\n desktopRows.push(`\"icon description${actionCell}\"`);\n } else if (hasIcon) {\n desktopRows.push(`\"icon${hasActions ? \" actions\" : \"\"}\"`);\n } else if (hasTitle && hasDescription) {\n desktopRows.push(`\"title${actionCell}\"`, `\"description${actionCell}\"`);\n } else if (hasTitle) {\n desktopRows.push(`\"title${actionCell}\"`);\n } else if (hasDescription) {\n desktopRows.push(`\"description${actionCell}\"`);\n } else if (hasActions) {\n desktopRows.push('\"actions\"');\n }\n\n return {\n gridTemplateAreas: {\n base: mobileRows.join(\" \"),\n sm: desktopRows.join(\" \"),\n },\n gridTemplateColumns: {\n base: mobileColumns,\n sm: desktopContentColumns.join(\" \") || \"auto\",\n },\n };\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: fairmintVars.colorTextSecondary,\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={fairmintVars.colorTextSecondary}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n actions,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const tokens = TONE_TOKENS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedActions = actions ?? (action === undefined ? [] : [action]);\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n const layout = getBannerLayout({\n hasActions: resolvedActions.length > 0,\n hasDescription: description !== undefined,\n hasIcon: iconNode !== null,\n hasTitle: title !== undefined || badgeLabel !== undefined,\n });\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n pl=\"md\"\n pr=\"lg\"\n py=\"md\"\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n sx={{\n display: \"grid\",\n // Match Alert: icon→copy uses spacing.md; title→body is tighter than xs.\n columnGap: spacing.md,\n rowGap: \"0.25rem\",\n ...layout,\n }}\n >\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={20}\n variant=\"transparent\"\n style={{\n color: tokens.icon,\n gridArea: \"icon\",\n // Top-left of the container — matches Alert; stays with the title\n // when description/actions stretch the grid row span.\n alignSelf: \"start\",\n }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n {(title !== undefined || badgeLabel !== undefined) && (\n <Group\n align=\"center\"\n gap=\"xs\"\n wrap=\"wrap\"\n style={{ gridArea: \"title\", minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title !== undefined && (\n <Text\n fw={500}\n size=\"md\"\n c={titleColor()}\n style={{ lineHeight: 1.35, minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n )}\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n\n {description !== undefined && (\n <Box style={{ gridArea: \"description\", minWidth: 0, overflowWrap: \"anywhere\" }}>\n <BannerDescription>{description}</BannerDescription>\n </Box>\n )}\n\n {resolvedActions.length > 0 && (\n <Box\n sx={{\n display: \"flex\",\n flexDirection: { base: \"column\", sm: \"row\" },\n alignItems: \"stretch\",\n justifyContent: \"flex-end\",\n gap: spacing.xs,\n minWidth: 0,\n width: { base: \"100%\", sm: \"max-content\" },\n maxWidth: \"100%\",\n }}\n style={{ gridArea: \"actions\", alignSelf: \"center\", justifySelf: \"end\" }}\n >\n {resolvedActions.map(({ label, size, ...buttonProps }, index) => (\n <Button\n key={buttonProps.id ?? (typeof label === \"string\" ? label : `banner-action-${index}`)}\n {...buttonProps}\n color={color}\n size={size ?? \"sm\"}\n variant={actionVariant(tone, index < resolvedActions.length - 1)}\n style={{\n ...buttonProps.style,\n boxSizing: \"border-box\",\n flex: \"0 1 auto\",\n maxWidth: \"100%\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"normal\",\n width: \"100%\",\n }}\n >\n {label}\n </Button>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n"],"names":["colors","fairmintVars","jsxs","jsx","radii","Text","Box","fontSizes","layout","spacing","ThemeIcon","Group","Badge","index","Button"],"mappings":"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"}
1
+ {"version":3,"file":"Banner.cjs","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fairmintVars, fontSizes, radii, spacing } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport type BannerActions =\n | readonly [BannerActionProps]\n | readonly [BannerActionProps, BannerActionProps];\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown beside the title. Pass `null` to hide. Default is a 20px tone icon. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Up to two CTAs in visual order: secondary first, primary last. */\n actions?: BannerActions;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst TONE_TOKENS = {\n brand: {\n background: fairmintVars.colorBgBrandSubtle,\n border: fairmintVars.colorBorderFocus,\n icon: fairmintVars.colorBrandPrimary,\n },\n neutral: {\n background: fairmintVars.colorBgSurfaceSecondary,\n border: fairmintVars.colorBorderDefault,\n icon: fairmintVars.colorIconSecondary,\n },\n info: {\n background: fairmintVars.colorInfoBg,\n border: fairmintVars.colorInfoBorder,\n icon: fairmintVars.colorInfoText,\n },\n success: {\n background: fairmintVars.colorSuccessBg,\n border: fairmintVars.colorSuccessBorder,\n icon: fairmintVars.colorSuccessText,\n },\n warning: {\n background: fairmintVars.colorWarningBg,\n border: fairmintVars.colorWarningBorder,\n icon: fairmintVars.colorWarningText,\n },\n error: {\n background: fairmintVars.colorErrorBg,\n border: fairmintVars.colorErrorBorder,\n icon: fairmintVars.colorErrorText,\n },\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const tokens = TONE_TOKENS[tone];\n\n if (presentation === \"page-level\") {\n return {\n style: {\n backgroundColor: tokens.background,\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n return {\n style: {\n backgroundColor: tokens.background,\n border: `1px solid ${tokens.border}`,\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Banner titles always use primary text color regardless of tone or\n * presentation — tinted semantic shades are reserved for the fill/border/icon,\n * keeping title contrast consistent (and WCAG AA) across color schemes.\n */\nconst titleColor = () => fairmintVars.colorTextPrimary;\n\nconst actionVariant = (tone: BannerTone, isSecondary: boolean): ButtonProps[\"variant\"] => {\n if (isSecondary) return \"outline\";\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\ninterface BannerLayoutOptions {\n hasIcon: boolean;\n hasTitle: boolean;\n hasDescription: boolean;\n hasActions: boolean;\n}\n\nconst getBannerLayout = ({\n hasActions,\n hasDescription,\n hasIcon,\n hasTitle,\n}: BannerLayoutOptions) => {\n const mobileColumns = hasIcon ? \"20px minmax(0, 1fr)\" : \"minmax(0, 1fr)\";\n const desktopContentColumns = hasIcon ? [\"20px\"] : [];\n\n if (hasTitle || hasDescription) {\n desktopContentColumns.push(\"minmax(0, 1fr)\");\n }\n\n if (hasActions) {\n // max-content keeps the track wide enough for full button labels beside long copy.\n desktopContentColumns.push(\"max-content\");\n }\n\n const mobileRows: string[] = [];\n if (hasIcon && hasTitle) mobileRows.push('\"icon title\"');\n else if (hasIcon) mobileRows.push('\"icon icon\"');\n else if (hasTitle) mobileRows.push('\"title\"');\n\n if (hasDescription) mobileRows.push(hasIcon ? '\"description description\"' : '\"description\"');\n if (hasActions) mobileRows.push(hasIcon ? '\"actions actions\"' : '\"actions\"');\n\n const desktopRows: string[] = [];\n const actionCell = hasActions ? \" actions\" : \"\";\n if (hasIcon && hasTitle && hasDescription) {\n desktopRows.push(`\"icon title${actionCell}\"`, `\"icon description${actionCell}\"`);\n } else if (hasIcon && hasTitle) {\n desktopRows.push(`\"icon title${actionCell}\"`);\n } else if (hasIcon && hasDescription) {\n desktopRows.push(`\"icon description${actionCell}\"`);\n } else if (hasIcon) {\n desktopRows.push(`\"icon${hasActions ? \" actions\" : \"\"}\"`);\n } else if (hasTitle && hasDescription) {\n desktopRows.push(`\"title${actionCell}\"`, `\"description${actionCell}\"`);\n } else if (hasTitle) {\n desktopRows.push(`\"title${actionCell}\"`);\n } else if (hasDescription) {\n desktopRows.push(`\"description${actionCell}\"`);\n } else if (hasActions) {\n desktopRows.push('\"actions\"');\n }\n\n return {\n gridTemplateAreas: {\n base: mobileRows.join(\" \"),\n sm: desktopRows.join(\" \"),\n },\n gridTemplateColumns: {\n base: mobileColumns,\n sm: desktopContentColumns.join(\" \") || \"auto\",\n },\n };\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: fairmintVars.colorTextSecondary,\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={fairmintVars.colorTextSecondary}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n actions,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const tokens = TONE_TOKENS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedActions = actions ?? (action === undefined ? [] : [action]);\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n const layout = getBannerLayout({\n hasActions: resolvedActions.length > 0,\n hasDescription: description !== undefined,\n hasIcon: iconNode !== null,\n hasTitle: title !== undefined || badgeLabel !== undefined,\n });\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n pl=\"md\"\n pr=\"lg\"\n py=\"md\"\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n sx={{\n display: \"grid\",\n // Match Alert: icon→copy uses spacing.md; title→body is tighter than xs.\n columnGap: spacing.md,\n rowGap: \"0.25rem\",\n ...layout,\n }}\n >\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={20}\n variant=\"transparent\"\n style={{\n color: tokens.icon,\n gridArea: \"icon\",\n // Top-left of the container — matches Alert; stays with the title\n // when description/actions stretch the grid row span.\n alignSelf: \"start\",\n }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n {(title !== undefined || badgeLabel !== undefined) && (\n <Group\n align=\"center\"\n gap=\"xs\"\n wrap=\"wrap\"\n style={{ gridArea: \"title\", minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title !== undefined && (\n <Text\n fw={500}\n size=\"md\"\n c={titleColor()}\n style={{ lineHeight: 1.35, minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n )}\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n\n {description !== undefined && (\n <Box style={{ gridArea: \"description\", minWidth: 0, overflowWrap: \"anywhere\" }}>\n <BannerDescription>{description}</BannerDescription>\n </Box>\n )}\n\n {resolvedActions.length > 0 && (\n <Box\n sx={{\n display: \"flex\",\n flexDirection: { base: \"column\", sm: \"row\" },\n alignItems: { base: \"stretch\", sm: \"center\" },\n justifyContent: \"flex-end\",\n gap: spacing.xs,\n flexShrink: { sm: 0 },\n minWidth: { base: 0, sm: \"max-content\" },\n width: { base: \"100%\", sm: \"max-content\" },\n maxWidth: \"100%\",\n }}\n style={{ gridArea: \"actions\", alignSelf: \"center\", justifySelf: \"end\" }}\n >\n {resolvedActions.map(({ label, size, ...buttonProps }, index) => (\n <Button\n key={buttonProps.id ?? (typeof label === \"string\" ? label : `banner-action-${index}`)}\n {...buttonProps}\n color={color}\n size={size ?? \"sm\"}\n variant={actionVariant(tone, index < resolvedActions.length - 1)}\n sx={{\n boxSizing: \"border-box\",\n flex: { base: \"0 1 auto\", sm: \"0 0 auto\" },\n maxWidth: { base: \"100%\", sm: \"none\" },\n overflowWrap: \"anywhere\",\n whiteSpace: { base: \"normal\", sm: \"nowrap\" },\n width: { base: \"100%\", sm: \"auto\" },\n ...buttonProps.sx,\n }}\n style={buttonProps.style}\n >\n {label}\n </Button>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n"],"names":["colors","fairmintVars","jsxs","jsx","radii","Text","Box","fontSizes","layout","spacing","ThemeIcon","Group","Badge","index","Button"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIhE,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AACxF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5F,4BAA4B;IAC5B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GACrB,SAAS,CAAC,iBAAiB,CAAC,GAC5B,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,oGAAoG;IACpG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,qFAAqF;IACrF,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,qEAAqE;IACrE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,6FAA6F;IAC7F,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AA8ND;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAuB,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAc,GACf,EAAE,WAAW,+BA+Hb"}
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIhE,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG1E,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AACxF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5F,4BAA4B;IAC5B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GACrB,SAAS,CAAC,iBAAiB,CAAC,GAC5B,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,oGAAoG;IACpG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,qFAAqF;IACrF,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,qEAAqE;IACrE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,6FAA6F;IAC7F,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AA+ND;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,OAAO,EACP,YAAuB,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAc,GACf,EAAE,WAAW,+BAiIb"}
@@ -128,7 +128,7 @@ const getBannerLayout = ({
128
128
  desktopContentColumns.push("minmax(0, 1fr)");
129
129
  }
130
130
  if (hasActions) {
131
- desktopContentColumns.push("auto");
131
+ desktopContentColumns.push("max-content");
132
132
  }
133
133
  const mobileRows = [];
134
134
  if (hasIcon && hasTitle) mobileRows.push('"icon title"');
@@ -286,10 +286,11 @@ function Banner({
286
286
  sx: {
287
287
  display: "flex",
288
288
  flexDirection: { base: "column", sm: "row" },
289
- alignItems: "stretch",
289
+ alignItems: { base: "stretch", sm: "center" },
290
290
  justifyContent: "flex-end",
291
291
  gap: spacing.xs,
292
- minWidth: 0,
292
+ flexShrink: { sm: 0 },
293
+ minWidth: { base: 0, sm: "max-content" },
293
294
  width: { base: "100%", sm: "max-content" },
294
295
  maxWidth: "100%"
295
296
  },
@@ -301,15 +302,16 @@ function Banner({
301
302
  color,
302
303
  size: size ?? "sm",
303
304
  variant: actionVariant(tone, index < resolvedActions.length - 1),
304
- style: {
305
- ...buttonProps.style,
305
+ sx: {
306
306
  boxSizing: "border-box",
307
- flex: "0 1 auto",
308
- maxWidth: "100%",
307
+ flex: { base: "0 1 auto", sm: "0 0 auto" },
308
+ maxWidth: { base: "100%", sm: "none" },
309
309
  overflowWrap: "anywhere",
310
- whiteSpace: "normal",
311
- width: "100%"
310
+ whiteSpace: { base: "normal", sm: "nowrap" },
311
+ width: { base: "100%", sm: "auto" },
312
+ ...buttonProps.sx
312
313
  },
314
+ style: buttonProps.style,
313
315
  children: label
314
316
  },
315
317
  buttonProps.id ?? (typeof label === "string" ? label : `banner-action-${index}`)
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fairmintVars, fontSizes, radii, spacing } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport type BannerActions =\n | readonly [BannerActionProps]\n | readonly [BannerActionProps, BannerActionProps];\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown beside the title. Pass `null` to hide. Default is a 20px tone icon. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Up to two CTAs in visual order: secondary first, primary last. */\n actions?: BannerActions;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst TONE_TOKENS = {\n brand: {\n background: fairmintVars.colorBgBrandSubtle,\n border: fairmintVars.colorBorderFocus,\n icon: fairmintVars.colorBrandPrimary,\n },\n neutral: {\n background: fairmintVars.colorBgSurfaceSecondary,\n border: fairmintVars.colorBorderDefault,\n icon: fairmintVars.colorIconSecondary,\n },\n info: {\n background: fairmintVars.colorInfoBg,\n border: fairmintVars.colorInfoBorder,\n icon: fairmintVars.colorInfoText,\n },\n success: {\n background: fairmintVars.colorSuccessBg,\n border: fairmintVars.colorSuccessBorder,\n icon: fairmintVars.colorSuccessText,\n },\n warning: {\n background: fairmintVars.colorWarningBg,\n border: fairmintVars.colorWarningBorder,\n icon: fairmintVars.colorWarningText,\n },\n error: {\n background: fairmintVars.colorErrorBg,\n border: fairmintVars.colorErrorBorder,\n icon: fairmintVars.colorErrorText,\n },\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const tokens = TONE_TOKENS[tone];\n\n if (presentation === \"page-level\") {\n return {\n style: {\n backgroundColor: tokens.background,\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n return {\n style: {\n backgroundColor: tokens.background,\n border: `1px solid ${tokens.border}`,\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Banner titles always use primary text color regardless of tone or\n * presentation — tinted semantic shades are reserved for the fill/border/icon,\n * keeping title contrast consistent (and WCAG AA) across color schemes.\n */\nconst titleColor = () => fairmintVars.colorTextPrimary;\n\nconst actionVariant = (tone: BannerTone, isSecondary: boolean): ButtonProps[\"variant\"] => {\n if (isSecondary) return \"outline\";\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\ninterface BannerLayoutOptions {\n hasIcon: boolean;\n hasTitle: boolean;\n hasDescription: boolean;\n hasActions: boolean;\n}\n\nconst getBannerLayout = ({\n hasActions,\n hasDescription,\n hasIcon,\n hasTitle,\n}: BannerLayoutOptions) => {\n const mobileColumns = hasIcon ? \"20px minmax(0, 1fr)\" : \"minmax(0, 1fr)\";\n const desktopContentColumns = hasIcon ? [\"20px\"] : [];\n\n if (hasTitle || hasDescription) {\n desktopContentColumns.push(\"minmax(0, 1fr)\");\n }\n\n if (hasActions) {\n desktopContentColumns.push(\"auto\");\n }\n\n const mobileRows: string[] = [];\n if (hasIcon && hasTitle) mobileRows.push('\"icon title\"');\n else if (hasIcon) mobileRows.push('\"icon icon\"');\n else if (hasTitle) mobileRows.push('\"title\"');\n\n if (hasDescription) mobileRows.push(hasIcon ? '\"description description\"' : '\"description\"');\n if (hasActions) mobileRows.push(hasIcon ? '\"actions actions\"' : '\"actions\"');\n\n const desktopRows: string[] = [];\n const actionCell = hasActions ? \" actions\" : \"\";\n if (hasIcon && hasTitle && hasDescription) {\n desktopRows.push(`\"icon title${actionCell}\"`, `\"icon description${actionCell}\"`);\n } else if (hasIcon && hasTitle) {\n desktopRows.push(`\"icon title${actionCell}\"`);\n } else if (hasIcon && hasDescription) {\n desktopRows.push(`\"icon description${actionCell}\"`);\n } else if (hasIcon) {\n desktopRows.push(`\"icon${hasActions ? \" actions\" : \"\"}\"`);\n } else if (hasTitle && hasDescription) {\n desktopRows.push(`\"title${actionCell}\"`, `\"description${actionCell}\"`);\n } else if (hasTitle) {\n desktopRows.push(`\"title${actionCell}\"`);\n } else if (hasDescription) {\n desktopRows.push(`\"description${actionCell}\"`);\n } else if (hasActions) {\n desktopRows.push('\"actions\"');\n }\n\n return {\n gridTemplateAreas: {\n base: mobileRows.join(\" \"),\n sm: desktopRows.join(\" \"),\n },\n gridTemplateColumns: {\n base: mobileColumns,\n sm: desktopContentColumns.join(\" \") || \"auto\",\n },\n };\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: fairmintVars.colorTextSecondary,\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={fairmintVars.colorTextSecondary}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n actions,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const tokens = TONE_TOKENS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedActions = actions ?? (action === undefined ? [] : [action]);\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n const layout = getBannerLayout({\n hasActions: resolvedActions.length > 0,\n hasDescription: description !== undefined,\n hasIcon: iconNode !== null,\n hasTitle: title !== undefined || badgeLabel !== undefined,\n });\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n pl=\"md\"\n pr=\"lg\"\n py=\"md\"\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n sx={{\n display: \"grid\",\n // Match Alert: icon→copy uses spacing.md; title→body is tighter than xs.\n columnGap: spacing.md,\n rowGap: \"0.25rem\",\n ...layout,\n }}\n >\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={20}\n variant=\"transparent\"\n style={{\n color: tokens.icon,\n gridArea: \"icon\",\n // Top-left of the container — matches Alert; stays with the title\n // when description/actions stretch the grid row span.\n alignSelf: \"start\",\n }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n {(title !== undefined || badgeLabel !== undefined) && (\n <Group\n align=\"center\"\n gap=\"xs\"\n wrap=\"wrap\"\n style={{ gridArea: \"title\", minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title !== undefined && (\n <Text\n fw={500}\n size=\"md\"\n c={titleColor()}\n style={{ lineHeight: 1.35, minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n )}\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n\n {description !== undefined && (\n <Box style={{ gridArea: \"description\", minWidth: 0, overflowWrap: \"anywhere\" }}>\n <BannerDescription>{description}</BannerDescription>\n </Box>\n )}\n\n {resolvedActions.length > 0 && (\n <Box\n sx={{\n display: \"flex\",\n flexDirection: { base: \"column\", sm: \"row\" },\n alignItems: \"stretch\",\n justifyContent: \"flex-end\",\n gap: spacing.xs,\n minWidth: 0,\n width: { base: \"100%\", sm: \"max-content\" },\n maxWidth: \"100%\",\n }}\n style={{ gridArea: \"actions\", alignSelf: \"center\", justifySelf: \"end\" }}\n >\n {resolvedActions.map(({ label, size, ...buttonProps }, index) => (\n <Button\n key={buttonProps.id ?? (typeof label === \"string\" ? label : `banner-action-${index}`)}\n {...buttonProps}\n color={color}\n size={size ?? \"sm\"}\n variant={actionVariant(tone, index < resolvedActions.length - 1)}\n style={{\n ...buttonProps.style,\n boxSizing: \"border-box\",\n flex: \"0 1 auto\",\n maxWidth: \"100%\",\n overflowWrap: \"anywhere\",\n whiteSpace: \"normal\",\n width: \"100%\",\n }}\n >\n {label}\n </Button>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Banner.js","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fairmintVars, fontSizes, radii, spacing } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Text, ThemeIcon } from \"../../primitives/layout\";\n\nexport type BannerTone = \"brand\" | \"neutral\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type BannerPresentation = \"inline\" | \"page-level\";\n\nexport interface BannerActionProps extends Omit<ButtonProps, \"children\" | \"color\" | \"variant\"> {\n /** Visible action label. */\n label: ReactNode;\n}\n\nexport type BannerActions =\n | readonly [BannerActionProps]\n | readonly [BannerActionProps, BannerActionProps];\n\nexport interface BannerProps {\n /** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */\n title?: ReactNode;\n /** Supporting context. Omit for a title-only banner. */\n description?: ReactNode;\n /** Semantic meaning and visual treatment. @default \"brand\" */\n tone?: BannerTone;\n /** Inline content callout or full-width page-edge treatment. @default \"inline\" */\n presentation?: BannerPresentation;\n /** Icon shown beside the title. Pass `null` to hide. Default is a 20px tone icon. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\n /** Up to two CTAs in visual order: secondary first, primary last. */\n actions?: BannerActions;\n /** Override the default accessible role. Error defaults to alert; other tones use status. */\n role?: AriaRole;\n /** Accessible label for the banner region. Defaults to the string title when possible. */\n ariaLabel?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst TONE_COLORS = {\n brand: colors.primary,\n neutral: colors.neutral,\n info: colors.info,\n success: colors.success,\n warning: colors.warning,\n error: colors.error,\n} as const;\n\nconst TONE_TOKENS = {\n brand: {\n background: fairmintVars.colorBgBrandSubtle,\n border: fairmintVars.colorBorderFocus,\n icon: fairmintVars.colorBrandPrimary,\n },\n neutral: {\n background: fairmintVars.colorBgSurfaceSecondary,\n border: fairmintVars.colorBorderDefault,\n icon: fairmintVars.colorIconSecondary,\n },\n info: {\n background: fairmintVars.colorInfoBg,\n border: fairmintVars.colorInfoBorder,\n icon: fairmintVars.colorInfoText,\n },\n success: {\n background: fairmintVars.colorSuccessBg,\n border: fairmintVars.colorSuccessBorder,\n icon: fairmintVars.colorSuccessText,\n },\n warning: {\n background: fairmintVars.colorWarningBg,\n border: fairmintVars.colorWarningBorder,\n icon: fairmintVars.colorWarningText,\n },\n error: {\n background: fairmintVars.colorErrorBg,\n border: fairmintVars.colorErrorBorder,\n icon: fairmintVars.colorErrorText,\n },\n} as const;\n\nconst DefaultStatusIcon = ({ tone }: { tone: BannerTone }) => {\n const commonProps = {\n width: 20,\n height: 20,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.75,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n \"aria-hidden\": true,\n };\n\n if (tone === \"success\") {\n return (\n <svg {...commonProps}>\n <title>Success</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12 2.25 2.25L15.75 9\" />\n </svg>\n );\n }\n\n if (tone === \"warning\") {\n return (\n <svg {...commonProps}>\n <title>Warning</title>\n <path d=\"M10.3 4.2 2.6 18a2 2 0 0 0 1.75 3h15.3a2 2 0 0 0 1.75-3L13.7 4.2a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n }\n\n if (tone === \"error\") {\n return (\n <svg {...commonProps}>\n <title>Error</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m9 9 6 6\" />\n <path d=\"m15 9-6 6\" />\n </svg>\n );\n }\n\n return (\n <svg {...commonProps}>\n <title>Information</title>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 11v5\" />\n <path d=\"M12 8h.01\" />\n </svg>\n );\n};\n\nconst surfaceProps = (tone: BannerTone, presentation: BannerPresentation) => {\n const tokens = TONE_TOKENS[tone];\n\n if (presentation === \"page-level\") {\n return {\n style: {\n backgroundColor: tokens.background,\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n return {\n style: {\n backgroundColor: tokens.background,\n border: `1px solid ${tokens.border}`,\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Banner titles always use primary text color regardless of tone or\n * presentation — tinted semantic shades are reserved for the fill/border/icon,\n * keeping title contrast consistent (and WCAG AA) across color schemes.\n */\nconst titleColor = () => fairmintVars.colorTextPrimary;\n\nconst actionVariant = (tone: BannerTone, isSecondary: boolean): ButtonProps[\"variant\"] => {\n if (isSecondary) return \"outline\";\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\ninterface BannerLayoutOptions {\n hasIcon: boolean;\n hasTitle: boolean;\n hasDescription: boolean;\n hasActions: boolean;\n}\n\nconst getBannerLayout = ({\n hasActions,\n hasDescription,\n hasIcon,\n hasTitle,\n}: BannerLayoutOptions) => {\n const mobileColumns = hasIcon ? \"20px minmax(0, 1fr)\" : \"minmax(0, 1fr)\";\n const desktopContentColumns = hasIcon ? [\"20px\"] : [];\n\n if (hasTitle || hasDescription) {\n desktopContentColumns.push(\"minmax(0, 1fr)\");\n }\n\n if (hasActions) {\n // max-content keeps the track wide enough for full button labels beside long copy.\n desktopContentColumns.push(\"max-content\");\n }\n\n const mobileRows: string[] = [];\n if (hasIcon && hasTitle) mobileRows.push('\"icon title\"');\n else if (hasIcon) mobileRows.push('\"icon icon\"');\n else if (hasTitle) mobileRows.push('\"title\"');\n\n if (hasDescription) mobileRows.push(hasIcon ? '\"description description\"' : '\"description\"');\n if (hasActions) mobileRows.push(hasIcon ? '\"actions actions\"' : '\"actions\"');\n\n const desktopRows: string[] = [];\n const actionCell = hasActions ? \" actions\" : \"\";\n if (hasIcon && hasTitle && hasDescription) {\n desktopRows.push(`\"icon title${actionCell}\"`, `\"icon description${actionCell}\"`);\n } else if (hasIcon && hasTitle) {\n desktopRows.push(`\"icon title${actionCell}\"`);\n } else if (hasIcon && hasDescription) {\n desktopRows.push(`\"icon description${actionCell}\"`);\n } else if (hasIcon) {\n desktopRows.push(`\"icon${hasActions ? \" actions\" : \"\"}\"`);\n } else if (hasTitle && hasDescription) {\n desktopRows.push(`\"title${actionCell}\"`, `\"description${actionCell}\"`);\n } else if (hasTitle) {\n desktopRows.push(`\"title${actionCell}\"`);\n } else if (hasDescription) {\n desktopRows.push(`\"description${actionCell}\"`);\n } else if (hasActions) {\n desktopRows.push('\"actions\"');\n }\n\n return {\n gridTemplateAreas: {\n base: mobileRows.join(\" \"),\n sm: desktopRows.join(\" \"),\n },\n gridTemplateColumns: {\n base: mobileColumns,\n sm: desktopContentColumns.join(\" \") || \"auto\",\n },\n };\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: fairmintVars.colorTextSecondary,\n style: { lineHeight: 1.4 },\n};\n\nfunction BannerDescription({ children }: { children: ReactNode }) {\n if (typeof children === \"string\" || typeof children === \"number\") {\n return <Text {...descriptionTextProps}>{children}</Text>;\n }\n\n return (\n <Box\n c={fairmintVars.colorTextSecondary}\n style={{\n fontSize: fontSizes.sm,\n lineHeight: 1.4,\n }}\n >\n {children}\n </Box>\n );\n}\n\n/**\n * Persistent contextual guidance with semantic inline and page-level presentations.\n * Position page-level banners in the consuming layout; the component does not use fixed positioning.\n */\nexport function Banner({\n action,\n ariaLabel,\n badgeLabel,\n className,\n description,\n icon,\n actions,\n presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const tokens = TONE_TOKENS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedActions = actions ?? (action === undefined ? [] : [action]);\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n const layout = getBannerLayout({\n hasActions: resolvedActions.length > 0,\n hasDescription: description !== undefined,\n hasIcon: iconNode !== null,\n hasTitle: title !== undefined || badgeLabel !== undefined,\n });\n\n return (\n <Box\n aria-label={resolvedAriaLabel}\n className={className}\n data-presentation={presentation}\n data-tone={tone}\n role={resolvedRole}\n pl=\"md\"\n pr=\"lg\"\n py=\"md\"\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n sx={{\n display: \"grid\",\n // Match Alert: icon→copy uses spacing.md; title→body is tighter than xs.\n columnGap: spacing.md,\n rowGap: \"0.25rem\",\n ...layout,\n }}\n >\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={20}\n variant=\"transparent\"\n style={{\n color: tokens.icon,\n gridArea: \"icon\",\n // Top-left of the container — matches Alert; stays with the title\n // when description/actions stretch the grid row span.\n alignSelf: \"start\",\n }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n {(title !== undefined || badgeLabel !== undefined) && (\n <Group\n align=\"center\"\n gap=\"xs\"\n wrap=\"wrap\"\n style={{ gridArea: \"title\", minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title !== undefined && (\n <Text\n fw={500}\n size=\"md\"\n c={titleColor()}\n style={{ lineHeight: 1.35, minWidth: 0, overflowWrap: \"anywhere\" }}\n >\n {title}\n </Text>\n )}\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n\n {description !== undefined && (\n <Box style={{ gridArea: \"description\", minWidth: 0, overflowWrap: \"anywhere\" }}>\n <BannerDescription>{description}</BannerDescription>\n </Box>\n )}\n\n {resolvedActions.length > 0 && (\n <Box\n sx={{\n display: \"flex\",\n flexDirection: { base: \"column\", sm: \"row\" },\n alignItems: { base: \"stretch\", sm: \"center\" },\n justifyContent: \"flex-end\",\n gap: spacing.xs,\n flexShrink: { sm: 0 },\n minWidth: { base: 0, sm: \"max-content\" },\n width: { base: \"100%\", sm: \"max-content\" },\n maxWidth: \"100%\",\n }}\n style={{ gridArea: \"actions\", alignSelf: \"center\", justifySelf: \"end\" }}\n >\n {resolvedActions.map(({ label, size, ...buttonProps }, index) => (\n <Button\n key={buttonProps.id ?? (typeof label === \"string\" ? label : `banner-action-${index}`)}\n {...buttonProps}\n color={color}\n size={size ?? \"sm\"}\n variant={actionVariant(tone, index < resolvedActions.length - 1)}\n sx={{\n boxSizing: \"border-box\",\n flex: { base: \"0 1 auto\", sm: \"0 0 auto\" },\n maxWidth: { base: \"100%\", sm: \"none\" },\n overflowWrap: \"anywhere\",\n whiteSpace: { base: \"normal\", sm: \"nowrap\" },\n width: { base: \"100%\", sm: \"auto\" },\n ...buttonProps.sx,\n }}\n style={buttonProps.style}\n >\n {label}\n </Button>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -94,12 +94,16 @@ function StepProgress({
94
94
  // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.
95
95
  "--fairmint-step-progress-surface-selected": index.fairmintVars.colorBgBrandSubtleHover,
96
96
  "--fairmint-step-progress-active-border": index.indigoColors[3],
97
- "--fairmint-step-progress-active-indicator-text": index.commonColors.white,
97
+ // Not brand indigo: no ink clears AA on it. Both follow the scheme, giving white on
98
+ // indigo[6] (6.29:1) in light and dark ink on indigo[2] (11.8:1) in dark.
99
+ "--fairmint-step-progress-active-indicator": index.fairmintVars.colorIconOnSurfaceSelected,
100
+ "--fairmint-step-progress-active-indicator-text": index.fairmintVars.colorTextInverse,
98
101
  "--fairmint-step-progress-complete-border": index.indigoColors[3],
99
102
  "--fairmint-step-progress-complete-text": index.fairmintVars.colorIconOnSurfaceSelected,
100
103
  // The detail line is the one place that needs muted ink; pending labels above it stay primary.
101
104
  "--fairmint-step-progress-detail": index.fairmintVars.colorTextSecondary,
102
105
  "--fairmint-step-progress-stopped": index.fairmintVars.colorErrorSolid,
106
+ "--fairmint-step-progress-stopped-indicator-text": index.commonColors.white,
103
107
  "--fairmint-step-progress-stopped-text": index.fairmintVars.colorErrorText,
104
108
  // Status rows lay out as a grid; the last column never stretches, so it stays flush right.
105
109
  "--fairmint-step-progress-columns": steps.length > 1 ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)` : "minmax(min-content, max-content)"
@@ -1 +1 @@
1
- {"version":3,"file":"StepProgress.cjs","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { brandColors, commonColors, fairmintVars, indigoColors } from \"../../../theme\";\nimport { Box, UnstyledButton } from \"../../primitives/layout\";\nimport \"./StepProgress.css\";\n\nexport type StepProgressOrientation = \"horizontal\" | \"vertical\";\nexport type StepProgressVariant = \"navigation\" | \"status\";\nexport type StepProgressStepStatus = \"complete\" | \"active\" | \"pending\" | \"stopped\";\n\nexport interface StepProgressStep {\n /** Visible label in the progress pill. */\n label: string;\n /** Explicitly mark a step complete when completion is not derived from activeStep. */\n completed?: boolean;\n /** Prevent navigation to this step when onStepChange is supplied. */\n disabled?: boolean;\n /** Second line under the label, such as when the step happened. Shown by the status variant only. */\n detail?: string;\n /** The record stopped at this step (rejected, failed, cancelled). Shown by the status variant only. */\n stopped?: boolean;\n}\n\nexport interface StepProgressProps {\n /** Ordered steps. The visible number is derived from this array and is 1-indexed. */\n steps: readonly StepProgressStep[];\n /** Current step number. This is intentionally 1-indexed to match StepCard and the UI. */\n activeStep: number;\n /** Row of pills for in-app progress or a rail for onboarding. @default \"horizontal\" */\n orientation?: StepProgressOrientation;\n /**\n * `navigation` is where the user is in a flow they are filling in. `status` is where a\n * record is in its lifecycle: read-only, no pill, and each step can carry a `detail`.\n * @default \"navigation\"\n */\n variant?: StepProgressVariant;\n /** Called with the 1-indexed step number when a pill is activated. Ignored by the status variant. */\n onStepChange?: (step: number) => void;\n /** Accessible label for the navigation. @default \"Progress\" */\n ariaLabel?: string;\n}\n\nconst CheckIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m5 13 4 4 10-10\" />\n </svg>\n);\n\nconst StopIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M7 7l10 10M17 7 7 17\" />\n </svg>\n);\n\nconst STATUS_TEXT: Readonly<Record<StepProgressStepStatus, string | undefined>> = {\n complete: \"(done)\",\n active: undefined,\n pending: undefined,\n stopped: \"(stopped)\",\n};\n\nconst resolveActiveStep = (activeStep: number, stepCount: number) => {\n if (!Number.isFinite(activeStep)) return 1;\n return Math.min(Math.max(Math.trunc(activeStep), 1), stepCount);\n};\n\nexport const getStepProgressStatus = (\n step: StepProgressStep,\n stepNumber: number,\n activeStep: number,\n variant: StepProgressVariant = \"navigation\",\n): StepProgressStepStatus => {\n if (variant === \"status\") {\n if (step.stopped) return \"stopped\";\n // A finished record has no current step: its last step is done, not in progress.\n if (step.completed) return \"complete\";\n }\n if (stepNumber === activeStep) return \"active\";\n if (step.completed ?? stepNumber < activeStep) return \"complete\";\n return \"pending\";\n};\n\n/**\n * Numbered progress pills shared by horizontal in-app flows and vertical\n * onboarding rails. Owns navigation only — the numbered content container is\n * `StepCard`, and `StepFlow` pairs the two into the canonical shell.\n *\n * The `status` variant reuses the same anatomy as a read-only lifecycle track,\n * so a record's progress and a flow's progress look like one component.\n */\nexport function StepProgress({\n steps,\n activeStep,\n orientation = \"horizontal\",\n variant = \"navigation\",\n onStepChange,\n ariaLabel = \"Progress\",\n}: StepProgressProps) {\n const listRef = useRef<HTMLOListElement>(null);\n const resolvedActiveStep = resolveActiveStep(activeStep, Math.max(steps.length, 1));\n\n // When the row scrolls, keep the current step in view as it changes. Scrolls the\n // list only — scrollIntoView would also move the page to the progress row.\n useEffect(() => {\n const list = listRef.current;\n const pill = list?.children[resolvedActiveStep - 1]?.querySelector<HTMLElement>(\n \".fairmint-step-progress__pill\",\n );\n if (!list || !pill || list.scrollWidth <= list.clientWidth) return;\n const listBox = list.getBoundingClientRect();\n const pillBox = pill.getBoundingClientRect();\n if (pillBox.left < listBox.left) {\n list.scrollLeft -= listBox.left - pillBox.left;\n } else if (pillBox.right > listBox.right) {\n list.scrollLeft += pillBox.right - listBox.right;\n }\n }, [resolvedActiveStep]);\n\n if (steps.length === 0) return null;\n\n const isStatus = variant === \"status\";\n const rootStyle = {\n \"--fairmint-step-progress-brand\": brandColors.indigo,\n // colorBorderDefault washes out on colorBgSurfaceSecondary; text-secondary clears 3:1.\n \"--fairmint-step-progress-border\": fairmintVars.colorTextSecondary,\n // Kept off the ring token: the ring carries the step number and needs 3:1, the\n // connector is decorative and reads as a hairline between pills.\n \"--fairmint-step-progress-connector\": fairmintVars.colorBorderDefault,\n \"--fairmint-step-progress-text-primary\": fairmintVars.colorTextPrimary,\n // Pending labels use primary ink; active hierarchy is weight + fill, not mute gray.\n \"--fairmint-step-progress-text-secondary\": fairmintVars.colorTextPrimary,\n // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.\n \"--fairmint-step-progress-surface-selected\": fairmintVars.colorBgBrandSubtleHover,\n \"--fairmint-step-progress-active-border\": indigoColors[3],\n \"--fairmint-step-progress-active-indicator-text\": commonColors.white,\n \"--fairmint-step-progress-complete-border\": indigoColors[3],\n \"--fairmint-step-progress-complete-text\": fairmintVars.colorIconOnSurfaceSelected,\n // The detail line is the one place that needs muted ink; pending labels above it stay primary.\n \"--fairmint-step-progress-detail\": fairmintVars.colorTextSecondary,\n \"--fairmint-step-progress-stopped\": fairmintVars.colorErrorSolid,\n \"--fairmint-step-progress-stopped-text\": fairmintVars.colorErrorText,\n // Status rows lay out as a grid; the last column never stretches, so it stays flush right.\n \"--fairmint-step-progress-columns\":\n steps.length > 1\n ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)`\n : \"minmax(min-content, max-content)\",\n };\n\n return (\n <Box\n // A status track is not navigation: nothing in it goes anywhere.\n component={isStatus ? \"div\" : \"nav\"}\n role={isStatus ? \"group\" : undefined}\n aria-label={ariaLabel}\n className=\"fairmint-step-progress\"\n data-orientation={orientation}\n data-variant={variant}\n style={rootStyle}\n >\n <ol ref={listRef} className=\"fairmint-step-progress__list\">\n {steps.map((step, index) => {\n const stepNumber = index + 1;\n const status = getStepProgressStatus(step, stepNumber, resolvedActiveStep, variant);\n const isInteractive = !isStatus && Boolean(onStepChange) && !step.disabled;\n const detail = isStatus ? step.detail : undefined;\n // The indicator icons are aria-hidden, so a status track says done and stopped in words.\n const statusText = isStatus ? STATUS_TEXT[status] : undefined;\n const pillContent = (\n <>\n <span className=\"fairmint-step-progress__indicator\" aria-hidden=\"true\">\n {status === \"complete\" ? (\n <CheckIcon />\n ) : status === \"stopped\" ? (\n <StopIcon />\n ) : (\n stepNumber\n )}\n </span>\n {detail ? (\n <span className=\"fairmint-step-progress__text\">\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n <span className=\"fairmint-step-progress__detail\">{detail}</span>\n </span>\n ) : (\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n )}\n {statusText ? (\n <span className=\"fairmint-step-progress__status-text\">{statusText}</span>\n ) : null}\n </>\n );\n\n return (\n <li key={`${stepNumber}-${step.label}`} className=\"fairmint-step-progress__item\">\n {isInteractive ? (\n <UnstyledButton\n type=\"button\"\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-interactive=\"true\"\n data-disabled=\"false\"\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-label={`Step ${stepNumber}: ${step.label}`}\n onClick={() => onStepChange?.(stepNumber)}\n >\n {pillContent}\n </UnstyledButton>\n ) : (\n <span\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-disabled={step.disabled ? \"true\" : \"false\"}\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-disabled={step.disabled || undefined}\n title={`Step ${stepNumber}: ${step.label}`}\n >\n {pillContent}\n </span>\n )}\n {index < steps.length - 1 ? (\n <span\n className=\"fairmint-step-progress__connector\"\n data-state={status}\n aria-hidden=\"true\"\n />\n ) : null}\n </li>\n );\n })}\n </ol>\n </Box>\n );\n}\n\nexport const STEP_PROGRESS_MOBILE_BREAKPOINT = \"48em\";\n"],"names":["jsx","useRef","useEffect","brandColors","fairmintVars","indigoColors","commonColors","Box","index","jsxs","Fragment","UnstyledButton"],"mappings":"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"}
1
+ {"version":3,"file":"StepProgress.cjs","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { brandColors, commonColors, fairmintVars, indigoColors } from \"../../../theme\";\nimport { Box, UnstyledButton } from \"../../primitives/layout\";\nimport \"./StepProgress.css\";\n\nexport type StepProgressOrientation = \"horizontal\" | \"vertical\";\nexport type StepProgressVariant = \"navigation\" | \"status\";\nexport type StepProgressStepStatus = \"complete\" | \"active\" | \"pending\" | \"stopped\";\n\nexport interface StepProgressStep {\n /** Visible label in the progress pill. */\n label: string;\n /** Explicitly mark a step complete when completion is not derived from activeStep. */\n completed?: boolean;\n /** Prevent navigation to this step when onStepChange is supplied. */\n disabled?: boolean;\n /** Second line under the label, such as when the step happened. Shown by the status variant only. */\n detail?: string;\n /** The record stopped at this step (rejected, failed, cancelled). Shown by the status variant only. */\n stopped?: boolean;\n}\n\nexport interface StepProgressProps {\n /** Ordered steps. The visible number is derived from this array and is 1-indexed. */\n steps: readonly StepProgressStep[];\n /** Current step number. This is intentionally 1-indexed to match StepCard and the UI. */\n activeStep: number;\n /** Row of pills for in-app progress or a rail for onboarding. @default \"horizontal\" */\n orientation?: StepProgressOrientation;\n /**\n * `navigation` is where the user is in a flow they are filling in. `status` is where a\n * record is in its lifecycle: read-only, no pill, and each step can carry a `detail`.\n * @default \"navigation\"\n */\n variant?: StepProgressVariant;\n /** Called with the 1-indexed step number when a pill is activated. Ignored by the status variant. */\n onStepChange?: (step: number) => void;\n /** Accessible label for the navigation. @default \"Progress\" */\n ariaLabel?: string;\n}\n\nconst CheckIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m5 13 4 4 10-10\" />\n </svg>\n);\n\nconst StopIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M7 7l10 10M17 7 7 17\" />\n </svg>\n);\n\nconst STATUS_TEXT: Readonly<Record<StepProgressStepStatus, string | undefined>> = {\n complete: \"(done)\",\n active: undefined,\n pending: undefined,\n stopped: \"(stopped)\",\n};\n\nconst resolveActiveStep = (activeStep: number, stepCount: number) => {\n if (!Number.isFinite(activeStep)) return 1;\n return Math.min(Math.max(Math.trunc(activeStep), 1), stepCount);\n};\n\nexport const getStepProgressStatus = (\n step: StepProgressStep,\n stepNumber: number,\n activeStep: number,\n variant: StepProgressVariant = \"navigation\",\n): StepProgressStepStatus => {\n if (variant === \"status\") {\n if (step.stopped) return \"stopped\";\n // A finished record has no current step: its last step is done, not in progress.\n if (step.completed) return \"complete\";\n }\n if (stepNumber === activeStep) return \"active\";\n if (step.completed ?? stepNumber < activeStep) return \"complete\";\n return \"pending\";\n};\n\n/**\n * Numbered progress pills shared by horizontal in-app flows and vertical\n * onboarding rails. Owns navigation only — the numbered content container is\n * `StepCard`, and `StepFlow` pairs the two into the canonical shell.\n *\n * The `status` variant reuses the same anatomy as a read-only lifecycle track,\n * so a record's progress and a flow's progress look like one component.\n */\nexport function StepProgress({\n steps,\n activeStep,\n orientation = \"horizontal\",\n variant = \"navigation\",\n onStepChange,\n ariaLabel = \"Progress\",\n}: StepProgressProps) {\n const listRef = useRef<HTMLOListElement>(null);\n const resolvedActiveStep = resolveActiveStep(activeStep, Math.max(steps.length, 1));\n\n // When the row scrolls, keep the current step in view as it changes. Scrolls the\n // list only — scrollIntoView would also move the page to the progress row.\n useEffect(() => {\n const list = listRef.current;\n const pill = list?.children[resolvedActiveStep - 1]?.querySelector<HTMLElement>(\n \".fairmint-step-progress__pill\",\n );\n if (!list || !pill || list.scrollWidth <= list.clientWidth) return;\n const listBox = list.getBoundingClientRect();\n const pillBox = pill.getBoundingClientRect();\n if (pillBox.left < listBox.left) {\n list.scrollLeft -= listBox.left - pillBox.left;\n } else if (pillBox.right > listBox.right) {\n list.scrollLeft += pillBox.right - listBox.right;\n }\n }, [resolvedActiveStep]);\n\n if (steps.length === 0) return null;\n\n const isStatus = variant === \"status\";\n const rootStyle = {\n \"--fairmint-step-progress-brand\": brandColors.indigo,\n // colorBorderDefault washes out on colorBgSurfaceSecondary; text-secondary clears 3:1.\n \"--fairmint-step-progress-border\": fairmintVars.colorTextSecondary,\n // Kept off the ring token: the ring carries the step number and needs 3:1, the\n // connector is decorative and reads as a hairline between pills.\n \"--fairmint-step-progress-connector\": fairmintVars.colorBorderDefault,\n \"--fairmint-step-progress-text-primary\": fairmintVars.colorTextPrimary,\n // Pending labels use primary ink; active hierarchy is weight + fill, not mute gray.\n \"--fairmint-step-progress-text-secondary\": fairmintVars.colorTextPrimary,\n // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.\n \"--fairmint-step-progress-surface-selected\": fairmintVars.colorBgBrandSubtleHover,\n \"--fairmint-step-progress-active-border\": indigoColors[3],\n // Not brand indigo: no ink clears AA on it. Both follow the scheme, giving white on\n // indigo[6] (6.29:1) in light and dark ink on indigo[2] (11.8:1) in dark.\n \"--fairmint-step-progress-active-indicator\": fairmintVars.colorIconOnSurfaceSelected,\n \"--fairmint-step-progress-active-indicator-text\": fairmintVars.colorTextInverse,\n \"--fairmint-step-progress-complete-border\": indigoColors[3],\n \"--fairmint-step-progress-complete-text\": fairmintVars.colorIconOnSurfaceSelected,\n // The detail line is the one place that needs muted ink; pending labels above it stay primary.\n \"--fairmint-step-progress-detail\": fairmintVars.colorTextSecondary,\n \"--fairmint-step-progress-stopped\": fairmintVars.colorErrorSolid,\n \"--fairmint-step-progress-stopped-indicator-text\": commonColors.white,\n \"--fairmint-step-progress-stopped-text\": fairmintVars.colorErrorText,\n // Status rows lay out as a grid; the last column never stretches, so it stays flush right.\n \"--fairmint-step-progress-columns\":\n steps.length > 1\n ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)`\n : \"minmax(min-content, max-content)\",\n };\n\n return (\n <Box\n // A status track is not navigation: nothing in it goes anywhere.\n component={isStatus ? \"div\" : \"nav\"}\n role={isStatus ? \"group\" : undefined}\n aria-label={ariaLabel}\n className=\"fairmint-step-progress\"\n data-orientation={orientation}\n data-variant={variant}\n style={rootStyle}\n >\n <ol ref={listRef} className=\"fairmint-step-progress__list\">\n {steps.map((step, index) => {\n const stepNumber = index + 1;\n const status = getStepProgressStatus(step, stepNumber, resolvedActiveStep, variant);\n const isInteractive = !isStatus && Boolean(onStepChange) && !step.disabled;\n const detail = isStatus ? step.detail : undefined;\n // The indicator icons are aria-hidden, so a status track says done and stopped in words.\n const statusText = isStatus ? STATUS_TEXT[status] : undefined;\n const pillContent = (\n <>\n <span className=\"fairmint-step-progress__indicator\" aria-hidden=\"true\">\n {status === \"complete\" ? (\n <CheckIcon />\n ) : status === \"stopped\" ? (\n <StopIcon />\n ) : (\n stepNumber\n )}\n </span>\n {detail ? (\n <span className=\"fairmint-step-progress__text\">\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n <span className=\"fairmint-step-progress__detail\">{detail}</span>\n </span>\n ) : (\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n )}\n {statusText ? (\n <span className=\"fairmint-step-progress__status-text\">{statusText}</span>\n ) : null}\n </>\n );\n\n return (\n <li key={`${stepNumber}-${step.label}`} className=\"fairmint-step-progress__item\">\n {isInteractive ? (\n <UnstyledButton\n type=\"button\"\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-interactive=\"true\"\n data-disabled=\"false\"\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-label={`Step ${stepNumber}: ${step.label}`}\n onClick={() => onStepChange?.(stepNumber)}\n >\n {pillContent}\n </UnstyledButton>\n ) : (\n <span\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-disabled={step.disabled ? \"true\" : \"false\"}\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-disabled={step.disabled || undefined}\n title={`Step ${stepNumber}: ${step.label}`}\n >\n {pillContent}\n </span>\n )}\n {index < steps.length - 1 ? (\n <span\n className=\"fairmint-step-progress__connector\"\n data-state={status}\n aria-hidden=\"true\"\n />\n ) : null}\n </li>\n );\n })}\n </ol>\n </Box>\n );\n}\n\nexport const STEP_PROGRESS_MOBILE_BREAKPOINT = \"48em\";\n"],"names":["jsx","useRef","useEffect","brandColors","fairmintVars","indigoColors","commonColors","Box","index","jsxs","Fragment","UnstyledButton"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"StepProgress.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"names":[],"mappings":"AAGA,OAAO,oBAAoB,CAAC;AAE5B,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,UAAU,CAAC;AAChE,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnF,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnC,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,qGAAqG;IACrG,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8CD,eAAO,MAAM,qBAAqB,GAChC,MAAM,gBAAgB,EACtB,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,UAAS,mBAAkC,KAC1C,sBASF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,UAAU,EACV,WAA0B,EAC1B,OAAsB,EACtB,YAAY,EACZ,SAAsB,GACvB,EAAE,iBAAiB,sCAuInB;AAED,eAAO,MAAM,+BAA+B,SAAS,CAAC"}
1
+ {"version":3,"file":"StepProgress.d.ts","sourceRoot":"","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"names":[],"mappings":"AAGA,OAAO,oBAAoB,CAAC;AAE5B,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,UAAU,CAAC;AAChE,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnF,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACnC,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,qGAAqG;IACrG,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8CD,eAAO,MAAM,qBAAqB,GAChC,MAAM,gBAAgB,EACtB,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,UAAS,mBAAkC,KAC1C,sBASF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,UAAU,EACV,WAA0B,EAC1B,OAAsB,EACtB,YAAY,EACZ,SAAsB,GACvB,EAAE,iBAAiB,sCA2InB;AAED,eAAO,MAAM,+BAA+B,SAAS,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useRef, useEffect } from "react";
3
- import { fairmintVars, indigoColors, commonColors, brandColors } from "../../../theme/index.js";
3
+ import { fairmintVars, commonColors, indigoColors, brandColors } from "../../../theme/index.js";
4
4
  import { Box } from "../../primitives/layout.js";
5
5
  /* empty css */
6
6
  import { UnstyledButton } from "../../../node_modules/@mantine/core/esm/components/UnstyledButton/UnstyledButton.js";
@@ -92,12 +92,16 @@ function StepProgress({
92
92
  // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.
93
93
  "--fairmint-step-progress-surface-selected": fairmintVars.colorBgBrandSubtleHover,
94
94
  "--fairmint-step-progress-active-border": indigoColors[3],
95
- "--fairmint-step-progress-active-indicator-text": commonColors.white,
95
+ // Not brand indigo: no ink clears AA on it. Both follow the scheme, giving white on
96
+ // indigo[6] (6.29:1) in light and dark ink on indigo[2] (11.8:1) in dark.
97
+ "--fairmint-step-progress-active-indicator": fairmintVars.colorIconOnSurfaceSelected,
98
+ "--fairmint-step-progress-active-indicator-text": fairmintVars.colorTextInverse,
96
99
  "--fairmint-step-progress-complete-border": indigoColors[3],
97
100
  "--fairmint-step-progress-complete-text": fairmintVars.colorIconOnSurfaceSelected,
98
101
  // The detail line is the one place that needs muted ink; pending labels above it stay primary.
99
102
  "--fairmint-step-progress-detail": fairmintVars.colorTextSecondary,
100
103
  "--fairmint-step-progress-stopped": fairmintVars.colorErrorSolid,
104
+ "--fairmint-step-progress-stopped-indicator-text": commonColors.white,
101
105
  "--fairmint-step-progress-stopped-text": fairmintVars.colorErrorText,
102
106
  // Status rows lay out as a grid; the last column never stretches, so it stays flush right.
103
107
  "--fairmint-step-progress-columns": steps.length > 1 ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)` : "minmax(min-content, max-content)"
@@ -1 +1 @@
1
- {"version":3,"file":"StepProgress.js","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { brandColors, commonColors, fairmintVars, indigoColors } from \"../../../theme\";\nimport { Box, UnstyledButton } from \"../../primitives/layout\";\nimport \"./StepProgress.css\";\n\nexport type StepProgressOrientation = \"horizontal\" | \"vertical\";\nexport type StepProgressVariant = \"navigation\" | \"status\";\nexport type StepProgressStepStatus = \"complete\" | \"active\" | \"pending\" | \"stopped\";\n\nexport interface StepProgressStep {\n /** Visible label in the progress pill. */\n label: string;\n /** Explicitly mark a step complete when completion is not derived from activeStep. */\n completed?: boolean;\n /** Prevent navigation to this step when onStepChange is supplied. */\n disabled?: boolean;\n /** Second line under the label, such as when the step happened. Shown by the status variant only. */\n detail?: string;\n /** The record stopped at this step (rejected, failed, cancelled). Shown by the status variant only. */\n stopped?: boolean;\n}\n\nexport interface StepProgressProps {\n /** Ordered steps. The visible number is derived from this array and is 1-indexed. */\n steps: readonly StepProgressStep[];\n /** Current step number. This is intentionally 1-indexed to match StepCard and the UI. */\n activeStep: number;\n /** Row of pills for in-app progress or a rail for onboarding. @default \"horizontal\" */\n orientation?: StepProgressOrientation;\n /**\n * `navigation` is where the user is in a flow they are filling in. `status` is where a\n * record is in its lifecycle: read-only, no pill, and each step can carry a `detail`.\n * @default \"navigation\"\n */\n variant?: StepProgressVariant;\n /** Called with the 1-indexed step number when a pill is activated. Ignored by the status variant. */\n onStepChange?: (step: number) => void;\n /** Accessible label for the navigation. @default \"Progress\" */\n ariaLabel?: string;\n}\n\nconst CheckIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m5 13 4 4 10-10\" />\n </svg>\n);\n\nconst StopIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M7 7l10 10M17 7 7 17\" />\n </svg>\n);\n\nconst STATUS_TEXT: Readonly<Record<StepProgressStepStatus, string | undefined>> = {\n complete: \"(done)\",\n active: undefined,\n pending: undefined,\n stopped: \"(stopped)\",\n};\n\nconst resolveActiveStep = (activeStep: number, stepCount: number) => {\n if (!Number.isFinite(activeStep)) return 1;\n return Math.min(Math.max(Math.trunc(activeStep), 1), stepCount);\n};\n\nexport const getStepProgressStatus = (\n step: StepProgressStep,\n stepNumber: number,\n activeStep: number,\n variant: StepProgressVariant = \"navigation\",\n): StepProgressStepStatus => {\n if (variant === \"status\") {\n if (step.stopped) return \"stopped\";\n // A finished record has no current step: its last step is done, not in progress.\n if (step.completed) return \"complete\";\n }\n if (stepNumber === activeStep) return \"active\";\n if (step.completed ?? stepNumber < activeStep) return \"complete\";\n return \"pending\";\n};\n\n/**\n * Numbered progress pills shared by horizontal in-app flows and vertical\n * onboarding rails. Owns navigation only — the numbered content container is\n * `StepCard`, and `StepFlow` pairs the two into the canonical shell.\n *\n * The `status` variant reuses the same anatomy as a read-only lifecycle track,\n * so a record's progress and a flow's progress look like one component.\n */\nexport function StepProgress({\n steps,\n activeStep,\n orientation = \"horizontal\",\n variant = \"navigation\",\n onStepChange,\n ariaLabel = \"Progress\",\n}: StepProgressProps) {\n const listRef = useRef<HTMLOListElement>(null);\n const resolvedActiveStep = resolveActiveStep(activeStep, Math.max(steps.length, 1));\n\n // When the row scrolls, keep the current step in view as it changes. Scrolls the\n // list only — scrollIntoView would also move the page to the progress row.\n useEffect(() => {\n const list = listRef.current;\n const pill = list?.children[resolvedActiveStep - 1]?.querySelector<HTMLElement>(\n \".fairmint-step-progress__pill\",\n );\n if (!list || !pill || list.scrollWidth <= list.clientWidth) return;\n const listBox = list.getBoundingClientRect();\n const pillBox = pill.getBoundingClientRect();\n if (pillBox.left < listBox.left) {\n list.scrollLeft -= listBox.left - pillBox.left;\n } else if (pillBox.right > listBox.right) {\n list.scrollLeft += pillBox.right - listBox.right;\n }\n }, [resolvedActiveStep]);\n\n if (steps.length === 0) return null;\n\n const isStatus = variant === \"status\";\n const rootStyle = {\n \"--fairmint-step-progress-brand\": brandColors.indigo,\n // colorBorderDefault washes out on colorBgSurfaceSecondary; text-secondary clears 3:1.\n \"--fairmint-step-progress-border\": fairmintVars.colorTextSecondary,\n // Kept off the ring token: the ring carries the step number and needs 3:1, the\n // connector is decorative and reads as a hairline between pills.\n \"--fairmint-step-progress-connector\": fairmintVars.colorBorderDefault,\n \"--fairmint-step-progress-text-primary\": fairmintVars.colorTextPrimary,\n // Pending labels use primary ink; active hierarchy is weight + fill, not mute gray.\n \"--fairmint-step-progress-text-secondary\": fairmintVars.colorTextPrimary,\n // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.\n \"--fairmint-step-progress-surface-selected\": fairmintVars.colorBgBrandSubtleHover,\n \"--fairmint-step-progress-active-border\": indigoColors[3],\n \"--fairmint-step-progress-active-indicator-text\": commonColors.white,\n \"--fairmint-step-progress-complete-border\": indigoColors[3],\n \"--fairmint-step-progress-complete-text\": fairmintVars.colorIconOnSurfaceSelected,\n // The detail line is the one place that needs muted ink; pending labels above it stay primary.\n \"--fairmint-step-progress-detail\": fairmintVars.colorTextSecondary,\n \"--fairmint-step-progress-stopped\": fairmintVars.colorErrorSolid,\n \"--fairmint-step-progress-stopped-text\": fairmintVars.colorErrorText,\n // Status rows lay out as a grid; the last column never stretches, so it stays flush right.\n \"--fairmint-step-progress-columns\":\n steps.length > 1\n ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)`\n : \"minmax(min-content, max-content)\",\n };\n\n return (\n <Box\n // A status track is not navigation: nothing in it goes anywhere.\n component={isStatus ? \"div\" : \"nav\"}\n role={isStatus ? \"group\" : undefined}\n aria-label={ariaLabel}\n className=\"fairmint-step-progress\"\n data-orientation={orientation}\n data-variant={variant}\n style={rootStyle}\n >\n <ol ref={listRef} className=\"fairmint-step-progress__list\">\n {steps.map((step, index) => {\n const stepNumber = index + 1;\n const status = getStepProgressStatus(step, stepNumber, resolvedActiveStep, variant);\n const isInteractive = !isStatus && Boolean(onStepChange) && !step.disabled;\n const detail = isStatus ? step.detail : undefined;\n // The indicator icons are aria-hidden, so a status track says done and stopped in words.\n const statusText = isStatus ? STATUS_TEXT[status] : undefined;\n const pillContent = (\n <>\n <span className=\"fairmint-step-progress__indicator\" aria-hidden=\"true\">\n {status === \"complete\" ? (\n <CheckIcon />\n ) : status === \"stopped\" ? (\n <StopIcon />\n ) : (\n stepNumber\n )}\n </span>\n {detail ? (\n <span className=\"fairmint-step-progress__text\">\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n <span className=\"fairmint-step-progress__detail\">{detail}</span>\n </span>\n ) : (\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n )}\n {statusText ? (\n <span className=\"fairmint-step-progress__status-text\">{statusText}</span>\n ) : null}\n </>\n );\n\n return (\n <li key={`${stepNumber}-${step.label}`} className=\"fairmint-step-progress__item\">\n {isInteractive ? (\n <UnstyledButton\n type=\"button\"\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-interactive=\"true\"\n data-disabled=\"false\"\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-label={`Step ${stepNumber}: ${step.label}`}\n onClick={() => onStepChange?.(stepNumber)}\n >\n {pillContent}\n </UnstyledButton>\n ) : (\n <span\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-disabled={step.disabled ? \"true\" : \"false\"}\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-disabled={step.disabled || undefined}\n title={`Step ${stepNumber}: ${step.label}`}\n >\n {pillContent}\n </span>\n )}\n {index < steps.length - 1 ? (\n <span\n className=\"fairmint-step-progress__connector\"\n data-state={status}\n aria-hidden=\"true\"\n />\n ) : null}\n </li>\n );\n })}\n </ol>\n </Box>\n );\n}\n\nexport const STEP_PROGRESS_MOBILE_BREAKPOINT = \"48em\";\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StepProgress.js","sources":["../../../../src/components/generic/StepProgress/StepProgress.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { brandColors, commonColors, fairmintVars, indigoColors } from \"../../../theme\";\nimport { Box, UnstyledButton } from \"../../primitives/layout\";\nimport \"./StepProgress.css\";\n\nexport type StepProgressOrientation = \"horizontal\" | \"vertical\";\nexport type StepProgressVariant = \"navigation\" | \"status\";\nexport type StepProgressStepStatus = \"complete\" | \"active\" | \"pending\" | \"stopped\";\n\nexport interface StepProgressStep {\n /** Visible label in the progress pill. */\n label: string;\n /** Explicitly mark a step complete when completion is not derived from activeStep. */\n completed?: boolean;\n /** Prevent navigation to this step when onStepChange is supplied. */\n disabled?: boolean;\n /** Second line under the label, such as when the step happened. Shown by the status variant only. */\n detail?: string;\n /** The record stopped at this step (rejected, failed, cancelled). Shown by the status variant only. */\n stopped?: boolean;\n}\n\nexport interface StepProgressProps {\n /** Ordered steps. The visible number is derived from this array and is 1-indexed. */\n steps: readonly StepProgressStep[];\n /** Current step number. This is intentionally 1-indexed to match StepCard and the UI. */\n activeStep: number;\n /** Row of pills for in-app progress or a rail for onboarding. @default \"horizontal\" */\n orientation?: StepProgressOrientation;\n /**\n * `navigation` is where the user is in a flow they are filling in. `status` is where a\n * record is in its lifecycle: read-only, no pill, and each step can carry a `detail`.\n * @default \"navigation\"\n */\n variant?: StepProgressVariant;\n /** Called with the 1-indexed step number when a pill is activated. Ignored by the status variant. */\n onStepChange?: (step: number) => void;\n /** Accessible label for the navigation. @default \"Progress\" */\n ariaLabel?: string;\n}\n\nconst CheckIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m5 13 4 4 10-10\" />\n </svg>\n);\n\nconst StopIcon = () => (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M7 7l10 10M17 7 7 17\" />\n </svg>\n);\n\nconst STATUS_TEXT: Readonly<Record<StepProgressStepStatus, string | undefined>> = {\n complete: \"(done)\",\n active: undefined,\n pending: undefined,\n stopped: \"(stopped)\",\n};\n\nconst resolveActiveStep = (activeStep: number, stepCount: number) => {\n if (!Number.isFinite(activeStep)) return 1;\n return Math.min(Math.max(Math.trunc(activeStep), 1), stepCount);\n};\n\nexport const getStepProgressStatus = (\n step: StepProgressStep,\n stepNumber: number,\n activeStep: number,\n variant: StepProgressVariant = \"navigation\",\n): StepProgressStepStatus => {\n if (variant === \"status\") {\n if (step.stopped) return \"stopped\";\n // A finished record has no current step: its last step is done, not in progress.\n if (step.completed) return \"complete\";\n }\n if (stepNumber === activeStep) return \"active\";\n if (step.completed ?? stepNumber < activeStep) return \"complete\";\n return \"pending\";\n};\n\n/**\n * Numbered progress pills shared by horizontal in-app flows and vertical\n * onboarding rails. Owns navigation only — the numbered content container is\n * `StepCard`, and `StepFlow` pairs the two into the canonical shell.\n *\n * The `status` variant reuses the same anatomy as a read-only lifecycle track,\n * so a record's progress and a flow's progress look like one component.\n */\nexport function StepProgress({\n steps,\n activeStep,\n orientation = \"horizontal\",\n variant = \"navigation\",\n onStepChange,\n ariaLabel = \"Progress\",\n}: StepProgressProps) {\n const listRef = useRef<HTMLOListElement>(null);\n const resolvedActiveStep = resolveActiveStep(activeStep, Math.max(steps.length, 1));\n\n // When the row scrolls, keep the current step in view as it changes. Scrolls the\n // list only — scrollIntoView would also move the page to the progress row.\n useEffect(() => {\n const list = listRef.current;\n const pill = list?.children[resolvedActiveStep - 1]?.querySelector<HTMLElement>(\n \".fairmint-step-progress__pill\",\n );\n if (!list || !pill || list.scrollWidth <= list.clientWidth) return;\n const listBox = list.getBoundingClientRect();\n const pillBox = pill.getBoundingClientRect();\n if (pillBox.left < listBox.left) {\n list.scrollLeft -= listBox.left - pillBox.left;\n } else if (pillBox.right > listBox.right) {\n list.scrollLeft += pillBox.right - listBox.right;\n }\n }, [resolvedActiveStep]);\n\n if (steps.length === 0) return null;\n\n const isStatus = variant === \"status\";\n const rootStyle = {\n \"--fairmint-step-progress-brand\": brandColors.indigo,\n // colorBorderDefault washes out on colorBgSurfaceSecondary; text-secondary clears 3:1.\n \"--fairmint-step-progress-border\": fairmintVars.colorTextSecondary,\n // Kept off the ring token: the ring carries the step number and needs 3:1, the\n // connector is decorative and reads as a hairline between pills.\n \"--fairmint-step-progress-connector\": fairmintVars.colorBorderDefault,\n \"--fairmint-step-progress-text-primary\": fairmintVars.colorTextPrimary,\n // Pending labels use primary ink; active hierarchy is weight + fill, not mute gray.\n \"--fairmint-step-progress-text-secondary\": fairmintVars.colorTextPrimary,\n // indigo[1] — surface-selected (indigo[0]) is too close to the secondary canvas.\n \"--fairmint-step-progress-surface-selected\": fairmintVars.colorBgBrandSubtleHover,\n \"--fairmint-step-progress-active-border\": indigoColors[3],\n // Not brand indigo: no ink clears AA on it. Both follow the scheme, giving white on\n // indigo[6] (6.29:1) in light and dark ink on indigo[2] (11.8:1) in dark.\n \"--fairmint-step-progress-active-indicator\": fairmintVars.colorIconOnSurfaceSelected,\n \"--fairmint-step-progress-active-indicator-text\": fairmintVars.colorTextInverse,\n \"--fairmint-step-progress-complete-border\": indigoColors[3],\n \"--fairmint-step-progress-complete-text\": fairmintVars.colorIconOnSurfaceSelected,\n // The detail line is the one place that needs muted ink; pending labels above it stay primary.\n \"--fairmint-step-progress-detail\": fairmintVars.colorTextSecondary,\n \"--fairmint-step-progress-stopped\": fairmintVars.colorErrorSolid,\n \"--fairmint-step-progress-stopped-indicator-text\": commonColors.white,\n \"--fairmint-step-progress-stopped-text\": fairmintVars.colorErrorText,\n // Status rows lay out as a grid; the last column never stretches, so it stays flush right.\n \"--fairmint-step-progress-columns\":\n steps.length > 1\n ? `repeat(${steps.length - 1}, auto) minmax(min-content, max-content)`\n : \"minmax(min-content, max-content)\",\n };\n\n return (\n <Box\n // A status track is not navigation: nothing in it goes anywhere.\n component={isStatus ? \"div\" : \"nav\"}\n role={isStatus ? \"group\" : undefined}\n aria-label={ariaLabel}\n className=\"fairmint-step-progress\"\n data-orientation={orientation}\n data-variant={variant}\n style={rootStyle}\n >\n <ol ref={listRef} className=\"fairmint-step-progress__list\">\n {steps.map((step, index) => {\n const stepNumber = index + 1;\n const status = getStepProgressStatus(step, stepNumber, resolvedActiveStep, variant);\n const isInteractive = !isStatus && Boolean(onStepChange) && !step.disabled;\n const detail = isStatus ? step.detail : undefined;\n // The indicator icons are aria-hidden, so a status track says done and stopped in words.\n const statusText = isStatus ? STATUS_TEXT[status] : undefined;\n const pillContent = (\n <>\n <span className=\"fairmint-step-progress__indicator\" aria-hidden=\"true\">\n {status === \"complete\" ? (\n <CheckIcon />\n ) : status === \"stopped\" ? (\n <StopIcon />\n ) : (\n stepNumber\n )}\n </span>\n {detail ? (\n <span className=\"fairmint-step-progress__text\">\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n <span className=\"fairmint-step-progress__detail\">{detail}</span>\n </span>\n ) : (\n <span className=\"fairmint-step-progress__label\">{step.label}</span>\n )}\n {statusText ? (\n <span className=\"fairmint-step-progress__status-text\">{statusText}</span>\n ) : null}\n </>\n );\n\n return (\n <li key={`${stepNumber}-${step.label}`} className=\"fairmint-step-progress__item\">\n {isInteractive ? (\n <UnstyledButton\n type=\"button\"\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-interactive=\"true\"\n data-disabled=\"false\"\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-label={`Step ${stepNumber}: ${step.label}`}\n onClick={() => onStepChange?.(stepNumber)}\n >\n {pillContent}\n </UnstyledButton>\n ) : (\n <span\n className=\"fairmint-step-progress__pill\"\n data-state={status}\n data-disabled={step.disabled ? \"true\" : \"false\"}\n aria-current={status === \"active\" ? \"step\" : undefined}\n aria-disabled={step.disabled || undefined}\n title={`Step ${stepNumber}: ${step.label}`}\n >\n {pillContent}\n </span>\n )}\n {index < steps.length - 1 ? (\n <span\n className=\"fairmint-step-progress__connector\"\n data-state={status}\n aria-hidden=\"true\"\n />\n ) : null}\n </li>\n );\n })}\n </ol>\n </Box>\n );\n}\n\nexport const STEP_PROGRESS_MOBILE_BREAKPOINT = \"48em\";\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const React = require("react");
4
- const index = require("../../../../../../_virtual/index4.cjs");
4
+ const index = require("../../../../../../_virtual/index3.cjs");
5
5
  const getStatus = require("../../get-status/get-status.cjs");
6
6
  const clearListState = require("../../lists/clear-list-state.cjs");
7
7
  const getPath = require("../../paths/get-path.cjs");
@@ -1,5 +1,5 @@
1
1
  import { useState, useRef, useCallback } from "react";
2
- import isEqual from "../../../../../../_virtual/index4.js";
2
+ import isEqual from "../../../../../../_virtual/index3.js";
3
3
  import { getStatus } from "../../get-status/get-status.js";
4
4
  import { clearListState } from "../../lists/clear-list-state.js";
5
5
  import { getPath } from "../../paths/get-path.js";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index$1 = require("../../_virtual/index3.cjs");
3
+ const index$1 = require("../../_virtual/index4.cjs");
4
4
  const index = require("./node_modules/react-is/index.cjs");
5
5
  const factoryWithTypeCheckers = require("./factoryWithTypeCheckers.cjs");
6
6
  const factoryWithThrowingShims = require("./factoryWithThrowingShims.cjs");
@@ -1,4 +1,4 @@
1
- import { __module as propTypes } from "../../_virtual/index3.js";
1
+ import { __module as propTypes } from "../../_virtual/index4.js";
2
2
  import { __require as requireReactIs } from "./node_modules/react-is/index.js";
3
3
  import { __require as requireFactoryWithTypeCheckers } from "./factoryWithTypeCheckers.js";
4
4
  import { __require as requireFactoryWithThrowingShims } from "./factoryWithThrowingShims.js";
package/dist/styles.css CHANGED
@@ -149,9 +149,14 @@
149
149
  line-height: 1;
150
150
  }
151
151
 
152
+ /*
153
+ * Filled with the completed check's ink rather than the brand: white on brand is
154
+ * 4.47:1, under AA for a number this small. In dark mode the ink turns light, so
155
+ * the number takes the inverse (dark) text color with it.
156
+ */
152
157
  .fairmint-step-progress__pill[data-state="active"] .fairmint-step-progress__indicator {
153
- border-color: var(--fairmint-step-progress-brand, #6366f1);
154
- background: var(--fairmint-step-progress-brand, #6366f1);
158
+ border-color: var(--fairmint-step-progress-active-indicator, #4f46e5);
159
+ background: var(--fairmint-step-progress-active-indicator, #4f46e5);
155
160
  color: var(--fairmint-step-progress-active-indicator-text, #ffffff);
156
161
  }
157
162
 
@@ -395,7 +400,7 @@
395
400
  .fairmint-step-progress__indicator {
396
401
  border-color: var(--fairmint-step-progress-stopped, #e5484d);
397
402
  background: var(--fairmint-step-progress-stopped, #e5484d);
398
- color: var(--fairmint-step-progress-active-indicator-text, #ffffff);
403
+ color: var(--fairmint-step-progress-stopped-indicator-text, #ffffff);
399
404
  }
400
405
 
401
406
  .fairmint-step-progress[data-variant="status"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairmint/ui",
3
- "version": "0.4.18",
3
+ "version": "0.4.20",
4
4
  "type": "module",
5
5
  "description": "Fairmint design system and UI component library",
6
6
  "license": "SEE LICENSE IN LICENSE",