@orangecheck/app-design 1.7.0 → 1.8.0

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.
@@ -469,9 +469,10 @@ declare function EmptyState({ title, children, action, icon, className, }: {
469
469
  className?: string;
470
470
  }): react.JSX.Element;
471
471
  type NoticeTone = 'neutral' | 'brand' | 'danger' | 'info' | 'success' | 'warning';
472
- declare function Notice({ tone, title, children, action, role, className, }: {
472
+ declare function Notice({ tone, title, children, action, icon, role, className, }: {
473
473
  tone?: NoticeTone;
474
474
  title?: ReactNode;
475
+ icon?: ReactNode;
475
476
  children?: ReactNode;
476
477
  action?: ReactNode;
477
478
  role?: 'alert' | 'status' | 'note';
@@ -573,7 +574,7 @@ declare function FloatChip({ icon, title, detail, delay, className, style, }: {
573
574
  style?: CSSProperties;
574
575
  }): react.JSX.Element;
575
576
 
576
- declare const SIZES: {
577
+ declare const SIZES$1: {
577
578
  readonly '2xs': "size-7 rounded-[0.55rem] text-[0.75rem]";
578
579
  readonly xs: "size-8 rounded-[0.6rem] text-[0.875rem]";
579
580
  readonly sm: "size-9 rounded-[0.7rem] text-[0.9375rem]";
@@ -585,7 +586,7 @@ declare function monogramGround(seed: string): number;
585
586
  declare function Monogram({ name, seed, size, className, style, }: {
586
587
  name: string;
587
588
  seed?: string;
588
- size?: keyof typeof SIZES;
589
+ size?: keyof typeof SIZES$1;
589
590
  className?: string;
590
591
  style?: CSSProperties;
591
592
  }): react.JSX.Element;
@@ -859,6 +860,22 @@ declare function SectionTitle({ title, meta, description, action, as: Tag, size,
859
860
  declare function ListCard({ as: Tag, className, ...props }: HTMLAttributes<HTMLElement> & {
860
861
  as?: 'ul' | 'ol' | 'div';
861
862
  }): react.JSX.Element;
863
+ declare function ListRow({ title, meta, description, leading, trailing, actions, revealActions, href, onSelect, current, unread, variant, as: Tag, className, }: {
864
+ title: ReactNode;
865
+ meta?: ReactNode;
866
+ description?: ReactNode;
867
+ leading?: ReactNode;
868
+ trailing?: ReactNode;
869
+ actions?: ReactNode;
870
+ revealActions?: 'always' | 'hover';
871
+ href?: string;
872
+ onSelect?: () => void;
873
+ current?: boolean;
874
+ unread?: boolean;
875
+ variant?: 'card' | 'pane';
876
+ as?: 'li' | 'div';
877
+ className?: string;
878
+ }): react.JSX.Element;
862
879
  declare function ChoiceGroup<T extends string>({ value, onValueChange, label, columns, size, disabled, className, children, }: {
863
880
  value: T | undefined;
864
881
  onValueChange: (value: T) => void;
@@ -878,6 +895,21 @@ declare function ChoiceCard({ value, title, description, icon, disabled, classNa
878
895
  className?: string;
879
896
  }): react.JSX.Element;
880
897
 
898
+ declare const SIZES: {
899
+ readonly '2xs': "size-7 text-[0.6875rem] [&_svg]:size-3.5";
900
+ readonly xs: "size-8 text-[0.75rem] [&_svg]:size-4";
901
+ readonly sm: "size-9 text-[0.8125rem] [&_svg]:size-4";
902
+ readonly md: "size-11 text-[0.9375rem] [&_svg]:size-5";
903
+ readonly lg: "size-14 text-[1.1875rem] [&_svg]:size-6";
904
+ };
905
+ declare function Avatar({ seed, name, src, size, className, }: {
906
+ seed: string;
907
+ name?: string | null;
908
+ src?: string | null;
909
+ size?: keyof typeof SIZES;
910
+ className?: string;
911
+ }): react.JSX.Element;
912
+
881
913
  interface SearchResult {
882
914
  id: string;
883
915
  href?: string;
@@ -917,4 +949,4 @@ interface SearchDialogProps {
917
949
  declare function SearchDialog({ onQuery, open: openProp, onOpenChange, onSelect, button, hotkey, label, placeholder, idle, defaultQuery, debounceMs, browse, className, }: SearchDialogProps): react.JSX.Element;
918
950
  declare function CommandDialog({ label, placeholder, ...props }: Omit<SearchDialogProps, 'browse' | 'button'>): react.JSX.Element;
919
951
 
920
- export { Accent, type ActivityItem, ActivityList, BrowserFrame, ChartFrame, type ChartTone, type CheckState, ChoiceCard, ChoiceGroup, Closing, type Column, CommandDialog, Container, CopyButton, type CopyButtonProps, CountdownRing, DataTable, Display, type DisplayProps, EmptyLine, EmptyState, type Endpoint, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, type FactRow, FactRows, Faq, FloatChip, Footnote, HashChip, HudCard, type KeyValueItem, KeyValueList, Lead, type LegalBlock, LegalDocument, type LegalSource, type LegendItem, ListCard, LoadingBlock, LockedPreview, Monogram, Notice, PackageCard, type PackageItem, PageHeader, Panel, PhoneFrame, PlanCard, type ProgressStep, ProgressSteps, ProofStrip, Prose, Reveal, Sats, SatsFigure, type SatsProps, type SatsTextOptions, ScrollStory, SearchButton, SearchDialog, type SearchDialogProps, type SearchGroup, type SearchQuery, type SearchResult, Section, SectionHeading, SectionIntro, type SectionProps, SectionTitle, SignMessage, SourceNote, type SourceNoteProps, Sparkline, SplitBar, type SplitSegment, StatCard, type StatCardProps, StatGrid, type StatGridProps, StepGrid, type StepGridProps, type StepItem, type StepState, TextLink, Ticker, type TruthRow, type TruthStatus, TruthTable, UsdApprox, type ValueTone, type VerifyCheck, VerifyReport, chartColor, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
952
+ export { Accent, type ActivityItem, ActivityList, Avatar, BrowserFrame, ChartFrame, type ChartTone, type CheckState, ChoiceCard, ChoiceGroup, Closing, type Column, CommandDialog, Container, CopyButton, type CopyButtonProps, CountdownRing, DataTable, Display, type DisplayProps, EmptyLine, EmptyState, type Endpoint, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, type FactRow, FactRows, Faq, FloatChip, Footnote, HashChip, HudCard, type KeyValueItem, KeyValueList, Lead, type LegalBlock, LegalDocument, type LegalSource, type LegendItem, ListCard, ListRow, LoadingBlock, LockedPreview, Monogram, Notice, PackageCard, type PackageItem, PageHeader, Panel, PhoneFrame, PlanCard, type ProgressStep, ProgressSteps, ProofStrip, Prose, Reveal, Sats, SatsFigure, type SatsProps, type SatsTextOptions, ScrollStory, SearchButton, SearchDialog, type SearchDialogProps, type SearchGroup, type SearchQuery, type SearchResult, Section, SectionHeading, SectionIntro, type SectionProps, SectionTitle, SignMessage, SourceNote, type SourceNoteProps, Sparkline, SplitBar, type SplitSegment, StatCard, type StatCardProps, StatGrid, type StatGridProps, StepGrid, type StepGridProps, type StepItem, type StepState, TextLink, Ticker, type TruthRow, type TruthStatus, TruthTable, UsdApprox, type ValueTone, type VerifyCheck, VerifyReport, chartColor, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
@@ -469,9 +469,10 @@ declare function EmptyState({ title, children, action, icon, className, }: {
469
469
  className?: string;
470
470
  }): react.JSX.Element;
471
471
  type NoticeTone = 'neutral' | 'brand' | 'danger' | 'info' | 'success' | 'warning';
472
- declare function Notice({ tone, title, children, action, role, className, }: {
472
+ declare function Notice({ tone, title, children, action, icon, role, className, }: {
473
473
  tone?: NoticeTone;
474
474
  title?: ReactNode;
475
+ icon?: ReactNode;
475
476
  children?: ReactNode;
476
477
  action?: ReactNode;
477
478
  role?: 'alert' | 'status' | 'note';
@@ -573,7 +574,7 @@ declare function FloatChip({ icon, title, detail, delay, className, style, }: {
573
574
  style?: CSSProperties;
574
575
  }): react.JSX.Element;
575
576
 
576
- declare const SIZES: {
577
+ declare const SIZES$1: {
577
578
  readonly '2xs': "size-7 rounded-[0.55rem] text-[0.75rem]";
578
579
  readonly xs: "size-8 rounded-[0.6rem] text-[0.875rem]";
579
580
  readonly sm: "size-9 rounded-[0.7rem] text-[0.9375rem]";
@@ -585,7 +586,7 @@ declare function monogramGround(seed: string): number;
585
586
  declare function Monogram({ name, seed, size, className, style, }: {
586
587
  name: string;
587
588
  seed?: string;
588
- size?: keyof typeof SIZES;
589
+ size?: keyof typeof SIZES$1;
589
590
  className?: string;
590
591
  style?: CSSProperties;
591
592
  }): react.JSX.Element;
@@ -859,6 +860,22 @@ declare function SectionTitle({ title, meta, description, action, as: Tag, size,
859
860
  declare function ListCard({ as: Tag, className, ...props }: HTMLAttributes<HTMLElement> & {
860
861
  as?: 'ul' | 'ol' | 'div';
861
862
  }): react.JSX.Element;
863
+ declare function ListRow({ title, meta, description, leading, trailing, actions, revealActions, href, onSelect, current, unread, variant, as: Tag, className, }: {
864
+ title: ReactNode;
865
+ meta?: ReactNode;
866
+ description?: ReactNode;
867
+ leading?: ReactNode;
868
+ trailing?: ReactNode;
869
+ actions?: ReactNode;
870
+ revealActions?: 'always' | 'hover';
871
+ href?: string;
872
+ onSelect?: () => void;
873
+ current?: boolean;
874
+ unread?: boolean;
875
+ variant?: 'card' | 'pane';
876
+ as?: 'li' | 'div';
877
+ className?: string;
878
+ }): react.JSX.Element;
862
879
  declare function ChoiceGroup<T extends string>({ value, onValueChange, label, columns, size, disabled, className, children, }: {
863
880
  value: T | undefined;
864
881
  onValueChange: (value: T) => void;
@@ -878,6 +895,21 @@ declare function ChoiceCard({ value, title, description, icon, disabled, classNa
878
895
  className?: string;
879
896
  }): react.JSX.Element;
880
897
 
898
+ declare const SIZES: {
899
+ readonly '2xs': "size-7 text-[0.6875rem] [&_svg]:size-3.5";
900
+ readonly xs: "size-8 text-[0.75rem] [&_svg]:size-4";
901
+ readonly sm: "size-9 text-[0.8125rem] [&_svg]:size-4";
902
+ readonly md: "size-11 text-[0.9375rem] [&_svg]:size-5";
903
+ readonly lg: "size-14 text-[1.1875rem] [&_svg]:size-6";
904
+ };
905
+ declare function Avatar({ seed, name, src, size, className, }: {
906
+ seed: string;
907
+ name?: string | null;
908
+ src?: string | null;
909
+ size?: keyof typeof SIZES;
910
+ className?: string;
911
+ }): react.JSX.Element;
912
+
881
913
  interface SearchResult {
882
914
  id: string;
883
915
  href?: string;
@@ -917,4 +949,4 @@ interface SearchDialogProps {
917
949
  declare function SearchDialog({ onQuery, open: openProp, onOpenChange, onSelect, button, hotkey, label, placeholder, idle, defaultQuery, debounceMs, browse, className, }: SearchDialogProps): react.JSX.Element;
918
950
  declare function CommandDialog({ label, placeholder, ...props }: Omit<SearchDialogProps, 'browse' | 'button'>): react.JSX.Element;
919
951
 
920
- export { Accent, type ActivityItem, ActivityList, BrowserFrame, ChartFrame, type ChartTone, type CheckState, ChoiceCard, ChoiceGroup, Closing, type Column, CommandDialog, Container, CopyButton, type CopyButtonProps, CountdownRing, DataTable, Display, type DisplayProps, EmptyLine, EmptyState, type Endpoint, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, type FactRow, FactRows, Faq, FloatChip, Footnote, HashChip, HudCard, type KeyValueItem, KeyValueList, Lead, type LegalBlock, LegalDocument, type LegalSource, type LegendItem, ListCard, LoadingBlock, LockedPreview, Monogram, Notice, PackageCard, type PackageItem, PageHeader, Panel, PhoneFrame, PlanCard, type ProgressStep, ProgressSteps, ProofStrip, Prose, Reveal, Sats, SatsFigure, type SatsProps, type SatsTextOptions, ScrollStory, SearchButton, SearchDialog, type SearchDialogProps, type SearchGroup, type SearchQuery, type SearchResult, Section, SectionHeading, SectionIntro, type SectionProps, SectionTitle, SignMessage, SourceNote, type SourceNoteProps, Sparkline, SplitBar, type SplitSegment, StatCard, type StatCardProps, StatGrid, type StatGridProps, StepGrid, type StepGridProps, type StepItem, type StepState, TextLink, Ticker, type TruthRow, type TruthStatus, TruthTable, UsdApprox, type ValueTone, type VerifyCheck, VerifyReport, chartColor, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
952
+ export { Accent, type ActivityItem, ActivityList, Avatar, BrowserFrame, ChartFrame, type ChartTone, type CheckState, ChoiceCard, ChoiceGroup, Closing, type Column, CommandDialog, Container, CopyButton, type CopyButtonProps, CountdownRing, DataTable, Display, type DisplayProps, EmptyLine, EmptyState, type Endpoint, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, type FactRow, FactRows, Faq, FloatChip, Footnote, HashChip, HudCard, type KeyValueItem, KeyValueList, Lead, type LegalBlock, LegalDocument, type LegalSource, type LegendItem, ListCard, ListRow, LoadingBlock, LockedPreview, Monogram, Notice, PackageCard, type PackageItem, PageHeader, Panel, PhoneFrame, PlanCard, type ProgressStep, ProgressSteps, ProofStrip, Prose, Reveal, Sats, SatsFigure, type SatsProps, type SatsTextOptions, ScrollStory, SearchButton, SearchDialog, type SearchDialogProps, type SearchGroup, type SearchQuery, type SearchResult, Section, SectionHeading, SectionIntro, type SectionProps, SectionTitle, SignMessage, SourceNote, type SourceNoteProps, Sparkline, SplitBar, type SplitSegment, StatCard, type StatCardProps, StatGrid, type StatGridProps, StepGrid, type StepGridProps, type StepItem, type StepState, TextLink, Ticker, type TruthRow, type TruthStatus, TruthTable, UsdApprox, type ValueTone, type VerifyCheck, VerifyReport, chartColor, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
@@ -570,7 +570,7 @@ var JS_TAG = /<\/?(?=[A-Za-z])/y;
570
570
  var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
571
571
  var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
572
572
  var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
573
- function scanJs(src, emit, jsx39) {
573
+ function scanJs(src, emit, jsx40) {
574
574
  let i = 0;
575
575
  let prev = "";
576
576
  let tagDepth = 0;
@@ -596,7 +596,7 @@ function scanJs(src, emit, jsx39) {
596
596
  sig('"');
597
597
  continue;
598
598
  }
599
- if (jsx39 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
599
+ if (jsx40 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
600
600
  const name = at(JS_TAG_NAME, src, i + m.length);
601
601
  if (name) {
602
602
  emit(m);
@@ -608,7 +608,7 @@ function scanJs(src, emit, jsx39) {
608
608
  continue;
609
609
  }
610
610
  }
611
- if (jsx39 && tagDepth > 0 && braceInTag === 0) {
611
+ if (jsx40 && tagDepth > 0 && braceInTag === 0) {
612
612
  if (src.startsWith("/>", i) || src[i] === ">") {
613
613
  const close = src[i] === ">" ? ">" : "/>";
614
614
  emit(close);
@@ -628,7 +628,7 @@ function scanJs(src, emit, jsx39) {
628
628
  continue;
629
629
  }
630
630
  if (src[i] === "{") braceInTag = 1;
631
- } else if (jsx39 && tagDepth > 0 && braceInTag > 0) {
631
+ } else if (jsx40 && tagDepth > 0 && braceInTag > 0) {
632
632
  if (src[i] === "{") braceInTag++;
633
633
  else if (src[i] === "}") braceInTag--;
634
634
  }
@@ -1513,6 +1513,7 @@ function Notice({
1513
1513
  title,
1514
1514
  children,
1515
1515
  action,
1516
+ icon,
1516
1517
  role,
1517
1518
  className
1518
1519
  }) {
@@ -1529,7 +1530,17 @@ function Notice({
1529
1530
  ),
1530
1531
  children: [
1531
1532
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 gap-3", children: [
1532
- kind !== "neutral" ? /* @__PURE__ */ jsxRuntime.jsx(
1533
+ icon ? /* @__PURE__ */ jsxRuntime.jsx(
1534
+ "span",
1535
+ {
1536
+ "aria-hidden": true,
1537
+ className: cn(
1538
+ "mt-0.5 shrink-0 [&_svg]:size-[1.125rem]",
1539
+ kind === "brand" ? "text-oca-accent-ink" : kind === "danger" ? "text-destructive" : "text-muted-foreground"
1540
+ ),
1541
+ children: icon
1542
+ }
1543
+ ) : kind !== "neutral" ? /* @__PURE__ */ jsxRuntime.jsx(
1533
1544
  "span",
1534
1545
  {
1535
1546
  "aria-hidden": true,
@@ -2805,7 +2816,8 @@ react.forwardRef(function DropdownMenuItem2({ className, destructive, ...props }
2805
2816
  {
2806
2817
  ref,
2807
2818
  className: cn(
2808
- "flex h-10 cursor-default select-none items-center gap-2.5 rounded-xl px-3 text-[0.9375rem] outline-none",
2819
+ // A thumb's 44px on a phone.
2820
+ "flex h-10 cursor-default select-none items-center gap-2.5 rounded-xl px-3 text-[0.9375rem] outline-none max-md:h-11",
2809
2821
  "data-[highlighted]:bg-accent data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:text-muted-foreground",
2810
2822
  destructive && "text-destructive [&_svg]:text-destructive",
2811
2823
  className
@@ -4464,6 +4476,66 @@ function ListCard({
4464
4476
  }) {
4465
4477
  return /* @__PURE__ */ jsxRuntime.jsx(Tag, { className: cn("divide-y divide-border overflow-clip rounded-[1.25rem] border border-border bg-card", className), ...props });
4466
4478
  }
4479
+ var ROW_LOOK = {
4480
+ // In a ListCard: full width, the card's hairlines between rows.
4481
+ card: { box: "px-5", hover: "hover:bg-accent/60", current: "bg-accent" },
4482
+ // In a pane's list (threads, contacts): rounded, lifted when current.
4483
+ pane: { box: "rounded-xl px-3", hover: "hover:bg-accent", current: "bg-card shadow-sm ring-1 ring-border" }
4484
+ };
4485
+ function ListRow({
4486
+ title,
4487
+ meta,
4488
+ description,
4489
+ leading,
4490
+ trailing,
4491
+ actions,
4492
+ revealActions = "always",
4493
+ href,
4494
+ onSelect,
4495
+ current = false,
4496
+ unread = false,
4497
+ variant = "card",
4498
+ as: Tag = "li",
4499
+ className
4500
+ }) {
4501
+ const tight = useDensity() === "compact";
4502
+ const look = ROW_LOOK[variant];
4503
+ const interactive = href !== void 0 || onSelect !== void 0;
4504
+ const cls = cn(
4505
+ "flex min-h-11 w-full min-w-0 items-center gap-3 text-left outline-none transition-colors",
4506
+ "focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
4507
+ look.box,
4508
+ variant === "pane" ? "py-2" : tight ? "py-3" : "py-4",
4509
+ interactive && !current && look.hover,
4510
+ current && look.current,
4511
+ actions && "pr-14"
4512
+ );
4513
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4514
+ leading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0", children: leading }) : null,
4515
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
4516
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-baseline justify-between gap-3", children: [
4517
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("truncate text-[0.9375rem] text-foreground", unread ? "font-semibold" : "font-medium"), children: title }),
4518
+ meta ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-tabular shrink-0 text-[0.8125rem] text-muted-foreground", children: meta }) : null
4519
+ ] }),
4520
+ description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("truncate text-[0.875rem]", unread ? "text-foreground" : "text-muted-foreground"), children: description }) : null
4521
+ ] }),
4522
+ trailing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center gap-2", children: trailing }) : null
4523
+ ] });
4524
+ const aria = current ? { "aria-current": "true" } : {};
4525
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { className: cn("group/row relative", className), children: [
4526
+ href !== void 0 ? href.startsWith("/") ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className: cls, ...aria, children: body }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className: cls, ...aria, children: body }) : onSelect ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onSelect, className: cls, ...aria, children: body }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cls, children: body }),
4527
+ actions ? /* @__PURE__ */ jsxRuntime.jsx(
4528
+ "div",
4529
+ {
4530
+ className: cn(
4531
+ "absolute right-2 top-1/2 flex -translate-y-1/2 items-center",
4532
+ revealActions === "hover" && "transition-opacity md:opacity-0 md:focus-within:opacity-100 md:group-hover/row:opacity-100 md:has-[[data-state=open]]:opacity-100"
4533
+ ),
4534
+ children: actions
4535
+ }
4536
+ ) : null
4537
+ ] });
4538
+ }
4467
4539
  var ChoiceSize = react.createContext("md");
4468
4540
  var COLUMNS = { 1: "", 2: "sm:grid-cols-2", 3: "sm:grid-cols-2 lg:grid-cols-3" };
4469
4541
  function ChoiceGroup({
@@ -4530,6 +4602,54 @@ function ChoiceCard({
4530
4602
  }
4531
4603
  );
4532
4604
  }
4605
+ var SIZES2 = {
4606
+ "2xs": "size-7 text-[0.6875rem] [&_svg]:size-3.5",
4607
+ xs: "size-8 text-[0.75rem] [&_svg]:size-4",
4608
+ sm: "size-9 text-[0.8125rem] [&_svg]:size-4",
4609
+ md: "size-11 text-[0.9375rem] [&_svg]:size-5",
4610
+ lg: "size-14 text-[1.1875rem] [&_svg]:size-6"
4611
+ };
4612
+ function personInitials(name) {
4613
+ return name.trim().split(/\s+/).slice(0, 2).map((w) => w.match(/[\p{L}\p{N}]/u)?.[0] ?? "").join("").toLocaleUpperCase();
4614
+ }
4615
+ function avatarHue(seed) {
4616
+ let h = 2166136261;
4617
+ for (let i = 0; i < seed.length; i++) {
4618
+ h ^= seed.charCodeAt(i);
4619
+ h = Math.imul(h, 16777619);
4620
+ }
4621
+ return (h >>> 0) % 360;
4622
+ }
4623
+ function Avatar({
4624
+ seed,
4625
+ name,
4626
+ src,
4627
+ size = "sm",
4628
+ className
4629
+ }) {
4630
+ const [failed, setFailed] = react.useState(null);
4631
+ const box = cn("inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full", SIZES2[size], className);
4632
+ if (src && failed !== src) {
4633
+ return (
4634
+ // eslint-disable-next-line @next/next/no-img-element
4635
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: "", "aria-hidden": true, className: cn(box, "object-cover"), onError: () => setFailed(src) })
4636
+ );
4637
+ }
4638
+ const initials = name ? personInitials(name) : "";
4639
+ return /* @__PURE__ */ jsxRuntime.jsx(
4640
+ "span",
4641
+ {
4642
+ "aria-hidden": true,
4643
+ className: cn(box, "font-medium leading-none"),
4644
+ style: {
4645
+ "--oca-avatar-h": avatarHue(seed),
4646
+ backgroundColor: "hsl(var(--oca-avatar-h) 60% var(--oca-avatar-bg-l))",
4647
+ color: "hsl(var(--oca-avatar-h) 45% var(--oca-avatar-fg-l))"
4648
+ },
4649
+ children: initials || /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserRound, {})
4650
+ }
4651
+ );
4652
+ }
4533
4653
  function useMacKeys() {
4534
4654
  const [mac, setMac] = react.useState(true);
4535
4655
  react.useEffect(() => {
@@ -5380,6 +5500,7 @@ exports.ApiTable = ApiTable;
5380
5500
  exports.AppCard = AppCard;
5381
5501
  exports.AppGrid = AppGrid;
5382
5502
  exports.ArtifactView = ArtifactView;
5503
+ exports.Avatar = Avatar;
5383
5504
  exports.BlockCountdown = BlockCountdown;
5384
5505
  exports.BlockHeight = BlockHeight;
5385
5506
  exports.Breadcrumbs = Breadcrumbs;
@@ -5426,6 +5547,7 @@ exports.Lead = Lead;
5426
5547
  exports.LegalDocument = LegalDocument;
5427
5548
  exports.LinkCard = LinkCard;
5428
5549
  exports.ListCard = ListCard;
5550
+ exports.ListRow = ListRow;
5429
5551
  exports.LoadingBlock = LoadingBlock;
5430
5552
  exports.LockedPreview = LockedPreview;
5431
5553
  exports.MdxTable = MdxTable;