@alfadocs/ui-kit-debug 1.98.0 → 1.99.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.
@@ -1,14 +1,14 @@
1
1
  import { jsxs as d, jsx as t } from "react/jsx-runtime";
2
- import { forwardRef as j, useState as E, useRef as o, useEffect as F, useMemo as O } from "react";
3
- import { c as M } from "./index-D2ZczOXr.js";
4
- import { useTranslation as H } from "react-i18next";
2
+ import { forwardRef as E, useState as F, useRef as o, useEffect as M, useMemo as O } from "react";
3
+ import { c as H } from "./index-D2ZczOXr.js";
4
+ import { useTranslation as V } from "react-i18next";
5
5
  import { P as l } from "./popover-CN5IsOeS.js";
6
- import { L as V } from "./link-DtCfnLnF.js";
7
- import { S as q } from "./scroll-area-CY5SLYNw.js";
8
- import { c as B } from "./compose-refs-C0k0tdqF.js";
9
- import { u as G } from "./registry-DvAUVLHh.js";
10
- import { I as J } from "./info-CGn22peZ.js";
11
- const Q = {
6
+ import { L as q } from "./link-DtCfnLnF.js";
7
+ import { S as B } from "./scroll-area-CY5SLYNw.js";
8
+ import { c as G } from "./compose-refs-C0k0tdqF.js";
9
+ import { u as J } from "./registry-DvAUVLHh.js";
10
+ import { I as Q } from "./info-CGn22peZ.js";
11
+ const U = {
12
12
  id: "info-tip",
13
13
  capabilities: ["open", "close"],
14
14
  state: {
@@ -51,7 +51,7 @@ const Q = {
51
51
  description: "Sourced from the id prop on InfoTip."
52
52
  }
53
53
  }
54
- }, U = M(
54
+ }, W = H(
55
55
  [
56
56
  "ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center",
57
57
  "ds:rounded-[var(--radius-full)]",
@@ -90,26 +90,27 @@ const Q = {
90
90
  size: "md"
91
91
  }
92
92
  }
93
- ), W = j(
93
+ ), X = E(
94
94
  ({
95
95
  content: n,
96
96
  heading: r,
97
97
  size: u = "md",
98
- side: D = "top",
99
- align: z = "center",
100
- "aria-label": C,
98
+ cardSize: D,
99
+ side: z = "top",
100
+ align: C = "center",
101
+ "aria-label": L,
101
102
  id: g,
102
- className: L,
103
+ className: S,
103
104
  formula: b,
104
105
  learnMoreHref: y,
105
- learnMoreLabel: S,
106
- onLearnMore: A
106
+ learnMoreLabel: A,
107
+ onLearnMore: K
107
108
  }, x) => {
108
- const { t: m } = H("ui"), [f, p] = E(!1), i = o(f);
109
- F(() => {
109
+ const { t: m } = V("ui"), [f, p] = F(!1), i = o(f);
110
+ M(() => {
110
111
  i.current = f;
111
112
  }, [f]);
112
- const K = O(
113
+ const P = O(
113
114
  () => ({
114
115
  getIsOpen: () => i.current,
115
116
  open: () => p(!0),
@@ -117,20 +118,20 @@ const Q = {
117
118
  }),
118
119
  []
119
120
  );
120
- G(Q, K, g);
121
+ J(U, P, g);
121
122
  const v = o(null), T = () => {
122
123
  v.current = i.current;
123
- }, w = y != null, k = o(null), P = O(
124
- () => B(x, k),
124
+ }, w = y != null, k = o(null), j = O(
125
+ () => G(x, k),
125
126
  [x]
126
- ), I = o(null), R = o(null), N = o(null), h = C ?? m("infoTip.triggerLabel", "More information");
127
+ ), I = o(null), R = o(null), N = o(null), h = L ?? m("infoTip.triggerLabel", "More information");
127
128
  return /* @__PURE__ */ d(l, { openOn: "hover-or-click", open: f, onOpenChange: p, children: [
128
129
  /* @__PURE__ */ t(
129
130
  l.Trigger,
130
131
  {
131
- ref: P,
132
+ ref: j,
132
133
  "aria-label": h,
133
- className: U({ size: u, className: L }),
134
+ className: W({ size: u, className: S }),
134
135
  "data-component": "info-tip",
135
136
  "data-component-id": g,
136
137
  onPointerDown: T,
@@ -144,7 +145,7 @@ const Q = {
144
145
  v.current = null, s === !1 && i.current && e.preventDefault();
145
146
  },
146
147
  children: /* @__PURE__ */ t(
147
- J,
148
+ Q,
148
149
  {
149
150
  "aria-hidden": "true",
150
151
  className: u === "sm" ? "ds:size-5" : "ds:size-6"
@@ -156,9 +157,9 @@ const Q = {
156
157
  l.Content,
157
158
  {
158
159
  ref: R,
159
- side: D,
160
- align: z,
161
- size: u === "sm" ? "sm" : "md",
160
+ side: z,
161
+ align: C,
162
+ size: D ?? (u === "sm" ? "sm" : "md"),
162
163
  className: "ds:flex ds:flex-col ds:max-h-[var(--radix-popover-content-available-height)]",
163
164
  "aria-label": r == null ? h : void 0,
164
165
  onOpenAutoFocus: (e) => e.preventDefault(),
@@ -171,7 +172,7 @@ const Q = {
171
172
  children: [
172
173
  r != null && /* @__PURE__ */ t(l.Heading, { children: r }),
173
174
  /* @__PURE__ */ t(l.Description, { className: "ds:flex ds:min-h-0 ds:flex-col", children: /* @__PURE__ */ d(
174
- q,
175
+ B,
175
176
  {
176
177
  ref: N,
177
178
  type: "native",
@@ -203,14 +204,14 @@ const Q = {
203
204
  "data-slot": "footer",
204
205
  className: "ds:mt-[var(--spacing-sm)] ds:flex ds:justify-end",
205
206
  children: /* @__PURE__ */ t(
206
- V,
207
+ q,
207
208
  {
208
209
  ref: I,
209
210
  href: y,
210
- onClick: A,
211
+ onClick: K,
211
212
  weight: "strong",
212
213
  className: "type-body-sm",
213
- children: S ?? m("infoTip.learnMore", "Learn more")
214
+ children: A ?? m("infoTip.learnMore", "Learn more")
214
215
  }
215
216
  )
216
217
  }
@@ -221,9 +222,9 @@ const Q = {
221
222
  ] });
222
223
  }
223
224
  );
224
- W.displayName = "InfoTip";
225
+ X.displayName = "InfoTip";
225
226
  export {
226
- W as I,
227
- Q as i
227
+ X as I,
228
+ U as i
228
229
  };
229
- //# sourceMappingURL=info-tip-CG-DEfkd.js.map
230
+ //# sourceMappingURL=info-tip-1Xsq9GLi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"info-tip-1Xsq9GLi.js","sources":["../../src/components/info-tip/info-tip.agent.ts","../../src/components/info-tip/info-tip.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { InfoTipHandle } from './info-tip';\n\nexport const infoTipAgent: AgentAdapter<InfoTipHandle> = {\n id: 'info-tip',\n capabilities: ['open', 'close'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.infoTip.state.isOpen',\n description: 'True when the info tip card is currently open.',\n read: (handle) => handle.getIsOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.open',\n description:\n 'Open the info tip card (including its formula and Learn more link, when set).',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.close',\n description: 'Close the info tip card.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'info-tip',\n description: 'Marks the InfoTip trigger button.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on InfoTip.',\n },\n },\n};\n","import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Info } from 'lucide-react';\nimport { Popover } from '../popover';\nimport { Link } from '../link';\nimport { ScrollArea } from '../scroll-area';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { infoTipAgent } from './info-tip.agent';\n\n/* -------------------------------------------------------------------- */\n/* Trigger — a small circular, branded affordance: card surface inside */\n/* the circle, accent ring + accent \"i\" glyph, and a soft drop shadow. */\n/* The accent alias is safe here: `--accent` resolves to magenta-700 in */\n/* light mode (the AA-safe interactive step) and the dark accent on dark */\n/* surfaces — never reference a raw magenta ramp step. */\n/* -------------------------------------------------------------------- */\n\nconst infoTipTriggerVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--card)]',\n 'ds:text-[var(--accent)]',\n // Single ring: the Lucide Info glyph draws its own accent circle, so the\n // trigger carries NO CSS border of its own (a border would read as a\n // second, concentric ring). The white circle comes from `bg-card` showing\n // through the glyph, lifted by the drop shadow.\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:cursor-pointer',\n 'ds:transition-[color,box-shadow] ds:motion-reduce:transition-none',\n 'ds:hover:text-[var(--accent-hover)] ds:hover:shadow-[var(--shadow-md)]',\n 'ds:data-[state=open]:text-[var(--accent-hover)] ds:data-[state=open]:shadow-[var(--shadow-md)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n // Both diameters sit below `--min-target-size` (44/48px), so each\n // re-uses IconButton's invisible `::before` hit-area expansion to a\n // full touch target on touch / small screens. From the `sm:`\n // breakpoint up the pointer is precise, so the expansion relaxes —\n // but the interactive target must never fall below WCAG 2.5.8's 24px:\n // • md (24px visual) already meets the 24px floor, so its `::before`\n // is hidden on desktop and the 24px circle IS the target.\n // • sm (20px visual) would fall to 20px if hidden — below the floor\n // — so instead of hiding, its `::before` shrinks to a persistent\n // `--spacing-lg` (24px) minimum that holds on desktop too.\n sm: 'ds:w-5 ds:h-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:inset-x-[calc((var(--spacing-lg)-100%)/-2)] ds:sm:before:inset-y-[calc((var(--spacing-lg)-100%)/-2)]',\n md: 'ds:w-6 ds:h-6 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\n// Curated agent-readiness handle — see info-tip.agent.ts.\nexport interface InfoTipHandle {\n getIsOpen: () => boolean;\n open: () => void;\n close: () => void;\n}\n\nexport interface InfoTipProps {\n /** Body of the tip — explanatory text shown in the floating card. */\n content: ReactNode;\n /** Optional heading rendered above the body. */\n heading?: ReactNode;\n /**\n * Trigger diameter. Also sets the floating card width unless `cardSize`\n * is given: `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.\n */\n size?: 'sm' | 'md';\n /**\n * Width of the floating card, when it should differ from the trigger size:\n * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`, `lg` →\n * `--popover-size-lg`. Defaults to the width that matches `size`, so a\n * small trigger can open a wider card for a longer explanation.\n */\n cardSize?: 'sm' | 'md' | 'lg';\n /** Logical side the card opens on. Default `'top'`. */\n side?: 'start' | 'top' | 'end' | 'bottom';\n /** Alignment along the side axis. Default `'center'`. */\n align?: 'start' | 'center' | 'end';\n /**\n * Accessible name for the trigger. Defaults to the translated\n * \"More information\" chrome string.\n */\n 'aria-label'?: string;\n /**\n * Opaque instance id — emitted as `data-component-id` on the trigger and\n * used to register the instance with the host agent registry.\n */\n id?: string;\n /** Extra classes merged onto the trigger button. */\n className?: string;\n /**\n * A formula written in words, shown below `content` in a quiet block, e.g.\n * \"Net revenue = invoices issued − credit notes\". It is part of the card's\n * description, so screen readers hear it.\n */\n formula?: ReactNode;\n /**\n * When set, the card gains a footer \"Learn more\" link to this URL and\n * becomes interactive: Tab from the open trigger moves to the link,\n * Shift+Tab returns, Escape closes and refocuses the trigger. Without it the\n * card is explanatory text and focus stays on the trigger, unless the text\n * is long enough to scroll: then Tab reaches the text so it can be scrolled.\n */\n learnMoreHref?: string;\n /** Link text. Defaults to the translated \"Learn more\" chrome string. */\n learnMoreLabel?: string;\n /**\n * Called when the link is activated. An SPA can call `event.preventDefault()`\n * and route client-side; the anchor keeps its real `href` either way.\n */\n onLearnMore?: (event: ReactMouseEvent<HTMLAnchorElement>) => void;\n}\n\n/**\n * InfoTip — a deliberate, branded \"more information\" affordance: a small\n * circular trigger that reveals an explanatory card on hover **and** click\n * (click also serves touch devices). Composes the kit Popover in\n * `openOn=\"hover-or-click\"` mode — hover intent, keyboard focus, Escape and\n * focus-return are all handled by the Popover/Radix layer.\n */\nexport const InfoTip = forwardRef<HTMLButtonElement, InfoTipProps>(\n (\n {\n content,\n heading,\n size = 'md',\n cardSize,\n side = 'top',\n align = 'center',\n 'aria-label': ariaLabelProp,\n id,\n className,\n formula,\n learnMoreHref,\n learnMoreLabel,\n onLearnMore,\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const [open, setOpen] = useState(false);\n\n // Agent handle.\n const openRef = useRef(open);\n useEffect(() => {\n openRef.current = open;\n }, [open]);\n\n const agentHandle = useMemo<InfoTipHandle>(\n () => ({\n getIsOpen: () => openRef.current,\n open: () => setOpen(true),\n close: () => setOpen(false),\n }),\n [],\n );\n useAgentRegistration(infoTipAgent, agentHandle, id);\n\n // Press bookkeeping. In hover-or-click mode the Popover opens as soon as\n // the trigger receives focus — which happens on pointerdown, BEFORE the\n // click event that Radix uses to toggle. Without intervention every\n // click/tap on a closed tip opens it (focus) and instantly toggles it\n // closed again (click). So each press (pointerdown, or Enter/Space)\n // snapshots the open state and the click handler consumes it: if the\n // press itself opened the card, swallow Radix's toggle so the card stays\n // open; if it was already open, let the toggle close it.\n //\n // `null` means \"no press recorded for this click\" — an orphan click\n // (programmatic .click(), or assistive tech dispatching click with no\n // pointer/key event). Those must fall through to Radix's default toggle\n // rather than read a stale snapshot, so the guard treats `null` as\n // \"don't suppress\" and every click clears the snapshot back to `null`.\n const pressStateRef = useRef<boolean | null>(null);\n const handlePressStart = () => {\n pressStateRef.current = openRef.current;\n };\n\n const hasLink = learnMoreHref != null;\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const composedTriggerRef = useMemo(\n () => composeRefs<HTMLButtonElement>(ref, triggerRef),\n [ref],\n );\n const linkRef = useRef<HTMLAnchorElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n // A long tip is capped at the height the viewport leaves it and its text\n // scrolls in a ScrollArea, which is a tab stop only while it can scroll.\n const scrollRef = useRef<HTMLDivElement | null>(null);\n\n const ariaLabel =\n ariaLabelProp ?? t('infoTip.triggerLabel', 'More information');\n\n return (\n <Popover openOn=\"hover-or-click\" open={open} onOpenChange={setOpen}>\n <Popover.Trigger\n ref={composedTriggerRef}\n aria-label={ariaLabel}\n className={infoTipTriggerVariants({ size, className })}\n data-component=\"info-tip\"\n data-component-id={id}\n onPointerDown={handlePressStart}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n handlePressStart();\n }\n // The card is portalled, so native Tab order would skip it. Tab\n // from the open trigger goes to the scrolling text when it\n // overflows, otherwise straight to the link.\n const scroll = scrollRef.current;\n const scrollable = scroll?.tabIndex === 0;\n const next = scrollable ? scroll : linkRef.current;\n if (\n (hasLink || scrollable) &&\n event.key === 'Tab' &&\n !event.shiftKey &&\n openRef.current &&\n next\n ) {\n event.preventDefault();\n next.focus();\n }\n }}\n onClick={(event) => {\n // Consume this click's press snapshot. A genuine pointer/keyboard\n // press recorded `false`/`true` on press-start; an orphan click\n // with no preceding pointerdown/keydown finds `null` and is left\n // to Radix's default toggle.\n const wasOpenAtPressStart = pressStateRef.current;\n pressStateRef.current = null;\n if (wasOpenAtPressStart === false && openRef.current) {\n // This press opened the card via focus — keep it open and\n // skip Radix's click toggle.\n event.preventDefault();\n }\n }}\n >\n <Info\n aria-hidden=\"true\"\n // Fills the circle so the glyph's own ring IS the trigger's\n // visible edge and the drop shadow hugs it.\n className={size === 'sm' ? 'ds:size-5' : 'ds:size-6'}\n />\n </Popover.Trigger>\n <Popover.Content\n ref={contentRef}\n side={side}\n align={align}\n size={cardSize ?? (size === 'sm' ? 'sm' : 'md')}\n // Never taller than the space the viewport leaves; the text scrolls.\n // The card itself does not clip, so its arrow stays visible.\n className=\"ds:flex ds:flex-col ds:max-h-[var(--radix-popover-content-available-height)]\"\n // The card is a Radix `role=\"dialog\"` surface, which axe requires\n // to have an accessible name (aria-dialog-name). With a heading,\n // Popover wires aria-labelledby; without one, fall back to the\n // trigger's label.\n aria-label={heading == null ? ariaLabel : undefined}\n // Toggletip focus contract: the card is explanatory text, never\n // interactive, so focus stays on the trigger for the whole\n // open/close cycle. Preventing the open move also keeps Escape\n // reliable — if Radix pulled focus into the card, closing would\n // refocus the trigger and re-fire the hover-mode focus handler,\n // reopening the card it just closed. Preventing the close move\n // keeps an unhover-close from stealing focus mid-task.\n //\n // With a learn-more link, or text long enough to scroll, the card\n // is interactive, but the same contract holds: focus is never\n // pulled in on open, only Tab moves it to the text or the link. Escape from inside the card is handled below so\n // focus returns to the trigger without re-firing its focus-open.\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n onEscapeKeyDown={(event) => {\n // Focus anywhere inside the card (the link, or the card itself\n // after a click on its text) goes back to the trigger.\n const active = document.activeElement;\n if (active && contentRef.current?.contains(active)) {\n event.preventDefault();\n triggerRef.current?.focus();\n setOpen(false);\n }\n }}\n >\n {heading != null && <Popover.Heading>{heading}</Popover.Heading>}\n <Popover.Description className=\"ds:flex ds:min-h-0 ds:flex-col\">\n <ScrollArea\n ref={scrollRef}\n type=\"native\"\n aria-label={typeof heading === 'string' ? heading : ariaLabel}\n // At high zoom the heading and link keep their height; the text\n // keeps at least three lines rather than collapsing to nothing.\n className=\"ds:min-h-[3lh]\"\n >\n {content}\n {formula != null && (\n <div\n data-slot=\"formula\"\n className=\"type-body-sm ds:mt-[var(--spacing-sm)] ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)] ds:px-[var(--spacing-sm)] ds:py-[var(--spacing-xs)] ds:text-[var(--foreground)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('infoTip.formula', 'Formula')}:{' '}\n </span>\n {formula}\n </div>\n )}\n </ScrollArea>\n </Popover.Description>\n {hasLink && (\n <div\n data-slot=\"footer\"\n className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:justify-end\"\n >\n <Link\n ref={linkRef}\n href={learnMoreHref}\n onClick={onLearnMore}\n weight=\"strong\"\n className=\"type-body-sm\"\n >\n {learnMoreLabel ?? t('infoTip.learnMore', 'Learn more')}\n </Link>\n </div>\n )}\n </Popover.Content>\n </Popover>\n );\n },\n);\n\nInfoTip.displayName = 'InfoTip';\n"],"names":["infoTipAgent","handle","infoTipTriggerVariants","cva","InfoTip","forwardRef","content","heading","size","cardSize","side","align","ariaLabelProp","id","className","formula","learnMoreHref","learnMoreLabel","onLearnMore","ref","t","useTranslation","open","setOpen","useState","openRef","useRef","useEffect","agentHandle","useMemo","useAgentRegistration","pressStateRef","handlePressStart","hasLink","triggerRef","composedTriggerRef","composeRefs","linkRef","contentRef","scrollRef","ariaLabel","Popover","jsx","event","scroll","scrollable","next","wasOpenAtPressStart","Info","jsxs","active","_a","_b","ScrollArea","Link"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "1.98.0",
3
+ "packageVersion": "1.99.0",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -1,4 +1,4 @@
1
- import { I as f, i as n } from "../../_chunks/info-tip-CG-DEfkd.js";
1
+ import { I as f, i as n } from "../../_chunks/info-tip-1Xsq9GLi.js";
2
2
  export {
3
3
  f as InfoTip,
4
4
  n as infoTipAgent
@@ -10,10 +10,17 @@ export interface InfoTipProps {
10
10
  /** Optional heading rendered above the body. */
11
11
  heading?: ReactNode;
12
12
  /**
13
- * Trigger diameter. Also maps the floating card width:
14
- * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.
13
+ * Trigger diameter. Also sets the floating card width unless `cardSize`
14
+ * is given: `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.
15
15
  */
16
16
  size?: 'sm' | 'md';
17
+ /**
18
+ * Width of the floating card, when it should differ from the trigger size:
19
+ * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`, `lg` →
20
+ * `--popover-size-lg`. Defaults to the width that matches `size`, so a
21
+ * small trigger can open a wider card for a longer explanation.
22
+ */
23
+ cardSize?: 'sm' | 'md' | 'lg';
17
24
  /** Logical side the card opens on. Default `'top'`. */
18
25
  side?: 'start' | 'top' | 'end' | 'bottom';
19
26
  /** Alignment along the side axis. Default `'center'`. */
@@ -1 +1 @@
1
- {"version":3,"file":"info-tip.d.ts","sourceRoot":"","sources":["../../../src/components/info-tip/info-tip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,UAAU,IAAI,eAAe,EAClC,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA6Df,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,OAAO,EAAE,SAAS,CAAC;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACnE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,4GA4MnB,CAAC"}
1
+ {"version":3,"file":"info-tip.d.ts","sourceRoot":"","sources":["../../../src/components/info-tip/info-tip.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,UAAU,IAAI,eAAe,EAClC,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA6Df,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,OAAO,EAAE,SAAS,CAAC;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9B,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;CACnE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,4GA6MnB,CAAC"}
package/dist/index.js CHANGED
@@ -158,7 +158,7 @@ import { E as Um } from "./_chunks/error-boundary-tAn_GuCu.js";
158
158
  import { E as Km } from "./_chunks/error-summary-mGxIyDAY.js";
159
159
  import { F as Xm } from "./_chunks/finished-terminal-DXVAfhRr.js";
160
160
  import { H as zm, h as jm, u as Qm } from "./_chunks/hover-card-CuRIA4wN.js";
161
- import { I as Jm, i as $m } from "./_chunks/info-tip-CG-DEfkd.js";
161
+ import { I as Jm, i as $m } from "./_chunks/info-tip-1Xsq9GLi.js";
162
162
  import { L as el } from "./_chunks/live-region-C41SO3cA.js";
163
163
  import { M as rl } from "./_chunks/matrix-rain-sDOUUwZp.js";
164
164
  import { M as tl } from "./_chunks/message-card-BzJEITml.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfadocs/ui-kit-debug",
3
- "version": "1.98.0",
3
+ "version": "1.99.0",
4
4
  "type": "module",
5
5
  "description": "AlfaDocs shared design system — tokens, components, patterns, and translations for platform, booking, and alfascribe. (debug build — identical runtime to @alfadocs/ui-kit, ships source maps for symbolication).",
6
6
  "license": "BUSL-1.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"info-tip-CG-DEfkd.js","sources":["../../src/components/info-tip/info-tip.agent.ts","../../src/components/info-tip/info-tip.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { InfoTipHandle } from './info-tip';\n\nexport const infoTipAgent: AgentAdapter<InfoTipHandle> = {\n id: 'info-tip',\n capabilities: ['open', 'close'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.infoTip.state.isOpen',\n description: 'True when the info tip card is currently open.',\n read: (handle) => handle.getIsOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.open',\n description:\n 'Open the info tip card (including its formula and Learn more link, when set).',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.close',\n description: 'Close the info tip card.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'info-tip',\n description: 'Marks the InfoTip trigger button.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on InfoTip.',\n },\n },\n};\n","import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Info } from 'lucide-react';\nimport { Popover } from '../popover';\nimport { Link } from '../link';\nimport { ScrollArea } from '../scroll-area';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { infoTipAgent } from './info-tip.agent';\n\n/* -------------------------------------------------------------------- */\n/* Trigger — a small circular, branded affordance: card surface inside */\n/* the circle, accent ring + accent \"i\" glyph, and a soft drop shadow. */\n/* The accent alias is safe here: `--accent` resolves to magenta-700 in */\n/* light mode (the AA-safe interactive step) and the dark accent on dark */\n/* surfaces — never reference a raw magenta ramp step. */\n/* -------------------------------------------------------------------- */\n\nconst infoTipTriggerVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--card)]',\n 'ds:text-[var(--accent)]',\n // Single ring: the Lucide Info glyph draws its own accent circle, so the\n // trigger carries NO CSS border of its own (a border would read as a\n // second, concentric ring). The white circle comes from `bg-card` showing\n // through the glyph, lifted by the drop shadow.\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:cursor-pointer',\n 'ds:transition-[color,box-shadow] ds:motion-reduce:transition-none',\n 'ds:hover:text-[var(--accent-hover)] ds:hover:shadow-[var(--shadow-md)]',\n 'ds:data-[state=open]:text-[var(--accent-hover)] ds:data-[state=open]:shadow-[var(--shadow-md)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n // Both diameters sit below `--min-target-size` (44/48px), so each\n // re-uses IconButton's invisible `::before` hit-area expansion to a\n // full touch target on touch / small screens. From the `sm:`\n // breakpoint up the pointer is precise, so the expansion relaxes —\n // but the interactive target must never fall below WCAG 2.5.8's 24px:\n // • md (24px visual) already meets the 24px floor, so its `::before`\n // is hidden on desktop and the 24px circle IS the target.\n // • sm (20px visual) would fall to 20px if hidden — below the floor\n // — so instead of hiding, its `::before` shrinks to a persistent\n // `--spacing-lg` (24px) minimum that holds on desktop too.\n sm: 'ds:w-5 ds:h-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:inset-x-[calc((var(--spacing-lg)-100%)/-2)] ds:sm:before:inset-y-[calc((var(--spacing-lg)-100%)/-2)]',\n md: 'ds:w-6 ds:h-6 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\n// Curated agent-readiness handle — see info-tip.agent.ts.\nexport interface InfoTipHandle {\n getIsOpen: () => boolean;\n open: () => void;\n close: () => void;\n}\n\nexport interface InfoTipProps {\n /** Body of the tip — explanatory text shown in the floating card. */\n content: ReactNode;\n /** Optional heading rendered above the body. */\n heading?: ReactNode;\n /**\n * Trigger diameter. Also maps the floating card width:\n * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.\n */\n size?: 'sm' | 'md';\n /** Logical side the card opens on. Default `'top'`. */\n side?: 'start' | 'top' | 'end' | 'bottom';\n /** Alignment along the side axis. Default `'center'`. */\n align?: 'start' | 'center' | 'end';\n /**\n * Accessible name for the trigger. Defaults to the translated\n * \"More information\" chrome string.\n */\n 'aria-label'?: string;\n /**\n * Opaque instance id — emitted as `data-component-id` on the trigger and\n * used to register the instance with the host agent registry.\n */\n id?: string;\n /** Extra classes merged onto the trigger button. */\n className?: string;\n /**\n * A formula written in words, shown below `content` in a quiet block, e.g.\n * \"Net revenue = invoices issued − credit notes\". It is part of the card's\n * description, so screen readers hear it.\n */\n formula?: ReactNode;\n /**\n * When set, the card gains a footer \"Learn more\" link to this URL and\n * becomes interactive: Tab from the open trigger moves to the link,\n * Shift+Tab returns, Escape closes and refocuses the trigger. Without it the\n * card is explanatory text and focus stays on the trigger, unless the text\n * is long enough to scroll: then Tab reaches the text so it can be scrolled.\n */\n learnMoreHref?: string;\n /** Link text. Defaults to the translated \"Learn more\" chrome string. */\n learnMoreLabel?: string;\n /**\n * Called when the link is activated. An SPA can call `event.preventDefault()`\n * and route client-side; the anchor keeps its real `href` either way.\n */\n onLearnMore?: (event: ReactMouseEvent<HTMLAnchorElement>) => void;\n}\n\n/**\n * InfoTip — a deliberate, branded \"more information\" affordance: a small\n * circular trigger that reveals an explanatory card on hover **and** click\n * (click also serves touch devices). Composes the kit Popover in\n * `openOn=\"hover-or-click\"` mode — hover intent, keyboard focus, Escape and\n * focus-return are all handled by the Popover/Radix layer.\n */\nexport const InfoTip = forwardRef<HTMLButtonElement, InfoTipProps>(\n (\n {\n content,\n heading,\n size = 'md',\n side = 'top',\n align = 'center',\n 'aria-label': ariaLabelProp,\n id,\n className,\n formula,\n learnMoreHref,\n learnMoreLabel,\n onLearnMore,\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const [open, setOpen] = useState(false);\n\n // Agent handle.\n const openRef = useRef(open);\n useEffect(() => {\n openRef.current = open;\n }, [open]);\n\n const agentHandle = useMemo<InfoTipHandle>(\n () => ({\n getIsOpen: () => openRef.current,\n open: () => setOpen(true),\n close: () => setOpen(false),\n }),\n [],\n );\n useAgentRegistration(infoTipAgent, agentHandle, id);\n\n // Press bookkeeping. In hover-or-click mode the Popover opens as soon as\n // the trigger receives focus — which happens on pointerdown, BEFORE the\n // click event that Radix uses to toggle. Without intervention every\n // click/tap on a closed tip opens it (focus) and instantly toggles it\n // closed again (click). So each press (pointerdown, or Enter/Space)\n // snapshots the open state and the click handler consumes it: if the\n // press itself opened the card, swallow Radix's toggle so the card stays\n // open; if it was already open, let the toggle close it.\n //\n // `null` means \"no press recorded for this click\" — an orphan click\n // (programmatic .click(), or assistive tech dispatching click with no\n // pointer/key event). Those must fall through to Radix's default toggle\n // rather than read a stale snapshot, so the guard treats `null` as\n // \"don't suppress\" and every click clears the snapshot back to `null`.\n const pressStateRef = useRef<boolean | null>(null);\n const handlePressStart = () => {\n pressStateRef.current = openRef.current;\n };\n\n const hasLink = learnMoreHref != null;\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const composedTriggerRef = useMemo(\n () => composeRefs<HTMLButtonElement>(ref, triggerRef),\n [ref],\n );\n const linkRef = useRef<HTMLAnchorElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n // A long tip is capped at the height the viewport leaves it and its text\n // scrolls in a ScrollArea, which is a tab stop only while it can scroll.\n const scrollRef = useRef<HTMLDivElement | null>(null);\n\n const ariaLabel =\n ariaLabelProp ?? t('infoTip.triggerLabel', 'More information');\n\n return (\n <Popover openOn=\"hover-or-click\" open={open} onOpenChange={setOpen}>\n <Popover.Trigger\n ref={composedTriggerRef}\n aria-label={ariaLabel}\n className={infoTipTriggerVariants({ size, className })}\n data-component=\"info-tip\"\n data-component-id={id}\n onPointerDown={handlePressStart}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n handlePressStart();\n }\n // The card is portalled, so native Tab order would skip it. Tab\n // from the open trigger goes to the scrolling text when it\n // overflows, otherwise straight to the link.\n const scroll = scrollRef.current;\n const scrollable = scroll?.tabIndex === 0;\n const next = scrollable ? scroll : linkRef.current;\n if (\n (hasLink || scrollable) &&\n event.key === 'Tab' &&\n !event.shiftKey &&\n openRef.current &&\n next\n ) {\n event.preventDefault();\n next.focus();\n }\n }}\n onClick={(event) => {\n // Consume this click's press snapshot. A genuine pointer/keyboard\n // press recorded `false`/`true` on press-start; an orphan click\n // with no preceding pointerdown/keydown finds `null` and is left\n // to Radix's default toggle.\n const wasOpenAtPressStart = pressStateRef.current;\n pressStateRef.current = null;\n if (wasOpenAtPressStart === false && openRef.current) {\n // This press opened the card via focus — keep it open and\n // skip Radix's click toggle.\n event.preventDefault();\n }\n }}\n >\n <Info\n aria-hidden=\"true\"\n // Fills the circle so the glyph's own ring IS the trigger's\n // visible edge and the drop shadow hugs it.\n className={size === 'sm' ? 'ds:size-5' : 'ds:size-6'}\n />\n </Popover.Trigger>\n <Popover.Content\n ref={contentRef}\n side={side}\n align={align}\n size={size === 'sm' ? 'sm' : 'md'}\n // Never taller than the space the viewport leaves; the text scrolls.\n // The card itself does not clip, so its arrow stays visible.\n className=\"ds:flex ds:flex-col ds:max-h-[var(--radix-popover-content-available-height)]\"\n // The card is a Radix `role=\"dialog\"` surface, which axe requires\n // to have an accessible name (aria-dialog-name). With a heading,\n // Popover wires aria-labelledby; without one, fall back to the\n // trigger's label.\n aria-label={heading == null ? ariaLabel : undefined}\n // Toggletip focus contract: the card is explanatory text, never\n // interactive, so focus stays on the trigger for the whole\n // open/close cycle. Preventing the open move also keeps Escape\n // reliable — if Radix pulled focus into the card, closing would\n // refocus the trigger and re-fire the hover-mode focus handler,\n // reopening the card it just closed. Preventing the close move\n // keeps an unhover-close from stealing focus mid-task.\n //\n // With a learn-more link, or text long enough to scroll, the card\n // is interactive, but the same contract holds: focus is never\n // pulled in on open, only Tab moves it to the text or the link. Escape from inside the card is handled below so\n // focus returns to the trigger without re-firing its focus-open.\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n onEscapeKeyDown={(event) => {\n // Focus anywhere inside the card (the link, or the card itself\n // after a click on its text) goes back to the trigger.\n const active = document.activeElement;\n if (active && contentRef.current?.contains(active)) {\n event.preventDefault();\n triggerRef.current?.focus();\n setOpen(false);\n }\n }}\n >\n {heading != null && <Popover.Heading>{heading}</Popover.Heading>}\n <Popover.Description className=\"ds:flex ds:min-h-0 ds:flex-col\">\n <ScrollArea\n ref={scrollRef}\n type=\"native\"\n aria-label={typeof heading === 'string' ? heading : ariaLabel}\n // At high zoom the heading and link keep their height; the text\n // keeps at least three lines rather than collapsing to nothing.\n className=\"ds:min-h-[3lh]\"\n >\n {content}\n {formula != null && (\n <div\n data-slot=\"formula\"\n className=\"type-body-sm ds:mt-[var(--spacing-sm)] ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)] ds:px-[var(--spacing-sm)] ds:py-[var(--spacing-xs)] ds:text-[var(--foreground)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('infoTip.formula', 'Formula')}:{' '}\n </span>\n {formula}\n </div>\n )}\n </ScrollArea>\n </Popover.Description>\n {hasLink && (\n <div\n data-slot=\"footer\"\n className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:justify-end\"\n >\n <Link\n ref={linkRef}\n href={learnMoreHref}\n onClick={onLearnMore}\n weight=\"strong\"\n className=\"type-body-sm\"\n >\n {learnMoreLabel ?? t('infoTip.learnMore', 'Learn more')}\n </Link>\n </div>\n )}\n </Popover.Content>\n </Popover>\n );\n },\n);\n\nInfoTip.displayName = 'InfoTip';\n"],"names":["infoTipAgent","handle","infoTipTriggerVariants","cva","InfoTip","forwardRef","content","heading","size","side","align","ariaLabelProp","id","className","formula","learnMoreHref","learnMoreLabel","onLearnMore","ref","t","useTranslation","open","setOpen","useState","openRef","useRef","useEffect","agentHandle","useMemo","useAgentRegistration","pressStateRef","handlePressStart","hasLink","triggerRef","composedTriggerRef","composeRefs","linkRef","contentRef","scrollRef","ariaLabel","Popover","jsx","event","scroll","scrollable","next","wasOpenAtPressStart","Info","jsxs","active","_a","_b","ScrollArea","Link"],"mappings":"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"}