@stackone/malachite 2.54.0 → 2.55.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.
@@ -1,5 +1,6 @@
1
- import { jsx as i } from "react/jsx-runtime";
2
- import { useState as g } from "react";
1
+ import { jsx as n } from "react/jsx-runtime";
2
+ import { useState as u } from "react";
3
+ import g from "../assets/empty_logo.svg.js";
3
4
  const p = (e) => {
4
5
  let r = 0;
5
6
  for (let t = 0; t < e.length; t += 1)
@@ -9,20 +10,20 @@ const p = (e) => {
9
10
  src: e,
10
11
  name: r,
11
12
  size: t = 24,
12
- shape: h = "square",
13
- fallback: c = "initial",
13
+ shape: l = "square",
14
+ fallback: h = "initial",
14
15
  className: o = ""
15
16
  }) => {
16
- const [f, u] = g(void 0), n = (r == null ? void 0 : r.trim()) ?? "", a = h === "circle" ? "50%" : `${Math.round(t * 0.25)}px`;
17
- if (e && f !== e)
18
- return /* @__PURE__ */ i(
17
+ const [c, f] = u(void 0), i = (r == null ? void 0 : r.trim()) ?? "", a = l === "circle" ? "50%" : `${Math.round(t * 0.25)}px`;
18
+ if (e && c !== e)
19
+ return /* @__PURE__ */ n(
19
20
  "img",
20
21
  {
21
22
  src: e,
22
- alt: n,
23
+ alt: i,
23
24
  loading: "lazy",
24
25
  decoding: "async",
25
- onError: () => u(e),
26
+ onError: () => f(e),
26
27
  className: o,
27
28
  style: {
28
29
  width: `${t}px`,
@@ -33,42 +34,23 @@ const p = (e) => {
33
34
  }
34
35
  }
35
36
  );
36
- const l = n ? { role: "img", "aria-label": n } : { "aria-hidden": !0 };
37
- if (c === "placeholder") {
38
- const d = `${Math.round(t * 0.25)}px`;
39
- return /* @__PURE__ */ i(
40
- "div",
41
- {
42
- ...l,
43
- className: o,
44
- style: {
45
- width: `${t}px`,
46
- height: `${t}px`,
47
- flexShrink: 0,
48
- borderRadius: a,
49
- display: "flex",
50
- alignItems: "center",
51
- justifyContent: "center",
52
- background: "var(--malachite-accent-background, rgb(0, 175, 102))"
53
- },
54
- children: /* @__PURE__ */ i(
55
- "span",
56
- {
57
- style: {
58
- width: d,
59
- height: d,
60
- borderRadius: "50%",
61
- background: "rgba(255, 255, 255, 0.8)"
62
- }
63
- }
64
- )
37
+ const d = i ? { role: "img", "aria-label": i } : { "aria-hidden": !0 };
38
+ return h === "placeholder" ? /* @__PURE__ */ n(
39
+ g,
40
+ {
41
+ ...d,
42
+ className: o,
43
+ width: t,
44
+ height: t,
45
+ style: {
46
+ flexShrink: 0,
47
+ borderRadius: l === "circle" ? "50%" : void 0
65
48
  }
66
- );
67
- }
68
- return /* @__PURE__ */ i(
49
+ }
50
+ ) : /* @__PURE__ */ n(
69
51
  "div",
70
52
  {
71
- ...l,
53
+ ...d,
72
54
  className: o,
73
55
  style: {
74
56
  width: `${t}px`,
@@ -78,14 +60,14 @@ const p = (e) => {
78
60
  display: "flex",
79
61
  alignItems: "center",
80
62
  justifyContent: "center",
81
- background: p(n),
63
+ background: p(i),
82
64
  color: "#ffffff",
83
65
  fontWeight: 600,
84
66
  fontSize: `${Math.round(t * 0.45)}px`,
85
67
  lineHeight: 1,
86
68
  textTransform: "uppercase"
87
69
  },
88
- children: n.charAt(0) || "?"
70
+ children: i.charAt(0) || "?"
89
71
  }
90
72
  );
91
73
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","sources":["../../src/components/Avatar.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nexport type AvatarShape = 'square' | 'circle';\n\n/** `initial` suits a named entity (a person, a model); `placeholder` says \"no logo available\". */\nexport type AvatarFallback = 'initial' | 'placeholder';\n\nexport interface AvatarProps {\n /** Image URL (logo/photo). Falls back to `fallback` when missing or it fails to load. */\n src?: string;\n /** Used for the initial fallback and as the image alt / accessible label. */\n name?: string;\n /** Pixel size of the (square) avatar. */\n size?: number;\n shape?: AvatarShape;\n /** What shows when `src` is missing or fails to load. Defaults to `initial`. */\n fallback?: AvatarFallback;\n className?: string;\n}\n\n// Deterministic, evenly-distributed hue from the label so the same entity always gets\n// the same colour. Saturation/lightness are fixed for a consistent, on-brand feel.\n// NOTE: avatar identity colours (this hue and the white text below) are intentionally\n// NOT theme tokens — they are a generated identity palette, an explicit exception to\n// the \"colours come from theme tokens\" rule (there is no avatar-colour token group).\nconst backgroundFor = (seed: string): string => {\n let hash = 0;\n for (let index = 0; index < seed.length; index += 1) {\n hash = seed.charCodeAt(index) + ((hash << 5) - hash);\n }\n return `hsl(${Math.abs(hash) % 360}, 55%, 52%)`;\n};\n\n/**\n * A logo/initial avatar. Renders `src` when available, otherwise a coloured tile\n * with the first letter of `name`. Encapsulates the fallback colour so consumers\n * never hand-roll it.\n */\nconst Avatar: React.FC<AvatarProps> = ({\n src,\n name,\n size = 24,\n shape = 'square',\n fallback = 'initial',\n className = '',\n}) => {\n // Track which src failed (not a boolean) so switching `src` to a new URL retries the\n // image instead of staying stuck on the fallback.\n const [failedSrc, setFailedSrc] = useState<string | undefined>(undefined);\n const label = name?.trim() ?? '';\n const borderRadius = shape === 'circle' ? '50%' : `${Math.round(size * 0.25)}px`;\n\n if (src && failedSrc !== src) {\n return (\n <img\n src={src}\n alt={label}\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setFailedSrc(src)}\n className={className}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n borderRadius,\n objectFit: 'contain',\n flexShrink: 0,\n }}\n />\n );\n }\n\n // With a label the tile is an image with an accessible name; without one it carries\n // no information, so mark it decorative (aria-hidden, no role) to avoid an unnamed\n // image in the accessibility tree.\n const tileSemantics = label ? { role: 'img', 'aria-label': label } : { 'aria-hidden': true };\n\n if (fallback === 'placeholder') {\n const dotSize = `${Math.round(size * 0.25)}px`;\n return (\n <div\n {...tileSemantics}\n className={className}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n flexShrink: 0,\n borderRadius,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'var(--malachite-accent-background, rgb(0, 175, 102))',\n }}\n >\n {/* The website's and docs' \"no logo\" mark: its white dot is part of the mark, not a theme colour. */}\n <span\n style={{\n width: dotSize,\n height: dotSize,\n borderRadius: '50%',\n background: 'rgba(255, 255, 255, 0.8)',\n }}\n />\n </div>\n );\n }\n\n return (\n <div\n {...tileSemantics}\n className={className}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n flexShrink: 0,\n borderRadius,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: backgroundFor(label),\n color: '#ffffff',\n fontWeight: 600,\n fontSize: `${Math.round(size * 0.45)}px`,\n lineHeight: 1,\n textTransform: 'uppercase',\n }}\n >\n {label.charAt(0) || '?'}\n </div>\n );\n};\n\nexport default Avatar;\nexport { Avatar };\n"],"names":["backgroundFor","seed","hash","index","Avatar","src","name","size","shape","fallback","className","failedSrc","setFailedSrc","useState","label","borderRadius","jsx","tileSemantics","dotSize"],"mappings":";;AAyBA,MAAMA,IAAgB,CAACC,MAAyB;AAC5C,MAAIC,IAAO;AACX,WAASC,IAAQ,GAAGA,IAAQF,EAAK,QAAQE,KAAS;AAC9C,IAAAD,IAAOD,EAAK,WAAWE,CAAK,MAAMD,KAAQ,KAAKA;AAEnD,SAAO,OAAO,KAAK,IAAIA,CAAI,IAAI,GAAG;AACtC,GAOME,IAAgC,CAAC;AAAA,EACnC,KAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAChB,MAAM;AAGF,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAA6B,MAAS,GAClEC,KAAQR,KAAA,gBAAAA,EAAM,WAAU,IACxBS,IAAeP,MAAU,WAAW,QAAQ,GAAG,KAAK,MAAMD,IAAO,IAAI,CAAC;AAE5E,MAAIF,KAAOM,MAAcN;AACrB,WACI,gBAAAW;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,KAAAX;AAAA,QACA,KAAKS;AAAA,QACL,SAAQ;AAAA,QACR,UAAS;AAAA,QACT,SAAS,MAAMF,EAAaP,CAAG;AAAA,QAC/B,WAAAK;AAAA,QACA,OAAO;AAAA,UACH,OAAO,GAAGH,CAAI;AAAA,UACd,QAAQ,GAAGA,CAAI;AAAA,UACf,cAAAQ;AAAA,UACA,WAAW;AAAA,UACX,YAAY;AAAA,QAAA;AAAA,MAChB;AAAA,IAAA;AAQZ,QAAME,IAAgBH,IAAQ,EAAE,MAAM,OAAO,cAAcA,EAAA,IAAU,EAAE,eAAe,GAAA;AAEtF,MAAIL,MAAa,eAAe;AAC5B,UAAMS,IAAU,GAAG,KAAK,MAAMX,IAAO,IAAI,CAAC;AAC1C,WACI,gBAAAS;AAAA,MAAC;AAAA,MAAA;AAAA,QACI,GAAGC;AAAA,QACJ,WAAAP;AAAA,QACA,OAAO;AAAA,UACH,OAAO,GAAGH,CAAI;AAAA,UACd,QAAQ,GAAGA,CAAI;AAAA,UACf,YAAY;AAAA,UACZ,cAAAQ;AAAA,UACA,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,YAAY;AAAA,QAAA;AAAA,QAIhB,UAAA,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACG,OAAO;AAAA,cACH,OAAOE;AAAA,cACP,QAAQA;AAAA,cACR,cAAc;AAAA,cACd,YAAY;AAAA,YAAA;AAAA,UAChB;AAAA,QAAA;AAAA,MACJ;AAAA,IAAA;AAAA,EAGZ;AAEA,SACI,gBAAAF;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAGC;AAAA,MACJ,WAAAP;AAAA,MACA,OAAO;AAAA,QACH,OAAO,GAAGH,CAAI;AAAA,QACd,QAAQ,GAAGA,CAAI;AAAA,QACf,YAAY;AAAA,QACZ,cAAAQ;AAAA,QACA,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,YAAYf,EAAcc,CAAK;AAAA,QAC/B,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU,GAAG,KAAK,MAAMP,IAAO,IAAI,CAAC;AAAA,QACpC,YAAY;AAAA,QACZ,eAAe;AAAA,MAAA;AAAA,MAGlB,UAAAO,EAAM,OAAO,CAAC,KAAK;AAAA,IAAA;AAAA,EAAA;AAGhC;"}
1
+ {"version":3,"file":"Avatar.js","sources":["../../src/components/Avatar.tsx"],"sourcesContent":["import React, { useState } from 'react';\n// The no-logo mark stackone-logos.com serves; the same in every theme, so its colours are fixed.\nimport EmptyLogoSvg from '../assets/empty_logo.svg?react';\n\nexport type AvatarShape = 'square' | 'circle';\n\n/** `initial` suits a named entity (a person, a model); `placeholder` says \"no logo available\". */\nexport type AvatarFallback = 'initial' | 'placeholder';\n\nexport interface AvatarProps {\n /** Image URL (logo/photo). Falls back to `fallback` when missing or it fails to load. */\n src?: string;\n /** Used for the initial fallback and as the image alt / accessible label. */\n name?: string;\n /** Pixel size of the (square) avatar. */\n size?: number;\n shape?: AvatarShape;\n /** What shows when `src` is missing or fails to load. Defaults to `initial`. */\n fallback?: AvatarFallback;\n className?: string;\n}\n\n// Deterministic, evenly-distributed hue from the label so the same entity always gets\n// the same colour. Saturation/lightness are fixed for a consistent, on-brand feel.\n// NOTE: avatar identity colours (this hue and the white text below) are intentionally\n// NOT theme tokens — they are a generated identity palette, an explicit exception to\n// the \"colours come from theme tokens\" rule (there is no avatar-colour token group).\nconst backgroundFor = (seed: string): string => {\n let hash = 0;\n for (let index = 0; index < seed.length; index += 1) {\n hash = seed.charCodeAt(index) + ((hash << 5) - hash);\n }\n return `hsl(${Math.abs(hash) % 360}, 55%, 52%)`;\n};\n\n/**\n * A logo/initial avatar. Renders `src` when available, otherwise a coloured tile\n * with the first letter of `name`. Encapsulates the fallback colour so consumers\n * never hand-roll it.\n */\nconst Avatar: React.FC<AvatarProps> = ({\n src,\n name,\n size = 24,\n shape = 'square',\n fallback = 'initial',\n className = '',\n}) => {\n // Track which src failed (not a boolean) so switching `src` to a new URL retries the\n // image instead of staying stuck on the fallback.\n const [failedSrc, setFailedSrc] = useState<string | undefined>(undefined);\n const label = name?.trim() ?? '';\n const borderRadius = shape === 'circle' ? '50%' : `${Math.round(size * 0.25)}px`;\n\n if (src && failedSrc !== src) {\n return (\n <img\n src={src}\n alt={label}\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setFailedSrc(src)}\n className={className}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n borderRadius,\n objectFit: 'contain',\n flexShrink: 0,\n }}\n />\n );\n }\n\n // With a label the tile is an image with an accessible name; without one it carries\n // no information, so mark it decorative (aria-hidden, no role) to avoid an unnamed\n // image in the accessibility tree.\n const tileSemantics = label ? { role: 'img', 'aria-label': label } : { 'aria-hidden': true };\n\n if (fallback === 'placeholder') {\n return (\n <EmptyLogoSvg\n {...tileSemantics}\n className={className}\n width={size}\n height={size}\n style={{\n flexShrink: 0,\n borderRadius: shape === 'circle' ? '50%' : undefined,\n }}\n />\n );\n }\n\n return (\n <div\n {...tileSemantics}\n className={className}\n style={{\n width: `${size}px`,\n height: `${size}px`,\n flexShrink: 0,\n borderRadius,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: backgroundFor(label),\n color: '#ffffff',\n fontWeight: 600,\n fontSize: `${Math.round(size * 0.45)}px`,\n lineHeight: 1,\n textTransform: 'uppercase',\n }}\n >\n {label.charAt(0) || '?'}\n </div>\n );\n};\n\nexport default Avatar;\nexport { Avatar };\n"],"names":["backgroundFor","seed","hash","index","Avatar","src","name","size","shape","fallback","className","failedSrc","setFailedSrc","useState","label","borderRadius","jsx","tileSemantics","EmptyLogoSvg"],"mappings":";;;AA2BA,MAAMA,IAAgB,CAACC,MAAyB;AAC5C,MAAIC,IAAO;AACX,WAASC,IAAQ,GAAGA,IAAQF,EAAK,QAAQE,KAAS;AAC9C,IAAAD,IAAOD,EAAK,WAAWE,CAAK,MAAMD,KAAQ,KAAKA;AAEnD,SAAO,OAAO,KAAK,IAAIA,CAAI,IAAI,GAAG;AACtC,GAOME,IAAgC,CAAC;AAAA,EACnC,KAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAChB,MAAM;AAGF,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAA6B,MAAS,GAClEC,KAAQR,KAAA,gBAAAA,EAAM,WAAU,IACxBS,IAAeP,MAAU,WAAW,QAAQ,GAAG,KAAK,MAAMD,IAAO,IAAI,CAAC;AAE5E,MAAIF,KAAOM,MAAcN;AACrB,WACI,gBAAAW;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,KAAAX;AAAA,QACA,KAAKS;AAAA,QACL,SAAQ;AAAA,QACR,UAAS;AAAA,QACT,SAAS,MAAMF,EAAaP,CAAG;AAAA,QAC/B,WAAAK;AAAA,QACA,OAAO;AAAA,UACH,OAAO,GAAGH,CAAI;AAAA,UACd,QAAQ,GAAGA,CAAI;AAAA,UACf,cAAAQ;AAAA,UACA,WAAW;AAAA,UACX,YAAY;AAAA,QAAA;AAAA,MAChB;AAAA,IAAA;AAQZ,QAAME,IAAgBH,IAAQ,EAAE,MAAM,OAAO,cAAcA,EAAA,IAAU,EAAE,eAAe,GAAA;AAEtF,SAAIL,MAAa,gBAET,gBAAAO;AAAA,IAACE;AAAAA,IAAA;AAAA,MACI,GAAGD;AAAA,MACJ,WAAAP;AAAA,MACA,OAAOH;AAAA,MACP,QAAQA;AAAA,MACR,OAAO;AAAA,QACH,YAAY;AAAA,QACZ,cAAcC,MAAU,WAAW,QAAQ;AAAA,MAAA;AAAA,IAC/C;AAAA,EAAA,IAMR,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAGC;AAAA,MACJ,WAAAP;AAAA,MACA,OAAO;AAAA,QACH,OAAO,GAAGH,CAAI;AAAA,QACd,QAAQ,GAAGA,CAAI;AAAA,QACf,YAAY;AAAA,QACZ,cAAAQ;AAAA,QACA,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,YAAYf,EAAcc,CAAK;AAAA,QAC/B,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU,GAAG,KAAK,MAAMP,IAAO,IAAI,CAAC;AAAA,QACpC,YAAY;AAAA,QACZ,eAAe;AAAA,MAAA;AAAA,MAGlB,UAAAO,EAAM,OAAO,CAAC,KAAK;AAAA,IAAA;AAAA,EAAA;AAGhC;"}
@@ -1,59 +1,56 @@
1
- import { jsx as a, jsxs as s } from "react/jsx-runtime";
2
- import u from "../ActionMenu.js";
3
- import { Alert as $ } from "../Alert.js";
4
- import { Breadcrumbs as D } from "../Breadcrumbs.js";
5
- import { hasBackButton as O } from "../breadcrumbsNav.js";
6
- import { Button as M } from "../Button.js";
1
+ import { jsx as l, jsxs as s } from "react/jsx-runtime";
2
+ import $ from "../ActionMenu.js";
3
+ import { Alert as D } from "../Alert.js";
4
+ import { Breadcrumbs as O } from "../Breadcrumbs.js";
5
+ import { hasBackButton as M } from "../breadcrumbsNav.js";
6
+ import { Button as u } from "../Button.js";
7
7
  import P from "../OverflowRow.js";
8
- import m from "../Skeleton.js";
8
+ import h from "../Skeleton.js";
9
9
  import j from "../Typography/PageTitle.js";
10
- import v from "../Typography/Text.js";
11
- import { safeHref as x } from "../safeHref.js";
12
- import { CARD_MIN_HEIGHT as G, CARD_RADIUS as L, CARD_CLASSES as z, HEADER_HEIGHT as U, DIVIDER_CLASSES as N, CONTENT_MIN_HEIGHT as V, CONTENT_INSET_VAR as K } from "./constants.js";
10
+ import N from "../Typography/Text.js";
11
+ import { safeHref as y } from "../safeHref.js";
12
+ import { CARD_MIN_HEIGHT as G, CARD_RADIUS as L, CARD_CLASSES as z, HEADER_HEIGHT as U, DIVIDER_CLASSES as x, CONTENT_MIN_HEIGHT as V, CONTENT_INSET_VAR as K } from "./constants.js";
13
13
  const q = {
14
14
  small: 8,
15
15
  medium: 16,
16
16
  large: 24,
17
17
  xlarge: 40
18
- }, F = (l) => l.variant === "destructive" || l.variant === "error", J = (l) => {
19
- const e = x(l.href);
20
- return e ? () => window.open(e, l.target ?? "_blank", "noopener,noreferrer") : l.onClick;
21
- }, Q = (l) => l.flatMap((e, r) => {
22
- const i = {
18
+ }, F = (a) => a.variant === "destructive" || a.variant === "error", J = (a) => a.flatMap((e, r) => {
19
+ const i = y(e.href), c = {
23
20
  key: `${r}-${e.label}`,
24
21
  label: e.label,
25
- onClick: J(e),
22
+ ...i ? { href: i, target: e.target ?? "_blank" } : { onClick: e.onClick },
26
23
  disabled: e.disabled,
27
24
  icon: e.icon,
28
25
  tooltip: e.tooltip,
29
26
  danger: F(e)
30
27
  };
31
- return e.dividerBefore && r > 0 ? [{ type: "divider", key: `divider-${r}-${e.label}` }, i] : [i];
32
- }), W = ({ buttons: l }) => l.length === 0 ? null : /* @__PURE__ */ a("div", { className: "min-w-0", children: /* @__PURE__ */ a(
28
+ return e.dividerBefore && r > 0 ? [{ type: "divider", key: `divider-${r}-${e.label}` }, c] : [c];
29
+ }), Q = ({ buttons: a }) => a.length === 0 ? null : /* @__PURE__ */ l("div", { className: "min-w-0", children: /* @__PURE__ */ l(
33
30
  P,
34
31
  {
35
32
  gap: 8,
36
33
  justify: "end",
37
- renderOverflow: (e) => /* @__PURE__ */ a(
38
- u,
34
+ renderOverflow: (e) => /* @__PURE__ */ l(
35
+ $,
39
36
  {
40
- items: Q(
41
- l.slice(Math.max(0, l.length - e))
37
+ items: J(
38
+ a.slice(Math.max(0, a.length - e))
42
39
  )
43
40
  }
44
41
  ),
45
- children: l.map((e, r) => {
46
- const i = x(e.href);
42
+ children: a.map((e, r) => {
43
+ const i = y(e.href);
47
44
  return /* @__PURE__ */ s("div", { className: "flex items-center gap-2", children: [
48
- e.dividerBefore && r > 0 ? /* @__PURE__ */ a(
45
+ e.dividerBefore && r > 0 ? /* @__PURE__ */ l(
49
46
  "span",
50
47
  {
51
48
  "aria-hidden": "true",
52
49
  className: "h-4 w-px bg-[var(--malachite-card-border)]"
53
50
  }
54
51
  ) : null,
55
- /* @__PURE__ */ a(
56
- M,
52
+ /* @__PURE__ */ l(
53
+ u,
57
54
  {
58
55
  variant: e.variant ?? "filled",
59
56
  size: "medium",
@@ -70,54 +67,54 @@ const q = {
70
67
  ] }, `${r}-${e.label}`);
71
68
  })
72
69
  }
73
- ) }), X = [], Y = [], de = ({
74
- breadcrumbLinks: l = X,
70
+ ) }), W = [], X = [], de = ({
71
+ breadcrumbLinks: a = W,
75
72
  breadcrumbActions: e,
76
73
  renderLink: r,
77
74
  title: i,
78
- titleSuffix: y,
79
- subtitle: c,
80
- description: o,
81
- buttons: t = Y,
75
+ titleSuffix: c,
76
+ subtitle: t,
77
+ description: d,
78
+ buttons: o = X,
82
79
  loading: n = !1,
83
- children: w,
80
+ children: I,
84
81
  centered: f = !1,
85
- noPadding: h = !1,
86
- contentGap: I = "small",
87
- alert: d,
82
+ noPadding: p = !1,
83
+ contentGap: w = "small",
84
+ alert: m,
88
85
  role: _,
89
86
  "aria-label": T,
90
- "aria-labelledby": A,
91
- className: E = "",
92
- style: S
87
+ "aria-labelledby": E,
88
+ className: S = "",
89
+ style: k
93
90
  }) => {
94
- const k = O(l), C = h ? 0 : f ? "5vh 14vw" : "40px", H = h ? "0px" : f ? "14vw" : "40px", B = !!(n || i || c || o || t.length > 0), p = c ? n ? /* @__PURE__ */ a(m.Input, { width: 120, height: 24 }) : /* @__PURE__ */ a(v, { color: "secondary", size: "small", children: c }) : null, g = n ? /* @__PURE__ */ a(m.Input, { width: 200, height: 40 }) : i ? /* @__PURE__ */ s("div", { className: "flex items-center", style: { gap: 12 }, children: [
95
- /* @__PURE__ */ a(j, { children: i }),
96
- y
97
- ] }) : null, R = o ? n ? /* @__PURE__ */ a(m.Input, { width: 120, height: 24 }) : /* @__PURE__ */ a(v, { color: "secondary", style: { lineHeight: 1.6 }, children: o }) : null;
91
+ const A = M(a), C = p ? 0 : f ? "5vh 14vw" : "40px", H = p ? "0px" : f ? "14vw" : "40px", B = !!(n || i || t || d || o.length > 0), g = t ? n ? /* @__PURE__ */ l(h.Input, { width: 120, height: 24 }) : /* @__PURE__ */ l(N, { color: "secondary", size: "small", children: t }) : null, v = n ? /* @__PURE__ */ l(h.Input, { width: 200, height: 40 }) : i ? /* @__PURE__ */ s("div", { className: "flex items-center", style: { gap: 12 }, children: [
92
+ /* @__PURE__ */ l(j, { children: i }),
93
+ c
94
+ ] }) : null, R = d ? n ? /* @__PURE__ */ l(h.Input, { width: 120, height: 24 }) : /* @__PURE__ */ l(N, { color: "secondary", style: { lineHeight: 1.6 }, children: d }) : null;
98
95
  return /* @__PURE__ */ s(
99
96
  "main",
100
97
  {
101
- className: `${z} ${E}`,
102
- style: { borderRadius: L, minHeight: G, ...S },
98
+ className: `${z} ${S}`,
99
+ style: { borderRadius: L, minHeight: G, ...k },
103
100
  role: _,
104
101
  "aria-label": T,
105
- "aria-labelledby": A,
102
+ "aria-labelledby": E,
106
103
  "aria-busy": n || void 0,
107
104
  children: [
108
- /* @__PURE__ */ a(
105
+ /* @__PURE__ */ l(
109
106
  "div",
110
107
  {
111
- className: `flex items-center ${N}`,
108
+ className: `flex items-center ${x}`,
112
109
  style: {
113
110
  height: U,
114
- paddingInlineStart: k ? 16 : 28,
111
+ paddingInlineStart: A ? 16 : 28,
115
112
  paddingInlineEnd: 16
116
113
  },
117
- children: /* @__PURE__ */ a(
118
- D,
114
+ children: /* @__PURE__ */ l(
115
+ O,
119
116
  {
120
- links: l,
117
+ links: a,
121
118
  actions: e,
122
119
  renderLink: r,
123
120
  className: "flex-1 min-w-0"
@@ -125,7 +122,7 @@ const q = {
125
122
  )
126
123
  }
127
124
  ),
128
- d ? /* @__PURE__ */ a("div", { className: N, style: { padding: "10px 16px" }, children: /* @__PURE__ */ a($, { message: d.message, type: d.type, hasMargin: !1 }) }) : null,
125
+ m ? /* @__PURE__ */ l("div", { className: x, style: { padding: "10px 16px" }, children: /* @__PURE__ */ l(D, { message: m.message, type: m.type, hasMargin: !1 }) }) : null,
129
126
  /* @__PURE__ */ s(
130
127
  "div",
131
128
  {
@@ -133,12 +130,12 @@ const q = {
133
130
  style: {
134
131
  padding: C,
135
132
  minHeight: V,
136
- gap: q[I],
133
+ gap: q[w],
137
134
  [K]: H
138
135
  },
139
136
  children: [
140
137
  B ? /* @__PURE__ */ s("div", { className: "flex flex-col", style: { gap: 12 }, children: [
141
- g || p || t.length > 0 ? /* @__PURE__ */ s(
138
+ v || g || o.length > 0 ? /* @__PURE__ */ s(
142
139
  "div",
143
140
  {
144
141
  className: "flex flex-wrap items-center justify-between",
@@ -150,18 +147,18 @@ const q = {
150
147
  className: "flex flex-col flex-auto min-w-0 overflow-hidden",
151
148
  style: { gap: 4 },
152
149
  children: [
153
- p,
154
- g
150
+ g,
151
+ v
155
152
  ]
156
153
  }
157
154
  ),
158
- n ? null : /* @__PURE__ */ a(W, { buttons: t })
155
+ n ? null : /* @__PURE__ */ l(Q, { buttons: o })
159
156
  ]
160
157
  }
161
158
  ) : null,
162
159
  R
163
160
  ] }) : null,
164
- w
161
+ I
165
162
  ]
166
163
  }
167
164
  )
@@ -170,7 +167,7 @@ const q = {
170
167
  );
171
168
  };
172
169
  export {
173
- W as PageActions,
170
+ Q as PageActions,
174
171
  de as RegularLayout,
175
172
  de as default
176
173
  };
@@ -1 +1 @@
1
- {"version":3,"file":"regularLayout.js","sources":["../../../src/components/PageLayout/regularLayout.tsx"],"sourcesContent":["import React from 'react';\nimport ActionMenu, { type ActionMenuItem } from '../ActionMenu';\nimport Alert, { type AlertType } from '../Alert';\nimport Breadcrumbs from '../Breadcrumbs';\nimport { hasBackButton } from '../breadcrumbsNav';\nimport Button from '../Button';\nimport OverflowRow from '../OverflowRow';\nimport Skeleton from '../Skeleton';\nimport PageTitle from '../Typography/PageTitle';\nimport Text from '../Typography/Text';\nimport { safeHref } from '../safeHref';\nimport {\n CARD_CLASSES,\n CARD_MIN_HEIGHT,\n CARD_RADIUS,\n CONTENT_INSET_VAR,\n CONTENT_MIN_HEIGHT,\n DIVIDER_CLASSES,\n HEADER_HEIGHT,\n} from './constants';\nimport type { BreadcrumbLink, PageAction, RenderBreadcrumbLink } from './types';\n\nexport type PageContentGap = 'small' | 'medium' | 'large' | 'xlarge';\n\nexport interface RegularLayoutProps {\n breadcrumbLinks?: BreadcrumbLink[];\n breadcrumbActions?: PageAction[];\n renderLink?: RenderBreadcrumbLink;\n title?: React.ReactNode;\n titleSuffix?: React.ReactNode;\n subtitle?: string;\n description?: React.ReactNode;\n buttons?: PageAction[];\n /**\n * Hides the buttons and skeletons the title. `subtitle` and `description` are only\n * skeletoned when those props are also passed.\n */\n loading?: boolean;\n children: React.ReactNode;\n centered?: boolean;\n noPadding?: boolean;\n contentGap?: PageContentGap;\n alert?: { message: string; type?: AlertType };\n /** Demotes the default `main` landmark — pass e.g. `region` when the app owns its own. */\n role?: React.AriaRole;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst CONTENT_GAPS: Record<PageContentGap, number> = {\n small: 8,\n medium: 16,\n large: 24,\n xlarge: 40,\n};\n\nconst isDanger = (button: PageAction): boolean =>\n button.variant === 'destructive' || button.variant === 'error';\n\n// ActionMenuItem has no link form, so a collapsed link action opens the tab itself.\nconst menuAction = (button: PageAction): (() => void) | undefined => {\n const href = safeHref(button.href);\n if (!href) {\n return button.onClick;\n }\n return () => window.open(href, button.target ?? '_blank', 'noopener,noreferrer');\n};\n\nconst toMenuItems = (buttons: PageAction[]): ActionMenuItem[] =>\n buttons.flatMap((button, index) => {\n const item: ActionMenuItem = {\n key: `${index}-${button.label}`,\n label: button.label,\n onClick: menuAction(button),\n disabled: button.disabled,\n icon: button.icon,\n tooltip: button.tooltip,\n danger: isDanger(button),\n };\n return button.dividerBefore && index > 0\n ? [{ type: 'divider' as const, key: `divider-${index}-${button.label}` }, item]\n : [item];\n });\n\n// Not `ActionBar`: it measures by walking ancestors for `clientWidth`, and this chrome\n// mounts on every page. OverflowRow batches its measurement instead.\n// A divider must live in the same OverflowRow child as its button — a standalone child\n// would survive its hidden button and break the child-index-to-button mapping.\n/**\n * The page's action buttons, collapsing into an overflow menu as the row narrows. Exported so\n * a page that renders its own header block — e.g. one that scrolls the title away — keeps the\n * same behaviour instead of hand-rolling `buttons.map(...)` and losing the collapse, the\n * dividers and the href handling.\n */\nexport const PageActions: React.FC<{ buttons: PageAction[] }> = ({ buttons }) => {\n if (buttons.length === 0) {\n return null;\n }\n\n // min-w-0 gives OverflowRow a shrinkable container to collapse against.\n return (\n <div className=\"min-w-0\">\n <OverflowRow\n gap={8}\n justify=\"end\"\n renderOverflow={(hiddenCount) => (\n <ActionMenu\n items={toMenuItems(\n buttons.slice(Math.max(0, buttons.length - hiddenCount)),\n )}\n />\n )}\n >\n {buttons.map((button, index) => {\n const href = safeHref(button.href);\n return (\n <div key={`${index}-${button.label}`} className=\"flex items-center gap-2\">\n {button.dividerBefore && index > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"h-4 w-px bg-[var(--malachite-card-border)]\"\n />\n ) : null}\n <Button\n variant={button.variant ?? 'filled'}\n size=\"medium\"\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n tooltipPlacement={button.tooltipPlacement}\n href={href}\n target={href ? (button.target ?? '_blank') : undefined}\n onClick={href ? undefined : button.onClick}\n >\n {button.label}\n </Button>\n </div>\n );\n })}\n </OverflowRow>\n </div>\n );\n};\n\nconst NO_LINKS: BreadcrumbLink[] = [];\nconst NO_BUTTONS: PageAction[] = [];\n\nconst RegularLayout: React.FC<RegularLayoutProps> = ({\n breadcrumbLinks = NO_LINKS,\n breadcrumbActions,\n renderLink,\n title,\n titleSuffix,\n subtitle,\n description,\n buttons = NO_BUTTONS,\n loading = false,\n children,\n centered = false,\n noPadding = false,\n contentGap = 'small',\n alert,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n style,\n}) => {\n const hasBack = hasBackButton(breadcrumbLinks);\n const contentPadding = noPadding ? 0 : centered ? '5vh 14vw' : '40px';\n // Published so a full-bleed child (CardStrip's bottom rule) can cancel it and re-apply\n // it as its own padding, instead of hardcoding the gutter at the call site.\n const contentInset = noPadding ? '0px' : centered ? '14vw' : '40px';\n const hasHeaderBlock = Boolean(\n loading || title || subtitle || description || buttons.length > 0,\n );\n\n const subtitleNode = subtitle ? (\n loading ? (\n <Skeleton.Input width={120} height={24} />\n ) : (\n <Text color=\"secondary\" size=\"small\">\n {subtitle}\n </Text>\n )\n ) : null;\n\n const titleNode = loading ? (\n <Skeleton.Input width={200} height={40} />\n ) : title ? (\n <div className=\"flex items-center\" style={{ gap: 12 }}>\n <PageTitle>{title}</PageTitle>\n {titleSuffix}\n </div>\n ) : null;\n\n const descriptionNode = description ? (\n loading ? (\n <Skeleton.Input width={120} height={24} />\n ) : (\n <Text color=\"secondary\" style={{ lineHeight: 1.6 }}>\n {description}\n </Text>\n )\n ) : null;\n\n return (\n <main\n className={`${CARD_CLASSES} ${className}`}\n style={{ borderRadius: CARD_RADIUS, minHeight: CARD_MIN_HEIGHT, ...style }}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-busy={loading || undefined}\n >\n <div\n className={`flex items-center ${DIVIDER_CLASSES}`}\n style={{\n height: HEADER_HEIGHT,\n paddingInlineStart: hasBack ? 16 : 28,\n paddingInlineEnd: 16,\n }}\n >\n <Breadcrumbs\n links={breadcrumbLinks}\n actions={breadcrumbActions}\n renderLink={renderLink}\n className=\"flex-1 min-w-0\"\n />\n </div>\n\n {alert ? (\n <div className={DIVIDER_CLASSES} style={{ padding: '10px 16px' }}>\n <Alert message={alert.message} type={alert.type} hasMargin={false} />\n </div>\n ) : null}\n\n <div\n className=\"flex flex-col\"\n style={\n {\n padding: contentPadding,\n minHeight: CONTENT_MIN_HEIGHT,\n gap: CONTENT_GAPS[contentGap],\n [CONTENT_INSET_VAR]: contentInset,\n } as React.CSSProperties\n }\n >\n {hasHeaderBlock ? (\n <div className=\"flex flex-col\" style={{ gap: 12 }}>\n {titleNode || subtitleNode || buttons.length > 0 ? (\n <div\n className=\"flex flex-wrap items-center justify-between\"\n style={{ gap: 12 }}\n >\n <div\n className=\"flex flex-col flex-auto min-w-0 overflow-hidden\"\n style={{ gap: 4 }}\n >\n {subtitleNode}\n {titleNode}\n </div>\n {loading ? null : <PageActions buttons={buttons} />}\n </div>\n ) : null}\n {descriptionNode}\n </div>\n ) : null}\n {children}\n </div>\n </main>\n );\n};\n\nexport default RegularLayout;\nexport { RegularLayout };\n"],"names":["CONTENT_GAPS","isDanger","button","menuAction","href","safeHref","toMenuItems","buttons","index","item","PageActions","jsx","OverflowRow","hiddenCount","ActionMenu","jsxs","Button","NO_LINKS","NO_BUTTONS","RegularLayout","breadcrumbLinks","breadcrumbActions","renderLink","title","titleSuffix","subtitle","description","loading","children","centered","noPadding","contentGap","alert","role","ariaLabel","ariaLabelledBy","className","style","hasBack","hasBackButton","contentPadding","contentInset","hasHeaderBlock","subtitleNode","Skeleton","Text","titleNode","PageTitle","descriptionNode","CARD_CLASSES","CARD_RADIUS","CARD_MIN_HEIGHT","DIVIDER_CLASSES","HEADER_HEIGHT","Breadcrumbs","Alert","CONTENT_MIN_HEIGHT","CONTENT_INSET_VAR"],"mappings":"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"}
1
+ {"version":3,"file":"regularLayout.js","sources":["../../../src/components/PageLayout/regularLayout.tsx"],"sourcesContent":["import React from 'react';\nimport ActionMenu, { type ActionMenuItem } from '../ActionMenu';\nimport Alert, { type AlertType } from '../Alert';\nimport Breadcrumbs from '../Breadcrumbs';\nimport { hasBackButton } from '../breadcrumbsNav';\nimport Button from '../Button';\nimport OverflowRow from '../OverflowRow';\nimport Skeleton from '../Skeleton';\nimport PageTitle from '../Typography/PageTitle';\nimport Text from '../Typography/Text';\nimport { safeHref } from '../safeHref';\nimport {\n CARD_CLASSES,\n CARD_MIN_HEIGHT,\n CARD_RADIUS,\n CONTENT_INSET_VAR,\n CONTENT_MIN_HEIGHT,\n DIVIDER_CLASSES,\n HEADER_HEIGHT,\n} from './constants';\nimport type { BreadcrumbLink, PageAction, RenderBreadcrumbLink } from './types';\n\nexport type PageContentGap = 'small' | 'medium' | 'large' | 'xlarge';\n\nexport interface RegularLayoutProps {\n breadcrumbLinks?: BreadcrumbLink[];\n breadcrumbActions?: PageAction[];\n renderLink?: RenderBreadcrumbLink;\n title?: React.ReactNode;\n titleSuffix?: React.ReactNode;\n subtitle?: string;\n description?: React.ReactNode;\n buttons?: PageAction[];\n /**\n * Hides the buttons and skeletons the title. `subtitle` and `description` are only\n * skeletoned when those props are also passed.\n */\n loading?: boolean;\n children: React.ReactNode;\n centered?: boolean;\n noPadding?: boolean;\n contentGap?: PageContentGap;\n alert?: { message: string; type?: AlertType };\n /** Demotes the default `main` landmark — pass e.g. `region` when the app owns its own. */\n role?: React.AriaRole;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst CONTENT_GAPS: Record<PageContentGap, number> = {\n small: 8,\n medium: 16,\n large: 24,\n xlarge: 40,\n};\n\nconst isDanger = (button: PageAction): boolean =>\n button.variant === 'destructive' || button.variant === 'error';\n\nconst toMenuItems = (buttons: PageAction[]): ActionMenuItem[] =>\n buttons.flatMap((button, index) => {\n const href = safeHref(button.href);\n const item: ActionMenuItem = {\n key: `${index}-${button.label}`,\n label: button.label,\n ...(href ? { href, target: button.target ?? '_blank' } : { onClick: button.onClick }),\n disabled: button.disabled,\n icon: button.icon,\n tooltip: button.tooltip,\n danger: isDanger(button),\n };\n return button.dividerBefore && index > 0\n ? [{ type: 'divider' as const, key: `divider-${index}-${button.label}` }, item]\n : [item];\n });\n\n// Not `ActionBar`: it measures by walking ancestors for `clientWidth`, and this chrome\n// mounts on every page. OverflowRow batches its measurement instead.\n// A divider must live in the same OverflowRow child as its button — a standalone child\n// would survive its hidden button and break the child-index-to-button mapping.\n/**\n * The page's action buttons, collapsing into an overflow menu as the row narrows. Exported so\n * a page that renders its own header block — e.g. one that scrolls the title away — keeps the\n * same behaviour instead of hand-rolling `buttons.map(...)` and losing the collapse, the\n * dividers and the href handling.\n */\nexport const PageActions: React.FC<{ buttons: PageAction[] }> = ({ buttons }) => {\n if (buttons.length === 0) {\n return null;\n }\n\n // min-w-0 gives OverflowRow a shrinkable container to collapse against.\n return (\n <div className=\"min-w-0\">\n <OverflowRow\n gap={8}\n justify=\"end\"\n renderOverflow={(hiddenCount) => (\n <ActionMenu\n items={toMenuItems(\n buttons.slice(Math.max(0, buttons.length - hiddenCount)),\n )}\n />\n )}\n >\n {buttons.map((button, index) => {\n const href = safeHref(button.href);\n return (\n <div key={`${index}-${button.label}`} className=\"flex items-center gap-2\">\n {button.dividerBefore && index > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"h-4 w-px bg-[var(--malachite-card-border)]\"\n />\n ) : null}\n <Button\n variant={button.variant ?? 'filled'}\n size=\"medium\"\n disabled={button.disabled}\n icon={button.icon}\n tooltip={button.tooltip}\n tooltipPlacement={button.tooltipPlacement}\n href={href}\n target={href ? (button.target ?? '_blank') : undefined}\n onClick={href ? undefined : button.onClick}\n >\n {button.label}\n </Button>\n </div>\n );\n })}\n </OverflowRow>\n </div>\n );\n};\n\nconst NO_LINKS: BreadcrumbLink[] = [];\nconst NO_BUTTONS: PageAction[] = [];\n\nconst RegularLayout: React.FC<RegularLayoutProps> = ({\n breadcrumbLinks = NO_LINKS,\n breadcrumbActions,\n renderLink,\n title,\n titleSuffix,\n subtitle,\n description,\n buttons = NO_BUTTONS,\n loading = false,\n children,\n centered = false,\n noPadding = false,\n contentGap = 'small',\n alert,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n style,\n}) => {\n const hasBack = hasBackButton(breadcrumbLinks);\n const contentPadding = noPadding ? 0 : centered ? '5vh 14vw' : '40px';\n // Published so a full-bleed child (CardStrip's bottom rule) can cancel it and re-apply\n // it as its own padding, instead of hardcoding the gutter at the call site.\n const contentInset = noPadding ? '0px' : centered ? '14vw' : '40px';\n const hasHeaderBlock = Boolean(\n loading || title || subtitle || description || buttons.length > 0,\n );\n\n const subtitleNode = subtitle ? (\n loading ? (\n <Skeleton.Input width={120} height={24} />\n ) : (\n <Text color=\"secondary\" size=\"small\">\n {subtitle}\n </Text>\n )\n ) : null;\n\n const titleNode = loading ? (\n <Skeleton.Input width={200} height={40} />\n ) : title ? (\n <div className=\"flex items-center\" style={{ gap: 12 }}>\n <PageTitle>{title}</PageTitle>\n {titleSuffix}\n </div>\n ) : null;\n\n const descriptionNode = description ? (\n loading ? (\n <Skeleton.Input width={120} height={24} />\n ) : (\n <Text color=\"secondary\" style={{ lineHeight: 1.6 }}>\n {description}\n </Text>\n )\n ) : null;\n\n return (\n <main\n className={`${CARD_CLASSES} ${className}`}\n style={{ borderRadius: CARD_RADIUS, minHeight: CARD_MIN_HEIGHT, ...style }}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-busy={loading || undefined}\n >\n <div\n className={`flex items-center ${DIVIDER_CLASSES}`}\n style={{\n height: HEADER_HEIGHT,\n paddingInlineStart: hasBack ? 16 : 28,\n paddingInlineEnd: 16,\n }}\n >\n <Breadcrumbs\n links={breadcrumbLinks}\n actions={breadcrumbActions}\n renderLink={renderLink}\n className=\"flex-1 min-w-0\"\n />\n </div>\n\n {alert ? (\n <div className={DIVIDER_CLASSES} style={{ padding: '10px 16px' }}>\n <Alert message={alert.message} type={alert.type} hasMargin={false} />\n </div>\n ) : null}\n\n <div\n className=\"flex flex-col\"\n style={\n {\n padding: contentPadding,\n minHeight: CONTENT_MIN_HEIGHT,\n gap: CONTENT_GAPS[contentGap],\n [CONTENT_INSET_VAR]: contentInset,\n } as React.CSSProperties\n }\n >\n {hasHeaderBlock ? (\n <div className=\"flex flex-col\" style={{ gap: 12 }}>\n {titleNode || subtitleNode || buttons.length > 0 ? (\n <div\n className=\"flex flex-wrap items-center justify-between\"\n style={{ gap: 12 }}\n >\n <div\n className=\"flex flex-col flex-auto min-w-0 overflow-hidden\"\n style={{ gap: 4 }}\n >\n {subtitleNode}\n {titleNode}\n </div>\n {loading ? null : <PageActions buttons={buttons} />}\n </div>\n ) : null}\n {descriptionNode}\n </div>\n ) : null}\n {children}\n </div>\n </main>\n );\n};\n\nexport default RegularLayout;\nexport { RegularLayout };\n"],"names":["CONTENT_GAPS","isDanger","button","toMenuItems","buttons","index","href","safeHref","item","PageActions","jsx","OverflowRow","hiddenCount","ActionMenu","jsxs","Button","NO_LINKS","NO_BUTTONS","RegularLayout","breadcrumbLinks","breadcrumbActions","renderLink","title","titleSuffix","subtitle","description","loading","children","centered","noPadding","contentGap","alert","role","ariaLabel","ariaLabelledBy","className","style","hasBack","hasBackButton","contentPadding","contentInset","hasHeaderBlock","subtitleNode","Skeleton","Text","titleNode","PageTitle","descriptionNode","CARD_CLASSES","CARD_RADIUS","CARD_MIN_HEIGHT","DIVIDER_CLASSES","HEADER_HEIGHT","Breadcrumbs","Alert","CONTENT_MIN_HEIGHT","CONTENT_INSET_VAR"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as n, jsxs as W } from "react/jsx-runtime";
2
- import { useRef as $, useState as A, useCallback as B } from "react";
2
+ import { useRef as C, useState as A, useCallback as B } from "react";
3
3
  import U from "./CustomIcons/DismissIcon.js";
4
4
  import { FOCUS_RING as E } from "./focusRing.js";
5
5
  import { activateOnEnterOrSpace as G } from "./keyboardActivation.js";
@@ -79,62 +79,63 @@ const q = (e) => {
79
79
  bordered: i = !1,
80
80
  onClick: r,
81
81
  shadow: s = !1,
82
- textTransform: f = "uppercase",
82
+ textTransform: x = "uppercase",
83
83
  width: N,
84
- paddingSize: x = "default",
84
+ paddingSize: p = "default",
85
85
  icon: l,
86
- iconPosition: p = "left",
87
- iconColor: g,
86
+ iconPosition: g = "left",
87
+ iconColor: h,
88
88
  pointerType: u,
89
- onRemove: h,
89
+ onRemove: d,
90
90
  tooltip: m,
91
91
  tooltipDescribesTag: z = !0,
92
92
  className: O = ""
93
93
  }) => {
94
- const b = g ? { color: _(g) } : void 0, d = $(null), o = $(null), [T, j] = A(!1), v = typeof e == "string" || typeof e == "number", k = B((t) => {
94
+ const b = h ? { color: _(h) } : void 0, f = C(null), o = C(null), [T, j] = A(!1), v = typeof e == "string" || typeof e == "number", I = B((t) => {
95
95
  var S;
96
- if ((S = d.current) == null || S.disconnect(), d.current = null, o.current !== null && (cancelAnimationFrame(o.current), o.current = null), !t || typeof ResizeObserver > "u")
96
+ if ((S = f.current) == null || S.disconnect(), f.current = null, o.current !== null && (cancelAnimationFrame(o.current), o.current = null), !t || typeof ResizeObserver > "u")
97
97
  return;
98
98
  const L = () => {
99
99
  o.current = null, t.clientWidth !== 0 && j((R) => {
100
- const C = t.scrollWidth > t.clientWidth;
101
- return R === C ? R : C;
100
+ const $ = t.scrollWidth > t.clientWidth;
101
+ return R === $ ? R : $;
102
102
  });
103
103
  }, w = () => {
104
104
  o.current === null && (o.current = requestAnimationFrame(L));
105
105
  };
106
- w(), d.current = Y(t, w);
107
- }, []), I = (t) => {
106
+ w(), f.current = Y(t, w);
107
+ }, []), k = (t) => {
108
108
  r && (t.stopPropagation(), t.preventDefault(), r());
109
109
  }, D = [
110
110
  K(N),
111
- M(a, x, c),
112
- f === "uppercase" ? "uppercase" : "normal-case",
111
+ M(a, p, c),
112
+ x === "uppercase" ? "uppercase" : "normal-case",
113
113
  r ? `cursor-pointer ${E}` : u ? `cursor-${u}` : "",
114
114
  v ? "min-w-0 max-w-full" : "",
115
115
  O
116
116
  ].filter(Boolean).join(" "), F = {
117
- ...X(a, i, s, x),
117
+ ...X(a, i, s, p),
118
118
  ...!r && !u && { cursor: V }
119
119
  }, y = /* @__PURE__ */ W(
120
120
  "span",
121
121
  {
122
122
  className: D,
123
- onClick: I,
123
+ onClick: k,
124
+ role: r && !d ? "button" : void 0,
124
125
  tabIndex: r ? 0 : void 0,
125
126
  onKeyDown: r ? (t) => G(t, r) : void 0,
126
127
  style: F,
127
128
  children: [
128
- l && p === "left" && /* @__PURE__ */ n("span", { className: "mr-1 flex items-center", style: b, children: l }),
129
- v ? /* @__PURE__ */ n("span", { className: "flex items-center min-w-0", children: /* @__PURE__ */ n("span", { ref: k, className: "block min-w-0 truncate", children: e }, String(e)) }) : /* @__PURE__ */ n("span", { className: "flex items-center", children: e }),
130
- l && p === "right" && /* @__PURE__ */ n("span", { className: "ml-1 flex items-center", style: b, children: l }),
131
- h && /* @__PURE__ */ n(
129
+ l && g === "left" && /* @__PURE__ */ n("span", { className: "mr-1 flex items-center", style: b, children: l }),
130
+ v ? /* @__PURE__ */ n("span", { className: "flex items-center min-w-0", children: /* @__PURE__ */ n("span", { ref: I, className: "block min-w-0 truncate", children: e }, String(e)) }) : /* @__PURE__ */ n("span", { className: "flex items-center", children: e }),
131
+ l && g === "right" && /* @__PURE__ */ n("span", { className: "ml-1 flex items-center", style: b, children: l }),
132
+ d && /* @__PURE__ */ n(
132
133
  "button",
133
134
  {
134
135
  type: "button",
135
136
  "aria-label": `Remove ${typeof e == "string" ? e : ""}`,
136
137
  onClick: (t) => {
137
- t.stopPropagation(), h(t);
138
+ t.stopPropagation(), d(t);
138
139
  },
139
140
  className: "ml-0.5 flex items-center justify-center shrink-0 border-none bg-transparent text-current cursor-pointer p-0 leading-none opacity-70 hover:opacity-100",
140
141
  children: /* @__PURE__ */ n(U, { size: 9 })
@@ -1 +1 @@
1
- {"version":3,"file":"Tag.js","sources":["../../src/components/Tag.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport { FOCUS_RING } from './focusRing';\nimport { activateOnEnterOrSpace } from './keyboardActivation';\nimport Tooltip from './Tooltip';\nimport type { TextColor } from './Typography/Text';\nimport { getTextColor } from './Typography/textStyles';\n\nexport type TagType =\n | 'primary'\n | 'secondary'\n | 'default'\n | 'error'\n | 'warning'\n | 'success'\n | 'emphasis'\n | 'info'\n /** Marks content a machine produced rather than a person — provenance, not severity. */\n | 'assistant';\n\nexport type WidthSize = 'large' | 'medium' | 'small' | 'xsmall';\n\nexport type PaddingSize = 'default' | 'compact';\n\ntype TagFontSize = 'xsmall' | 'small' | 'medium';\n\ninterface TagProps {\n value: string | number | React.ReactNode;\n /** Defaults to 12px. Use `xsmall` for a secondary badge beside a primary one. */\n fontSize?: TagFontSize;\n type?: TagType;\n bordered?: boolean;\n shadow?: boolean;\n textTransform?: 'none' | 'uppercase';\n width?: WidthSize;\n paddingSize?: PaddingSize;\n icon?: React.ReactNode;\n iconPosition?: 'left' | 'right';\n iconColor?: TextColor;\n /** The cursor over a tag that is not clickable. Unset, it is whatever an ancestor sets\n * through `--malachite-ctx-tag-cursor` (a `NavItem` row sets its pointer), else the arrow. */\n pointerType?: 'pointer' | 'default';\n onClick?: () => void;\n onRemove?: (e: React.MouseEvent) => void;\n /** Explains the tag on hover. Takes the place of the truncation tooltip, which only repeats\n * the label. */\n tooltip?: string;\n /** False when something else already reads `tooltip` to assistive tech, such as a card's\n * description, so it is not announced twice. */\n tooltipDescribesTag?: boolean;\n className?: string;\n}\n\nconst getFontSizeClass = (fontSize?: TagFontSize): string => {\n switch (fontSize) {\n case 'xsmall':\n return 'text-[length:var(--malachite-font-size-xsmall)]';\n case 'small':\n return 'text-[length:var(--malachite-font-size-small)]';\n case 'medium':\n return 'text-[length:var(--malachite-font-size-medium)]';\n default:\n return 'text-xs';\n }\n};\n\nconst getWidthClasses = (width?: WidthSize): string => {\n switch (width) {\n case 'large':\n return 'w-[88px]';\n case 'medium':\n return 'w-[44px]';\n case 'small':\n return 'w-[24px]';\n case 'xsmall':\n return 'w-[20px]';\n default:\n return 'w-fit';\n }\n};\n\nconst getPaddingClasses = (paddingSize?: PaddingSize): string => {\n return paddingSize === 'compact' ? 'px-[6px] py-[1px]' : 'px-2 py-1';\n};\n\nconst getBorderRadiusClasses = (paddingSize?: PaddingSize): React.CSSProperties => {\n return {\n borderRadius:\n paddingSize === 'compact' ? 'var(--malachite-radius-md)' : 'var(--malachite-radius-lg)',\n };\n};\n\nconst getTypeClasses = (\n type: TagType,\n paddingSize?: PaddingSize,\n fontSize?: TagFontSize,\n) => {\n const baseClasses = `inline-flex items-center justify-center ${getPaddingClasses(paddingSize)} ${getFontSizeClass(fontSize)} font-medium leading-normal tracking-[0.11px]`;\n\n const typeStyles = {\n primary: {\n text: 'text-[var(--malachite-tag-primary-foreground)]',\n },\n secondary: {\n text: 'text-[var(--malachite-tag-secondary-foreground)]',\n },\n default: {\n text: 'text-[var(--malachite-tag-default-foreground)]',\n },\n error: {\n text: 'text-[var(--malachite-tag-error-foreground)]',\n },\n warning: {\n text: 'text-[var(--malachite-tag-warning-foreground)]',\n },\n success: {\n text: 'text-[var(--malachite-tag-success-foreground)]',\n },\n emphasis: {\n text: 'text-[var(--malachite-tag-emphasis-foreground)]',\n },\n info: {\n text: 'text-[var(--malachite-tag-info-foreground)]',\n },\n assistant: {\n text: 'text-[var(--malachite-tag-assistant-foreground)]',\n },\n };\n\n const style = typeStyles[type];\n const classes = [baseClasses, style.text].filter(Boolean);\n\n return classes.join(' ');\n};\n\n/*\n * Context channels, not theme tokens: no palette value, not settable through `applyTheme`,\n * absent from `getCurrentTheme`. The ground goes under the tint, which is translucent and on\n * its own takes the colour of whatever is behind the tag, a row's hover or current tint included.\n */\nconst GROUND = 'var(--malachite-ctx-tag-ground, transparent)';\nconst IDLE_CURSOR = 'var(--malachite-ctx-tag-cursor, default)';\n\nconst getTypeStyles = (\n type: TagType,\n bordered?: boolean,\n shadow?: boolean,\n paddingSize?: PaddingSize,\n): React.CSSProperties => {\n const tint = `var(--malachite-tag-${type}-background)`;\n const styles: React.CSSProperties = {\n ...getBorderRadiusClasses(paddingSize),\n backgroundColor: GROUND,\n backgroundImage: `linear-gradient(${tint}, ${tint})`,\n };\n\n if (bordered) {\n styles.border = `2px solid var(--malachite-tag-${type}-border)`;\n }\n\n if (type === 'emphasis') {\n styles.boxShadow = '0px 0px 10px 0px var(--malachite-tag-emphasis-shadow)';\n } else if (shadow) {\n styles.boxShadow = `0 10px 15px -3px var(--malachite-tag-${type}-shadow)`;\n }\n\n return styles;\n};\n\nconst observeLabelSize = (el: HTMLSpanElement, onResize: () => void): ResizeObserver => {\n const observer = new ResizeObserver(onResize);\n observer.observe(el);\n return observer;\n};\n\nconst Tag: React.FC<TagProps> = ({\n value,\n fontSize,\n type = 'default',\n bordered = false,\n onClick,\n shadow = false,\n textTransform = 'uppercase',\n width,\n paddingSize = 'default',\n icon,\n iconPosition = 'left',\n iconColor,\n pointerType,\n onRemove,\n tooltip,\n tooltipDescribesTag = true,\n className = '',\n}) => {\n const iconColorStyle = iconColor ? { color: getTextColor(iconColor) } : undefined;\n const observerRef = useRef<ResizeObserver | null>(null);\n const frameRef = useRef<number | null>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n // Truncation applies to plain text labels; ReactNode values render untouched.\n const isTextLabel = typeof value === 'string' || typeof value === 'number';\n\n // Memoized so the ref keeps a stable identity. An inline ref callback would be\n // re-invoked (null, then the node) on every render, tearing down and recreating\n // the ResizeObserver each time; this way it only runs on mount/unmount.\n const setLabelRef = useCallback((el: HTMLSpanElement | null) => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (!el || typeof ResizeObserver === 'undefined') {\n return;\n }\n const measure = (): void => {\n frameRef.current = null;\n if (el.clientWidth === 0) {\n return;\n }\n setIsTruncated((prev) => {\n const next = el.scrollWidth > el.clientWidth;\n return prev === next ? prev : next;\n });\n };\n const check = (): void => {\n if (frameRef.current !== null) {\n return;\n }\n frameRef.current = requestAnimationFrame(measure);\n };\n check();\n observerRef.current = observeLabelSize(el, check);\n }, []);\n\n const handleClick = (e: React.MouseEvent) => {\n if (onClick) {\n e.stopPropagation();\n e.preventDefault();\n onClick();\n }\n };\n\n const baseClasses = [\n getWidthClasses(width),\n getTypeClasses(type, paddingSize, fontSize),\n textTransform === 'uppercase' ? 'uppercase' : 'normal-case',\n onClick ? `cursor-pointer ${FOCUS_RING}` : pointerType ? `cursor-${pointerType}` : '',\n isTextLabel ? 'min-w-0 max-w-full' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const typeStyles = {\n ...getTypeStyles(type, bordered, shadow, paddingSize),\n ...(!onClick && !pointerType && { cursor: IDLE_CURSOR }),\n };\n\n const tag = (\n <span\n className={baseClasses}\n onClick={handleClick}\n // No `role=\"button\"`: it takes presentational children, so a Tag carrying an\n // `onRemove` close button would hide that button from assistive tech.\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={onClick ? (event) => activateOnEnterOrSpace(event, onClick) : undefined}\n style={typeStyles}\n >\n {icon && iconPosition === 'left' && (\n <span className=\"mr-1 flex items-center\" style={iconColorStyle}>\n {icon}\n </span>\n )}\n {isTextLabel ? (\n <span className=\"flex items-center min-w-0\">\n <span key={String(value)} ref={setLabelRef} className=\"block min-w-0 truncate\">\n {value}\n </span>\n </span>\n ) : (\n <span className=\"flex items-center\">{value}</span>\n )}\n {icon && iconPosition === 'right' && (\n <span className=\"ml-1 flex items-center\" style={iconColorStyle}>\n {icon}\n </span>\n )}\n {onRemove && (\n <button\n type=\"button\"\n aria-label={`Remove ${typeof value === 'string' ? value : ''}`}\n onClick={(e) => {\n e.stopPropagation();\n onRemove(e);\n }}\n className=\"ml-0.5 flex items-center justify-center shrink-0 border-none bg-transparent text-current cursor-pointer p-0 leading-none opacity-70 hover:opacity-100\"\n >\n {/* A bare cross, not `CloseIcon`'s circled one: this sits inside the chip\n it removes, where a second enclosing ring reads as an object of its own\n rather than as part of the label. */}\n <DismissIcon size={9} />\n </button>\n )}\n </span>\n );\n\n if (!tooltip && !isTruncated) {\n return tag;\n }\n\n return (\n <Tooltip\n text={tooltip ?? value}\n placement=\"top\"\n wrapChildren={false}\n isShrinkable\n inline={tooltip !== undefined}\n describesTrigger={tooltip === undefined || tooltipDescribesTag}\n triggerAs=\"span\"\n >\n {tag}\n </Tooltip>\n );\n};\n\nexport default Tag;\nexport { Tag };\nexport type { TagProps };\n"],"names":["getFontSizeClass","fontSize","getWidthClasses","width","getPaddingClasses","paddingSize","getBorderRadiusClasses","getTypeClasses","type","baseClasses","style","GROUND","IDLE_CURSOR","getTypeStyles","bordered","shadow","tint","styles","observeLabelSize","el","onResize","observer","Tag","value","onClick","textTransform","icon","iconPosition","iconColor","pointerType","onRemove","tooltip","tooltipDescribesTag","className","iconColorStyle","getTextColor","observerRef","useRef","frameRef","isTruncated","setIsTruncated","useState","isTextLabel","setLabelRef","useCallback","_a","measure","prev","next","check","handleClick","e","FOCUS_RING","typeStyles","tag","jsxs","event","activateOnEnterOrSpace","jsx","DismissIcon","Tooltip"],"mappings":"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"}
1
+ {"version":3,"file":"Tag.js","sources":["../../src/components/Tag.tsx"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\nimport DismissIcon from './CustomIcons/DismissIcon';\nimport { FOCUS_RING } from './focusRing';\nimport { activateOnEnterOrSpace } from './keyboardActivation';\nimport Tooltip from './Tooltip';\nimport type { TextColor } from './Typography/Text';\nimport { getTextColor } from './Typography/textStyles';\n\nexport type TagType =\n | 'primary'\n | 'secondary'\n | 'default'\n | 'error'\n | 'warning'\n | 'success'\n | 'emphasis'\n | 'info'\n /** Marks content a machine produced rather than a person — provenance, not severity. */\n | 'assistant';\n\nexport type WidthSize = 'large' | 'medium' | 'small' | 'xsmall';\n\nexport type PaddingSize = 'default' | 'compact';\n\ntype TagFontSize = 'xsmall' | 'small' | 'medium';\n\ninterface TagProps {\n value: string | number | React.ReactNode;\n /** Defaults to 12px. Use `xsmall` for a secondary badge beside a primary one. */\n fontSize?: TagFontSize;\n type?: TagType;\n bordered?: boolean;\n shadow?: boolean;\n textTransform?: 'none' | 'uppercase';\n width?: WidthSize;\n paddingSize?: PaddingSize;\n icon?: React.ReactNode;\n iconPosition?: 'left' | 'right';\n iconColor?: TextColor;\n /** The cursor over a tag that is not clickable. Unset, it is whatever an ancestor sets\n * through `--malachite-ctx-tag-cursor` (a `NavItem` row sets its pointer), else the arrow. */\n pointerType?: 'pointer' | 'default';\n /** Makes it a button, unless `onRemove` is set; keep `value` and `icon` non-interactive. */\n onClick?: () => void;\n onRemove?: (e: React.MouseEvent) => void;\n /** Explains the tag on hover. Takes the place of the truncation tooltip, which only repeats\n * the label. */\n tooltip?: string;\n /** False when something else already reads `tooltip` to assistive tech, such as a card's\n * description, so it is not announced twice. */\n tooltipDescribesTag?: boolean;\n className?: string;\n}\n\nconst getFontSizeClass = (fontSize?: TagFontSize): string => {\n switch (fontSize) {\n case 'xsmall':\n return 'text-[length:var(--malachite-font-size-xsmall)]';\n case 'small':\n return 'text-[length:var(--malachite-font-size-small)]';\n case 'medium':\n return 'text-[length:var(--malachite-font-size-medium)]';\n default:\n return 'text-xs';\n }\n};\n\nconst getWidthClasses = (width?: WidthSize): string => {\n switch (width) {\n case 'large':\n return 'w-[88px]';\n case 'medium':\n return 'w-[44px]';\n case 'small':\n return 'w-[24px]';\n case 'xsmall':\n return 'w-[20px]';\n default:\n return 'w-fit';\n }\n};\n\nconst getPaddingClasses = (paddingSize?: PaddingSize): string => {\n return paddingSize === 'compact' ? 'px-[6px] py-[1px]' : 'px-2 py-1';\n};\n\nconst getBorderRadiusClasses = (paddingSize?: PaddingSize): React.CSSProperties => {\n return {\n borderRadius:\n paddingSize === 'compact' ? 'var(--malachite-radius-md)' : 'var(--malachite-radius-lg)',\n };\n};\n\nconst getTypeClasses = (\n type: TagType,\n paddingSize?: PaddingSize,\n fontSize?: TagFontSize,\n) => {\n const baseClasses = `inline-flex items-center justify-center ${getPaddingClasses(paddingSize)} ${getFontSizeClass(fontSize)} font-medium leading-normal tracking-[0.11px]`;\n\n const typeStyles = {\n primary: {\n text: 'text-[var(--malachite-tag-primary-foreground)]',\n },\n secondary: {\n text: 'text-[var(--malachite-tag-secondary-foreground)]',\n },\n default: {\n text: 'text-[var(--malachite-tag-default-foreground)]',\n },\n error: {\n text: 'text-[var(--malachite-tag-error-foreground)]',\n },\n warning: {\n text: 'text-[var(--malachite-tag-warning-foreground)]',\n },\n success: {\n text: 'text-[var(--malachite-tag-success-foreground)]',\n },\n emphasis: {\n text: 'text-[var(--malachite-tag-emphasis-foreground)]',\n },\n info: {\n text: 'text-[var(--malachite-tag-info-foreground)]',\n },\n assistant: {\n text: 'text-[var(--malachite-tag-assistant-foreground)]',\n },\n };\n\n const style = typeStyles[type];\n const classes = [baseClasses, style.text].filter(Boolean);\n\n return classes.join(' ');\n};\n\n/*\n * Context channels, not theme tokens: no palette value, not settable through `applyTheme`,\n * absent from `getCurrentTheme`. The ground goes under the tint, which is translucent and on\n * its own takes the colour of whatever is behind the tag, a row's hover or current tint included.\n */\nconst GROUND = 'var(--malachite-ctx-tag-ground, transparent)';\nconst IDLE_CURSOR = 'var(--malachite-ctx-tag-cursor, default)';\n\nconst getTypeStyles = (\n type: TagType,\n bordered?: boolean,\n shadow?: boolean,\n paddingSize?: PaddingSize,\n): React.CSSProperties => {\n const tint = `var(--malachite-tag-${type}-background)`;\n const styles: React.CSSProperties = {\n ...getBorderRadiusClasses(paddingSize),\n backgroundColor: GROUND,\n backgroundImage: `linear-gradient(${tint}, ${tint})`,\n };\n\n if (bordered) {\n styles.border = `2px solid var(--malachite-tag-${type}-border)`;\n }\n\n if (type === 'emphasis') {\n styles.boxShadow = '0px 0px 10px 0px var(--malachite-tag-emphasis-shadow)';\n } else if (shadow) {\n styles.boxShadow = `0 10px 15px -3px var(--malachite-tag-${type}-shadow)`;\n }\n\n return styles;\n};\n\nconst observeLabelSize = (el: HTMLSpanElement, onResize: () => void): ResizeObserver => {\n const observer = new ResizeObserver(onResize);\n observer.observe(el);\n return observer;\n};\n\nconst Tag: React.FC<TagProps> = ({\n value,\n fontSize,\n type = 'default',\n bordered = false,\n onClick,\n shadow = false,\n textTransform = 'uppercase',\n width,\n paddingSize = 'default',\n icon,\n iconPosition = 'left',\n iconColor,\n pointerType,\n onRemove,\n tooltip,\n tooltipDescribesTag = true,\n className = '',\n}) => {\n const iconColorStyle = iconColor ? { color: getTextColor(iconColor) } : undefined;\n const observerRef = useRef<ResizeObserver | null>(null);\n const frameRef = useRef<number | null>(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n // Truncation applies to plain text labels; ReactNode values render untouched.\n const isTextLabel = typeof value === 'string' || typeof value === 'number';\n\n // Memoized so the ref keeps a stable identity. An inline ref callback would be\n // re-invoked (null, then the node) on every render, tearing down and recreating\n // the ResizeObserver each time; this way it only runs on mount/unmount.\n const setLabelRef = useCallback((el: HTMLSpanElement | null) => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n if (frameRef.current !== null) {\n cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n if (!el || typeof ResizeObserver === 'undefined') {\n return;\n }\n const measure = (): void => {\n frameRef.current = null;\n if (el.clientWidth === 0) {\n return;\n }\n setIsTruncated((prev) => {\n const next = el.scrollWidth > el.clientWidth;\n return prev === next ? prev : next;\n });\n };\n const check = (): void => {\n if (frameRef.current !== null) {\n return;\n }\n frameRef.current = requestAnimationFrame(measure);\n };\n check();\n observerRef.current = observeLabelSize(el, check);\n }, []);\n\n const handleClick = (e: React.MouseEvent) => {\n if (onClick) {\n e.stopPropagation();\n e.preventDefault();\n onClick();\n }\n };\n\n const baseClasses = [\n getWidthClasses(width),\n getTypeClasses(type, paddingSize, fontSize),\n textTransform === 'uppercase' ? 'uppercase' : 'normal-case',\n onClick ? `cursor-pointer ${FOCUS_RING}` : pointerType ? `cursor-${pointerType}` : '',\n isTextLabel ? 'min-w-0 max-w-full' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const typeStyles = {\n ...getTypeStyles(type, bordered, shadow, paddingSize),\n ...(!onClick && !pointerType && { cursor: IDLE_CURSOR }),\n };\n\n const tag = (\n <span\n className={baseClasses}\n onClick={handleClick}\n // Not with `onRemove`: the role would hide its close button from assistive tech.\n role={onClick && !onRemove ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={onClick ? (event) => activateOnEnterOrSpace(event, onClick) : undefined}\n style={typeStyles}\n >\n {icon && iconPosition === 'left' && (\n <span className=\"mr-1 flex items-center\" style={iconColorStyle}>\n {icon}\n </span>\n )}\n {isTextLabel ? (\n <span className=\"flex items-center min-w-0\">\n <span key={String(value)} ref={setLabelRef} className=\"block min-w-0 truncate\">\n {value}\n </span>\n </span>\n ) : (\n <span className=\"flex items-center\">{value}</span>\n )}\n {icon && iconPosition === 'right' && (\n <span className=\"ml-1 flex items-center\" style={iconColorStyle}>\n {icon}\n </span>\n )}\n {onRemove && (\n <button\n type=\"button\"\n aria-label={`Remove ${typeof value === 'string' ? value : ''}`}\n onClick={(e) => {\n e.stopPropagation();\n onRemove(e);\n }}\n className=\"ml-0.5 flex items-center justify-center shrink-0 border-none bg-transparent text-current cursor-pointer p-0 leading-none opacity-70 hover:opacity-100\"\n >\n {/* A bare cross, not `CloseIcon`'s circled one: this sits inside the chip\n it removes, where a second enclosing ring reads as an object of its own\n rather than as part of the label. */}\n <DismissIcon size={9} />\n </button>\n )}\n </span>\n );\n\n if (!tooltip && !isTruncated) {\n return tag;\n }\n\n return (\n <Tooltip\n text={tooltip ?? value}\n placement=\"top\"\n wrapChildren={false}\n isShrinkable\n inline={tooltip !== undefined}\n describesTrigger={tooltip === undefined || tooltipDescribesTag}\n triggerAs=\"span\"\n >\n {tag}\n </Tooltip>\n );\n};\n\nexport default Tag;\nexport { Tag };\nexport type { TagProps };\n"],"names":["getFontSizeClass","fontSize","getWidthClasses","width","getPaddingClasses","paddingSize","getBorderRadiusClasses","getTypeClasses","type","baseClasses","style","GROUND","IDLE_CURSOR","getTypeStyles","bordered","shadow","tint","styles","observeLabelSize","el","onResize","observer","Tag","value","onClick","textTransform","icon","iconPosition","iconColor","pointerType","onRemove","tooltip","tooltipDescribesTag","className","iconColorStyle","getTextColor","observerRef","useRef","frameRef","isTruncated","setIsTruncated","useState","isTextLabel","setLabelRef","useCallback","_a","measure","prev","next","check","handleClick","e","FOCUS_RING","typeStyles","tag","jsxs","event","activateOnEnterOrSpace","jsx","DismissIcon","Tooltip"],"mappings":"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"}