@fairmint/ui 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/index3.cjs +5 -3
- package/dist/_virtual/index3.cjs.map +1 -1
- package/dist/_virtual/index3.js +5 -2
- package/dist/_virtual/index3.js.map +1 -1
- package/dist/_virtual/index4.cjs +3 -5
- package/dist/_virtual/index4.cjs.map +1 -1
- package/dist/_virtual/index4.js +2 -5
- package/dist/_virtual/index4.js.map +1 -1
- package/dist/components/generic/Banner/Banner.cjs +200 -0
- package/dist/components/generic/Banner/Banner.cjs.map +1 -0
- package/dist/components/generic/Banner/Banner.d.ts +36 -0
- package/dist/components/generic/Banner/Banner.d.ts.map +1 -0
- package/dist/components/generic/Banner/Banner.js +200 -0
- package/dist/components/generic/Banner/Banner.js.map +1 -0
- package/dist/components/generic/FileDropzone/FileDropzone.cjs +396 -0
- package/dist/components/generic/FileDropzone/FileDropzone.cjs.map +1 -0
- package/dist/components/generic/FileDropzone/FileDropzone.d.ts +91 -0
- package/dist/components/generic/FileDropzone/FileDropzone.d.ts.map +1 -0
- package/dist/components/generic/FileDropzone/FileDropzone.js +396 -0
- package/dist/components/generic/FileDropzone/FileDropzone.js.map +1 -0
- package/dist/fairmint-ui.cjs +6 -0
- package/dist/fairmint-ui.cjs.map +1 -1
- package/dist/fairmint-ui.js +6 -0
- package/dist/fairmint-ui.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.cjs +1 -1
- package/dist/node_modules/@mantine/form/esm/hooks/use-form-status/use-form-status.js +1 -1
- package/dist/node_modules/prop-types/index.cjs +1 -1
- package/dist/node_modules/prop-types/index.js +1 -1
- package/dist/styles.css +73 -0
- package/dist/theme/index.cjs +4 -0
- package/dist/theme/index.cjs.map +1 -1
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +4 -0
- package/dist/theme/index.js.map +1 -1
- package/package.json +1 -1
package/dist/_virtual/index3.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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":";;;;;;"}
|
package/dist/_virtual/index3.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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":";;;;"}
|
package/dist/_virtual/index4.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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":";;;;"}
|
package/dist/_virtual/index4.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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":";"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const index = require("../../../theme/index.cjs");
|
|
5
|
+
const colors = require("../../../theme/colors.cjs");
|
|
6
|
+
const Badge = require("../../primitives/Badge/Badge.cjs");
|
|
7
|
+
const Button = require("../../primitives/Button/Button.cjs");
|
|
8
|
+
const layout = require("../../primitives/layout.cjs");
|
|
9
|
+
const Group = require("../../../node_modules/@mantine/core/esm/components/Group/Group.cjs");
|
|
10
|
+
const ThemeIcon = require("../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.cjs");
|
|
11
|
+
const Text = require("../../../node_modules/@mantine/core/esm/components/Text/Text.cjs");
|
|
12
|
+
const fontSizes = require("../../../theme/fontSizes.cjs");
|
|
13
|
+
const TONE_COLORS = {
|
|
14
|
+
brand: colors.colors.primary,
|
|
15
|
+
neutral: colors.colors.neutral,
|
|
16
|
+
info: colors.colors.info,
|
|
17
|
+
success: colors.colors.success,
|
|
18
|
+
warning: colors.colors.warning,
|
|
19
|
+
error: colors.colors.error
|
|
20
|
+
};
|
|
21
|
+
const DefaultStatusIcon = ({ tone }) => {
|
|
22
|
+
const commonProps = {
|
|
23
|
+
width: 20,
|
|
24
|
+
height: 20,
|
|
25
|
+
viewBox: "0 0 24 24",
|
|
26
|
+
fill: "none",
|
|
27
|
+
stroke: "currentColor",
|
|
28
|
+
strokeWidth: 1.75,
|
|
29
|
+
strokeLinecap: "round",
|
|
30
|
+
strokeLinejoin: "round",
|
|
31
|
+
"aria-hidden": true
|
|
32
|
+
};
|
|
33
|
+
if (tone === "success") {
|
|
34
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...commonProps, children: [
|
|
35
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: "Success" }),
|
|
36
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
37
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m8.5 12 2.25 2.25L15.75 9" })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
if (tone === "warning") {
|
|
41
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...commonProps, children: [
|
|
42
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: "Warning" }),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx("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" }),
|
|
44
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 9v4" }),
|
|
45
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17h.01" })
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
if (tone === "error") {
|
|
49
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...commonProps, children: [
|
|
50
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: "Error" }),
|
|
51
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 9 6 6" }),
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 9-6 6" })
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...commonProps, children: [
|
|
57
|
+
/* @__PURE__ */ jsxRuntime.jsx("title", { children: "Information" }),
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
59
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 11v5" }),
|
|
60
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8h.01" })
|
|
61
|
+
] });
|
|
62
|
+
};
|
|
63
|
+
const surfaceProps = (tone, presentation) => {
|
|
64
|
+
const color = TONE_COLORS[tone];
|
|
65
|
+
if (presentation === "page-level") {
|
|
66
|
+
return {
|
|
67
|
+
bg: `${color}.1`,
|
|
68
|
+
style: {
|
|
69
|
+
borderRadius: 0
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const borderShade = tone === "brand" ? 1 : tone === "neutral" ? 3 : 2;
|
|
74
|
+
return {
|
|
75
|
+
bg: `${color}.0`,
|
|
76
|
+
bd: `1px solid ${color}.${borderShade}`,
|
|
77
|
+
style: {
|
|
78
|
+
borderRadius: index.radii.lg
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const titleColor = (tone, presentation) => {
|
|
83
|
+
if (presentation === "page-level") {
|
|
84
|
+
const color = TONE_COLORS[tone];
|
|
85
|
+
return `${color}.${tone === "neutral" ? 9 : 8}`;
|
|
86
|
+
}
|
|
87
|
+
return index.neutralColors[900];
|
|
88
|
+
};
|
|
89
|
+
const actionVariant = (tone) => {
|
|
90
|
+
if (tone === "brand") return "light";
|
|
91
|
+
if (tone === "neutral") return "outline";
|
|
92
|
+
return "filled";
|
|
93
|
+
};
|
|
94
|
+
const descriptionTextProps = {
|
|
95
|
+
size: "sm",
|
|
96
|
+
c: index.neutralColors[500],
|
|
97
|
+
style: { lineHeight: 1.4 }
|
|
98
|
+
};
|
|
99
|
+
function BannerDescription({ children }) {
|
|
100
|
+
if (typeof children === "string" || typeof children === "number") {
|
|
101
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Text.Text, { ...descriptionTextProps, children });
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
104
|
+
layout.Box,
|
|
105
|
+
{
|
|
106
|
+
c: index.neutralColors[500],
|
|
107
|
+
style: {
|
|
108
|
+
fontSize: fontSizes.fontSizes.sm,
|
|
109
|
+
lineHeight: 1.4
|
|
110
|
+
},
|
|
111
|
+
children
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function Banner({
|
|
116
|
+
action,
|
|
117
|
+
ariaLabel,
|
|
118
|
+
badgeLabel,
|
|
119
|
+
className,
|
|
120
|
+
description,
|
|
121
|
+
icon,
|
|
122
|
+
presentation = "inline",
|
|
123
|
+
role,
|
|
124
|
+
style,
|
|
125
|
+
title,
|
|
126
|
+
tone = "brand"
|
|
127
|
+
}) {
|
|
128
|
+
const color = TONE_COLORS[tone];
|
|
129
|
+
const iconNode = icon === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(DefaultStatusIcon, { tone }) : icon;
|
|
130
|
+
const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
|
|
131
|
+
const resolvedAriaLabel = ariaLabel ?? (typeof title === "string" ? title : void 0);
|
|
132
|
+
const surface = surfaceProps(tone, presentation);
|
|
133
|
+
let actionNode = null;
|
|
134
|
+
if (action !== void 0) {
|
|
135
|
+
const { label, ...buttonProps } = action;
|
|
136
|
+
actionNode = /* @__PURE__ */ jsxRuntime.jsx(
|
|
137
|
+
Button.Button,
|
|
138
|
+
{
|
|
139
|
+
...buttonProps,
|
|
140
|
+
color,
|
|
141
|
+
variant: actionVariant(tone),
|
|
142
|
+
style: { flex: "0 0 auto", ...buttonProps.style },
|
|
143
|
+
children: label
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
148
|
+
layout.Box,
|
|
149
|
+
{
|
|
150
|
+
"aria-label": resolvedAriaLabel,
|
|
151
|
+
className,
|
|
152
|
+
"data-presentation": presentation,
|
|
153
|
+
"data-tone": tone,
|
|
154
|
+
role: resolvedRole,
|
|
155
|
+
px: "md",
|
|
156
|
+
py: "md",
|
|
157
|
+
bg: surface.bg,
|
|
158
|
+
bd: "bd" in surface ? surface.bd : void 0,
|
|
159
|
+
style: {
|
|
160
|
+
boxSizing: "border-box",
|
|
161
|
+
width: "100%",
|
|
162
|
+
...surface.style,
|
|
163
|
+
...style
|
|
164
|
+
},
|
|
165
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { align: "center", gap: "sm", wrap: "wrap", children: [
|
|
166
|
+
iconNode !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
167
|
+
ThemeIcon.ThemeIcon,
|
|
168
|
+
{
|
|
169
|
+
"aria-hidden": true,
|
|
170
|
+
color,
|
|
171
|
+
radius: "sm",
|
|
172
|
+
size: 40,
|
|
173
|
+
variant: "light",
|
|
174
|
+
style: { flex: "0 0 auto" },
|
|
175
|
+
children: iconNode
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
/* @__PURE__ */ jsxRuntime.jsxs(layout.Stack, { gap: 4, style: { flex: "1 1 240px", minWidth: 0 }, children: [
|
|
179
|
+
title !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(Group.Group, { align: "center", gap: "xs", wrap: "wrap", children: [
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
Text.Text,
|
|
182
|
+
{
|
|
183
|
+
fw: 600,
|
|
184
|
+
size: "md",
|
|
185
|
+
c: titleColor(tone, presentation),
|
|
186
|
+
style: { lineHeight: 1.35 },
|
|
187
|
+
children: title
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
badgeLabel !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge.Badge, { color, size: "sm", variant: "light", children: badgeLabel })
|
|
191
|
+
] }),
|
|
192
|
+
description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(BannerDescription, { children: description })
|
|
193
|
+
] }),
|
|
194
|
+
actionNode
|
|
195
|
+
] })
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
exports.Banner = Banner;
|
|
200
|
+
//# sourceMappingURL=Banner.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Banner.cjs","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fontSizes, neutralColors, radii } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, 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 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 in the 40px semantic tile. Pass `null` to hide the tile. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\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 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 color = TONE_COLORS[tone];\n\n if (presentation === \"page-level\") {\n return {\n bg: `${color}.1`,\n style: {\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n // Chip Banner: tinted surface + semantic border (error border = error.2)\n const borderShade = tone === \"brand\" ? 1 : tone === \"neutral\" ? 3 : 2;\n\n return {\n bg: `${color}.0`,\n bd: `1px solid ${color}.${borderShade}`,\n style: {\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Inline Chip banners keep light semantic fills across color schemes, so titles\n * stay dark primary text for WCAG AA. Page-level uses a deeper semantic shade.\n */\nconst titleColor = (tone: BannerTone, presentation: BannerPresentation) => {\n if (presentation === \"page-level\") {\n const color = TONE_COLORS[tone];\n return `${color}.${tone === \"neutral\" ? 9 : 8}`;\n }\n return neutralColors[900];\n};\n\nconst actionVariant = (tone: BannerTone): ButtonProps[\"variant\"] => {\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: neutralColors[500],\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={neutralColors[500]}\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 presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n let actionNode: ReactNode = null;\n\n if (action !== undefined) {\n const { label, ...buttonProps } = action;\n actionNode = (\n <Button\n {...buttonProps}\n color={color}\n variant={actionVariant(tone)}\n style={{ flex: \"0 0 auto\", ...buttonProps.style }}\n >\n {label}\n </Button>\n );\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 px=\"md\"\n py=\"md\"\n bg={surface.bg}\n bd={\"bd\" in surface ? surface.bd : undefined}\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n >\n <Group align=\"center\" gap=\"sm\" wrap=\"wrap\">\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={40}\n variant=\"light\"\n style={{ flex: \"0 0 auto\" }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n <Stack gap={4} style={{ flex: \"1 1 240px\", minWidth: 0 }}>\n {title !== undefined && (\n <Group align=\"center\" gap=\"xs\" wrap=\"wrap\">\n <Text\n fw={600}\n size=\"md\"\n c={titleColor(tone, presentation)}\n style={{ lineHeight: 1.35 }}\n >\n {title}\n </Text>\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n {description !== undefined && <BannerDescription>{description}</BannerDescription>}\n </Stack>\n\n {actionNode}\n </Group>\n </Box>\n );\n}\n"],"names":["colors","jsxs","jsx","radii","neutralColors","Text","Box","fontSizes","Button","Group","ThemeIcon","Stack","Badge"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AriaRole, CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import { ButtonProps } from '../../primitives/Button/Button';
|
|
3
|
+
export type BannerTone = "brand" | "neutral" | "info" | "success" | "warning" | "error";
|
|
4
|
+
export type BannerPresentation = "inline" | "page-level";
|
|
5
|
+
export interface BannerActionProps extends Omit<ButtonProps, "children" | "color" | "variant"> {
|
|
6
|
+
/** Visible action label. */
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface BannerProps {
|
|
10
|
+
/** Primary message. Omit when the banner is description-only; set `ariaLabel` for accessibility. */
|
|
11
|
+
title?: ReactNode;
|
|
12
|
+
/** Supporting context. Omit for a title-only banner. */
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
/** Semantic meaning and visual treatment. @default "brand" */
|
|
15
|
+
tone?: BannerTone;
|
|
16
|
+
/** Inline content callout or full-width page-edge treatment. @default "inline" */
|
|
17
|
+
presentation?: BannerPresentation;
|
|
18
|
+
/** Icon shown in the 40px semantic tile. Pass `null` to hide the tile. */
|
|
19
|
+
icon?: ReactNode | null;
|
|
20
|
+
/** Optional badge label displayed beside the title. */
|
|
21
|
+
badgeLabel?: ReactNode;
|
|
22
|
+
/** Optional standardized CTA. */
|
|
23
|
+
action?: BannerActionProps;
|
|
24
|
+
/** Override the default accessible role. Error defaults to alert; other tones use status. */
|
|
25
|
+
role?: AriaRole;
|
|
26
|
+
/** Accessible label for the banner region. Defaults to the string title when possible. */
|
|
27
|
+
ariaLabel?: string;
|
|
28
|
+
className?: string;
|
|
29
|
+
style?: CSSProperties;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Persistent contextual guidance with semantic inline and page-level presentations.
|
|
33
|
+
* Position page-level banners in the consuming layout; the component does not use fixed positioning.
|
|
34
|
+
*/
|
|
35
|
+
export declare function Banner({ action, ariaLabel, badgeLabel, className, description, icon, presentation, role, style, title, tone, }: BannerProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
//# sourceMappingURL=Banner.d.ts.map
|
|
@@ -0,0 +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,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,0EAA0E;IAC1E,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iCAAiC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,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;AAoID;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,YAAuB,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAc,GACf,EAAE,WAAW,2CA+Eb"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { radii, neutralColors } from "../../../theme/index.js";
|
|
3
|
+
import { colors } from "../../../theme/colors.js";
|
|
4
|
+
import { Badge } from "../../primitives/Badge/Badge.js";
|
|
5
|
+
import { Button } from "../../primitives/Button/Button.js";
|
|
6
|
+
import { Box, Stack } from "../../primitives/layout.js";
|
|
7
|
+
import { Group } from "../../../node_modules/@mantine/core/esm/components/Group/Group.js";
|
|
8
|
+
import { ThemeIcon } from "../../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.js";
|
|
9
|
+
import { Text } from "../../../node_modules/@mantine/core/esm/components/Text/Text.js";
|
|
10
|
+
import { fontSizes } from "../../../theme/fontSizes.js";
|
|
11
|
+
const TONE_COLORS = {
|
|
12
|
+
brand: colors.primary,
|
|
13
|
+
neutral: colors.neutral,
|
|
14
|
+
info: colors.info,
|
|
15
|
+
success: colors.success,
|
|
16
|
+
warning: colors.warning,
|
|
17
|
+
error: colors.error
|
|
18
|
+
};
|
|
19
|
+
const DefaultStatusIcon = ({ tone }) => {
|
|
20
|
+
const commonProps = {
|
|
21
|
+
width: 20,
|
|
22
|
+
height: 20,
|
|
23
|
+
viewBox: "0 0 24 24",
|
|
24
|
+
fill: "none",
|
|
25
|
+
stroke: "currentColor",
|
|
26
|
+
strokeWidth: 1.75,
|
|
27
|
+
strokeLinecap: "round",
|
|
28
|
+
strokeLinejoin: "round",
|
|
29
|
+
"aria-hidden": true
|
|
30
|
+
};
|
|
31
|
+
if (tone === "success") {
|
|
32
|
+
return /* @__PURE__ */ jsxs("svg", { ...commonProps, children: [
|
|
33
|
+
/* @__PURE__ */ jsx("title", { children: "Success" }),
|
|
34
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
35
|
+
/* @__PURE__ */ jsx("path", { d: "m8.5 12 2.25 2.25L15.75 9" })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
if (tone === "warning") {
|
|
39
|
+
return /* @__PURE__ */ jsxs("svg", { ...commonProps, children: [
|
|
40
|
+
/* @__PURE__ */ jsx("title", { children: "Warning" }),
|
|
41
|
+
/* @__PURE__ */ jsx("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" }),
|
|
42
|
+
/* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
|
|
43
|
+
/* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
if (tone === "error") {
|
|
47
|
+
return /* @__PURE__ */ jsxs("svg", { ...commonProps, children: [
|
|
48
|
+
/* @__PURE__ */ jsx("title", { children: "Error" }),
|
|
49
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
50
|
+
/* @__PURE__ */ jsx("path", { d: "m9 9 6 6" }),
|
|
51
|
+
/* @__PURE__ */ jsx("path", { d: "m15 9-6 6" })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ jsxs("svg", { ...commonProps, children: [
|
|
55
|
+
/* @__PURE__ */ jsx("title", { children: "Information" }),
|
|
56
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
57
|
+
/* @__PURE__ */ jsx("path", { d: "M12 11v5" }),
|
|
58
|
+
/* @__PURE__ */ jsx("path", { d: "M12 8h.01" })
|
|
59
|
+
] });
|
|
60
|
+
};
|
|
61
|
+
const surfaceProps = (tone, presentation) => {
|
|
62
|
+
const color = TONE_COLORS[tone];
|
|
63
|
+
if (presentation === "page-level") {
|
|
64
|
+
return {
|
|
65
|
+
bg: `${color}.1`,
|
|
66
|
+
style: {
|
|
67
|
+
borderRadius: 0
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const borderShade = tone === "brand" ? 1 : tone === "neutral" ? 3 : 2;
|
|
72
|
+
return {
|
|
73
|
+
bg: `${color}.0`,
|
|
74
|
+
bd: `1px solid ${color}.${borderShade}`,
|
|
75
|
+
style: {
|
|
76
|
+
borderRadius: radii.lg
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const titleColor = (tone, presentation) => {
|
|
81
|
+
if (presentation === "page-level") {
|
|
82
|
+
const color = TONE_COLORS[tone];
|
|
83
|
+
return `${color}.${tone === "neutral" ? 9 : 8}`;
|
|
84
|
+
}
|
|
85
|
+
return neutralColors[900];
|
|
86
|
+
};
|
|
87
|
+
const actionVariant = (tone) => {
|
|
88
|
+
if (tone === "brand") return "light";
|
|
89
|
+
if (tone === "neutral") return "outline";
|
|
90
|
+
return "filled";
|
|
91
|
+
};
|
|
92
|
+
const descriptionTextProps = {
|
|
93
|
+
size: "sm",
|
|
94
|
+
c: neutralColors[500],
|
|
95
|
+
style: { lineHeight: 1.4 }
|
|
96
|
+
};
|
|
97
|
+
function BannerDescription({ children }) {
|
|
98
|
+
if (typeof children === "string" || typeof children === "number") {
|
|
99
|
+
return /* @__PURE__ */ jsx(Text, { ...descriptionTextProps, children });
|
|
100
|
+
}
|
|
101
|
+
return /* @__PURE__ */ jsx(
|
|
102
|
+
Box,
|
|
103
|
+
{
|
|
104
|
+
c: neutralColors[500],
|
|
105
|
+
style: {
|
|
106
|
+
fontSize: fontSizes.sm,
|
|
107
|
+
lineHeight: 1.4
|
|
108
|
+
},
|
|
109
|
+
children
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
function Banner({
|
|
114
|
+
action,
|
|
115
|
+
ariaLabel,
|
|
116
|
+
badgeLabel,
|
|
117
|
+
className,
|
|
118
|
+
description,
|
|
119
|
+
icon,
|
|
120
|
+
presentation = "inline",
|
|
121
|
+
role,
|
|
122
|
+
style,
|
|
123
|
+
title,
|
|
124
|
+
tone = "brand"
|
|
125
|
+
}) {
|
|
126
|
+
const color = TONE_COLORS[tone];
|
|
127
|
+
const iconNode = icon === void 0 ? /* @__PURE__ */ jsx(DefaultStatusIcon, { tone }) : icon;
|
|
128
|
+
const resolvedRole = role ?? (tone === "error" ? "alert" : "status");
|
|
129
|
+
const resolvedAriaLabel = ariaLabel ?? (typeof title === "string" ? title : void 0);
|
|
130
|
+
const surface = surfaceProps(tone, presentation);
|
|
131
|
+
let actionNode = null;
|
|
132
|
+
if (action !== void 0) {
|
|
133
|
+
const { label, ...buttonProps } = action;
|
|
134
|
+
actionNode = /* @__PURE__ */ jsx(
|
|
135
|
+
Button,
|
|
136
|
+
{
|
|
137
|
+
...buttonProps,
|
|
138
|
+
color,
|
|
139
|
+
variant: actionVariant(tone),
|
|
140
|
+
style: { flex: "0 0 auto", ...buttonProps.style },
|
|
141
|
+
children: label
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
146
|
+
Box,
|
|
147
|
+
{
|
|
148
|
+
"aria-label": resolvedAriaLabel,
|
|
149
|
+
className,
|
|
150
|
+
"data-presentation": presentation,
|
|
151
|
+
"data-tone": tone,
|
|
152
|
+
role: resolvedRole,
|
|
153
|
+
px: "md",
|
|
154
|
+
py: "md",
|
|
155
|
+
bg: surface.bg,
|
|
156
|
+
bd: "bd" in surface ? surface.bd : void 0,
|
|
157
|
+
style: {
|
|
158
|
+
boxSizing: "border-box",
|
|
159
|
+
width: "100%",
|
|
160
|
+
...surface.style,
|
|
161
|
+
...style
|
|
162
|
+
},
|
|
163
|
+
children: /* @__PURE__ */ jsxs(Group, { align: "center", gap: "sm", wrap: "wrap", children: [
|
|
164
|
+
iconNode !== null && /* @__PURE__ */ jsx(
|
|
165
|
+
ThemeIcon,
|
|
166
|
+
{
|
|
167
|
+
"aria-hidden": true,
|
|
168
|
+
color,
|
|
169
|
+
radius: "sm",
|
|
170
|
+
size: 40,
|
|
171
|
+
variant: "light",
|
|
172
|
+
style: { flex: "0 0 auto" },
|
|
173
|
+
children: iconNode
|
|
174
|
+
}
|
|
175
|
+
),
|
|
176
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: "1 1 240px", minWidth: 0 }, children: [
|
|
177
|
+
title !== void 0 && /* @__PURE__ */ jsxs(Group, { align: "center", gap: "xs", wrap: "wrap", children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
Text,
|
|
180
|
+
{
|
|
181
|
+
fw: 600,
|
|
182
|
+
size: "md",
|
|
183
|
+
c: titleColor(tone, presentation),
|
|
184
|
+
style: { lineHeight: 1.35 },
|
|
185
|
+
children: title
|
|
186
|
+
}
|
|
187
|
+
),
|
|
188
|
+
badgeLabel !== void 0 && /* @__PURE__ */ jsx(Badge, { color, size: "sm", variant: "light", children: badgeLabel })
|
|
189
|
+
] }),
|
|
190
|
+
description !== void 0 && /* @__PURE__ */ jsx(BannerDescription, { children: description })
|
|
191
|
+
] }),
|
|
192
|
+
actionNode
|
|
193
|
+
] })
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
Banner
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=Banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Banner.js","sources":["../../../../src/components/generic/Banner/Banner.tsx"],"sourcesContent":["import type { AriaRole, CSSProperties, ReactNode } from \"react\";\nimport { fontSizes, neutralColors, radii } from \"../../../theme\";\nimport { colors } from \"../../../theme/colors\";\nimport { Badge } from \"../../primitives/Badge/Badge\";\nimport { Button, type ButtonProps } from \"../../primitives/Button/Button\";\nimport { Box, Group, Stack, 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 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 in the 40px semantic tile. Pass `null` to hide the tile. */\n icon?: ReactNode | null;\n /** Optional badge label displayed beside the title. */\n badgeLabel?: ReactNode;\n /** Optional standardized CTA. */\n action?: BannerActionProps;\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 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 color = TONE_COLORS[tone];\n\n if (presentation === \"page-level\") {\n return {\n bg: `${color}.1`,\n style: {\n borderRadius: 0,\n } satisfies CSSProperties,\n };\n }\n\n // Chip Banner: tinted surface + semantic border (error border = error.2)\n const borderShade = tone === \"brand\" ? 1 : tone === \"neutral\" ? 3 : 2;\n\n return {\n bg: `${color}.0`,\n bd: `1px solid ${color}.${borderShade}`,\n style: {\n borderRadius: radii.lg,\n } satisfies CSSProperties,\n };\n};\n\n/**\n * Inline Chip banners keep light semantic fills across color schemes, so titles\n * stay dark primary text for WCAG AA. Page-level uses a deeper semantic shade.\n */\nconst titleColor = (tone: BannerTone, presentation: BannerPresentation) => {\n if (presentation === \"page-level\") {\n const color = TONE_COLORS[tone];\n return `${color}.${tone === \"neutral\" ? 9 : 8}`;\n }\n return neutralColors[900];\n};\n\nconst actionVariant = (tone: BannerTone): ButtonProps[\"variant\"] => {\n if (tone === \"brand\") return \"light\";\n if (tone === \"neutral\") return \"outline\";\n return \"filled\";\n};\n\nconst descriptionTextProps = {\n size: \"sm\" as const,\n c: neutralColors[500],\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={neutralColors[500]}\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 presentation = \"inline\",\n role,\n style,\n title,\n tone = \"brand\",\n}: BannerProps) {\n const color = TONE_COLORS[tone];\n const iconNode = icon === undefined ? <DefaultStatusIcon tone={tone} /> : icon;\n const resolvedRole = role ?? (tone === \"error\" ? \"alert\" : \"status\");\n const resolvedAriaLabel = ariaLabel ?? (typeof title === \"string\" ? title : undefined);\n const surface = surfaceProps(tone, presentation);\n let actionNode: ReactNode = null;\n\n if (action !== undefined) {\n const { label, ...buttonProps } = action;\n actionNode = (\n <Button\n {...buttonProps}\n color={color}\n variant={actionVariant(tone)}\n style={{ flex: \"0 0 auto\", ...buttonProps.style }}\n >\n {label}\n </Button>\n );\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 px=\"md\"\n py=\"md\"\n bg={surface.bg}\n bd={\"bd\" in surface ? surface.bd : undefined}\n style={{\n boxSizing: \"border-box\",\n width: \"100%\",\n ...surface.style,\n ...style,\n }}\n >\n <Group align=\"center\" gap=\"sm\" wrap=\"wrap\">\n {iconNode !== null && (\n <ThemeIcon\n aria-hidden\n color={color}\n radius=\"sm\"\n size={40}\n variant=\"light\"\n style={{ flex: \"0 0 auto\" }}\n >\n {iconNode}\n </ThemeIcon>\n )}\n\n <Stack gap={4} style={{ flex: \"1 1 240px\", minWidth: 0 }}>\n {title !== undefined && (\n <Group align=\"center\" gap=\"xs\" wrap=\"wrap\">\n <Text\n fw={600}\n size=\"md\"\n c={titleColor(tone, presentation)}\n style={{ lineHeight: 1.35 }}\n >\n {title}\n </Text>\n {badgeLabel !== undefined && (\n <Badge color={color} size=\"sm\" variant=\"light\">\n {badgeLabel}\n </Badge>\n )}\n </Group>\n )}\n {description !== undefined && <BannerDescription>{description}</BannerDescription>}\n </Stack>\n\n {actionNode}\n </Group>\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
|