@nebutra/ui 0.2.3 → 3.0.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.
- package/dist/animate-in-BlvjVh2S.d.ts +250 -0
- package/dist/{canonical-Drca5UMj.d.ts → canonical-DEhT4VfS.d.ts} +83 -369
- package/dist/card-DunB1gKE.d.ts +105 -0
- package/dist/chat/index.d.ts +1 -0
- package/dist/chat/index.js +3 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/components/index.d.ts +90 -126
- package/dist/components/index.js +433 -182
- package/dist/components/index.js.map +1 -1
- package/dist/editorial/index.d.ts +404 -0
- package/dist/editorial/index.js +942 -0
- package/dist/editorial/index.js.map +1 -0
- package/dist/empty-state-bmfHCOuN.d.ts +86 -0
- package/dist/hooks/index.d.ts +18 -1
- package/dist/hooks/index.js +120 -5
- package/dist/hooks/index.js.map +1 -1
- package/dist/icons/index.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/layout/index.d.ts +17 -58
- package/dist/layout/index.js +368 -127
- package/dist/layout/index.js.map +1 -1
- package/dist/layouts/index.d.ts +1 -1
- package/dist/layouts/index.js +93 -28
- package/dist/layouts/index.js.map +1 -1
- package/dist/patterns/index.d.ts +39 -46
- package/dist/patterns/index.js +534 -323
- package/dist/patterns/index.js.map +1 -1
- package/dist/primitives/canonical.d.ts +5 -2
- package/dist/primitives/canonical.js +598 -288
- package/dist/primitives/canonical.js.map +1 -1
- package/dist/primitives/index.d.ts +165 -63
- package/dist/primitives/index.js +1251 -983
- package/dist/primitives/index.js.map +1 -1
- package/dist/tailwind.preset.d.ts +32 -32
- package/dist/tailwind.preset.js +24 -20
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/theme/index.d.ts +1 -110
- package/dist/typography/fonts.css +8 -16
- package/dist/typography/index.d.ts +29 -45
- package/dist/typography/index.js +26 -14
- package/dist/typography/index.js.map +1 -1
- package/dist/utils/auth-surfaces.d.ts +33 -0
- package/dist/utils/auth-surfaces.js +9 -0
- package/dist/utils/auth-surfaces.js.map +1 -0
- package/dist/utils/index.d.ts +20 -16
- package/dist/utils/index.js +99 -20
- package/dist/utils/index.js.map +1 -1
- package/package.json +25 -11
- package/src/typography/fonts.css +8 -16
- package/dist/styles/brand-override.css +0 -61
- package/src/styles/brand-override.css +0 -61
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/tw-merge-theme.generated.ts","../../src/utils/cn.ts","../../src/editorial/editorial-surface.ts","../../src/editorial/editorial-author-bio.tsx","../../src/editorial/editorial-callout.tsx","../../src/editorial/editorial-chart.tsx","../../src/editorial/editorial-comparison-table.tsx","../../src/editorial/editorial-data-table.tsx","../../src/editorial/editorial-divider.tsx","../../src/editorial/editorial-embed-card.tsx","../../src/editorial/editorial-entity-chip.tsx","../../src/editorial/editorial-faq.tsx","../../src/editorial/editorial-figure.tsx","../../src/editorial/editorial-key-takeaways.tsx","../../src/editorial/editorial-margin-note.tsx","../../src/editorial/editorial-pull-quote.tsx","../../src/editorial/editorial-source-index.tsx","../../src/editorial/editorial-stat-grid.tsx","../../src/editorial/editorial-step-ladder.tsx","../../src/editorial/editorial-timeline.tsx"],"names":["jsxs","jsx","ArrowUpRight","hostname"],"mappings":"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","file":"index.js","sourcesContent":["// GENERATED by packages/design/ui/scripts/gen-tw-merge-theme.mjs — do not edit.\n// Source: the @theme blocks in packages/design/tokens/{styles,recipe}.css.\n\nexport const TW_MERGE_THEME = {\n breakpoint: [\"3xl\", \"shell\", \"tight\", \"xs\"],\n container: [\"content\", \"text\", \"wide\"],\n ease: [\"brand\", \"in\", \"in-out\", \"out\", \"spring\"],\n font: [\"cn\", \"display\", \"heading\", \"mono\", \"sans\"],\n leading: [\"display\", \"heading\"],\n radius: [\"2xl\", \"3xl\", \"button\", \"card\", \"full\", \"lg\", \"md\", \"none\", \"panel\", \"sm\", \"xl\", \"xs\"],\n shadow: [\n \"2xl\",\n \"ambient-glow\",\n \"ambient-lg\",\n \"ambient-md\",\n \"ambient-sm\",\n \"brand\",\n \"brand-lg\",\n \"glass-lg\",\n \"glass-md\",\n \"glass-sm\",\n \"glow-accent\",\n \"glow-accent-lg\",\n \"glow-accent-sm\",\n \"glow-primary\",\n \"lg\",\n \"md\",\n \"sheen\",\n \"sm\",\n \"xl\",\n \"xs\",\n ],\n text: [\n \"2xl\",\n \"2xs\",\n \"3xl\",\n \"4xl\",\n \"5xl\",\n \"6xl\",\n \"7xl\",\n \"8xl\",\n \"9xl\",\n \"base\",\n \"body\",\n \"display\",\n \"label\",\n \"lg\",\n \"meta\",\n \"sm\",\n \"ui\",\n \"xl\",\n \"xs\",\n ],\n tracking: [\"display\", \"heading\", \"label\", \"tight\"],\n} as const;\n\nexport const TW_MERGE_CLASS_GROUPS = {\n duration: [{ duration: [\"cinematic\", \"flow\", \"micro\", \"reveal\"] }],\n} as const;\n","import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\nimport { TW_MERGE_CLASS_GROUPS, TW_MERGE_THEME } from \"./tw-merge-theme.generated\";\n\n/**\n * tailwind-merge only knows Tailwind's default scale. Every utility the design\n * tokens add (text-label, shadow-ambient-md, rounded-card, ease-brand,\n * max-w-wide, …) was otherwise an unknown class: `cn(\"text-label\n * text-destructive-strong\")` returned \"text-destructive-strong\" and the size fell away, and\n * `cn(\"rounded-card\", \"rounded-lg\")` kept both so the winner depended on\n * stylesheet order. The theme below is generated from the tokens' @theme blocks\n * (scripts/gen-tw-merge-theme.mjs), so a new token utility is known here the\n * moment it exists; a test fails if the generated file goes stale.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: Object.fromEntries(\n Object.entries(TW_MERGE_THEME).map(([key, values]) => [key, [...values]]),\n ),\n classGroups: Object.fromEntries(\n Object.entries(TW_MERGE_CLASS_GROUPS).map(([key, groups]) => [\n key,\n groups.map((group) =>\n Object.fromEntries(Object.entries(group).map(([k, v]) => [k, [...v]])),\n ),\n ]),\n ),\n },\n});\n\n/** Kept for callers and tests that enumerate the design-system text steps. */\nexport const DESIGN_SYSTEM_TEXT_SIZES = TW_MERGE_THEME.text;\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { cva } from \"class-variance-authority\";\nimport type { CSSProperties } from \"react\";\n\n/**\n * Shared visual grammar for long-form editorial blocks.\n *\n * Every block in this directory composes these recipes instead of hand-picking\n * borders, radii and shadows, so a change to the editorial voice is one edit\n * here rather than fifteen edits across the renderer.\n *\n * The grammar is hairline-first: separation comes from a 1px border plus the\n * ambient elevation ramp, never from a filled colour panel. Tone is carried by\n * a 2px rail and an icon, so a page of stacked blocks still reads as one\n * document rather than a row of coloured cards.\n */\n\n/** Uppercase micro-label that opens a block. Not part of the registered type scale. */\nexport const EDITORIAL_EYEBROW =\n \"text-[0.6875rem] font-semibold uppercase leading-none tracking-[0.14em] text-muted-foreground\";\n\n/** Caption / footnote text under a figure, table or chart. */\nexport const EDITORIAL_CAPTION = \"text-sm leading-6 text-muted-foreground\";\n\n/** Body copy inside a block. One step tighter than article prose. */\nexport const EDITORIAL_BODY = \"text-[0.9375rem] leading-7 text-muted-foreground\";\n\n/** Block title. Sits below an article h3 so it never competes with the outline. */\nexport const EDITORIAL_TITLE = \"text-base font-semibold leading-6 text-foreground\";\n\n/**\n * Figures are numeric, so they take tabular lining figures — otherwise a column\n * of stats visually ragged-rights itself as digit widths change.\n */\nexport const EDITORIAL_FIGURE = \"font-mono font-semibold tabular-nums text-foreground\";\n\n/**\n * Article body is a ~3xl reading column. Blocks that carry a grid, a table or a\n * chart earn width by breaking out of it; prose-adjacent blocks stay inline so\n * the measure is preserved.\n */\nexport const editorialBlock = cva(\"\", {\n variants: {\n width: {\n column: \"\",\n breakout: \"lg:-mx-12\",\n full: \"lg:-mx-20\",\n },\n spacing: {\n none: \"\",\n tight: \"my-8\",\n normal: \"my-10\",\n loose: \"my-14\",\n },\n },\n defaultVariants: { width: \"column\", spacing: \"normal\" },\n});\n\n/**\n * Surface recipe. `resting` is the default for a card in flow; `raised` is for\n * the one block in a set that should read as emphasised, not for every card.\n */\nexport const editorialFrame = cva(\"border border-border bg-background\", {\n variants: {\n radius: {\n card: \"rounded-[var(--radius-xl)]\",\n panel: \"rounded-[var(--radius-2xl)]\",\n inner: \"rounded-[var(--radius-md)]\",\n },\n elevation: {\n flat: \"\",\n resting: \"shadow-ambient-sm\",\n raised: \"shadow-ambient-md\",\n },\n },\n defaultVariants: { radius: \"card\", elevation: \"resting\" },\n});\n\nexport const EDITORIAL_TONES = [\"note\", \"insight\", \"success\", \"warning\", \"danger\"] as const;\n\nexport type EditorialTone = (typeof EDITORIAL_TONES)[number];\n\n/**\n * Every entry resolves to a complete colour, never to bare HSL channels: the\n * accent is consumed by `color-mix()` and by a `background-color`, both of\n * which discard the whole declaration if handed `222 47% 11%`. That is why\n * `insight` wraps `--primary` in `hsl()` rather than reaching for\n * `--brand-primary`, which is the VI identity lock and not a surface colour.\n */\nconst TONE_ACCENT: Record<EditorialTone, string> = {\n note: \"var(--neutral-8)\",\n insight: \"hsl(var(--primary))\",\n success: \"var(--status-success)\",\n warning: \"var(--status-warning)\",\n danger: \"var(--status-danger)\",\n};\n\nexport function editorialToneAccent(tone: EditorialTone): string {\n return TONE_ACCENT[tone];\n}\n\nexport function isEditorialTone(value: unknown): value is EditorialTone {\n return typeof value === \"string\" && (EDITORIAL_TONES as readonly string[]).includes(value);\n}\n\n/**\n * Inline custom property consumed by the tone-aware utility classes below.\n * `--editorial-tone` is a private name: shadowing a core token such as\n * `--primary` on an element would leak into the whole subtree.\n */\nexport function editorialToneStyle(tone: EditorialTone): CSSProperties {\n // `CSSProperties` has no index signature for custom properties, so the cast\n // is unavoidable. Keeping it here means no component repeats it.\n return { \"--editorial-tone\": editorialToneAccent(tone) } as CSSProperties;\n}\n\n/** Foreground for icons and rails. */\nexport const EDITORIAL_TONE_FG = \"text-[color:var(--editorial-tone)]\";\n\n/** 5% wash — enough to register as tinted, not enough to read as a coloured block. */\nexport const EDITORIAL_TONE_WASH = \"bg-[color-mix(in_srgb,var(--editorial-tone)_5%,transparent)]\";\n\n/** 12% plate behind an icon. */\nexport const EDITORIAL_TONE_PLATE = \"bg-[color-mix(in_srgb,var(--editorial-tone)_12%,transparent)]\";\n","import { ArrowUpRight } from \"@nebutra/icons\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n EDITORIAL_BODY,\n EDITORIAL_EYEBROW,\n editorialBlock,\n editorialFrame,\n} from \"./editorial-surface\";\n\nexport type EditorialAuthorLink = {\n href: string;\n key?: string;\n label: string;\n};\n\nexport type EditorialAuthorBioProps = {\n /** Avatar slot. Apps pass their own image component so this stays framework-free. */\n avatar?: ReactNode;\n bio?: string | null;\n className?: string;\n label?: string;\n links?: EditorialAuthorLink[];\n name: string;\n role?: string | null;\n};\n\n/** Byline card closing an article. */\nexport function EditorialAuthorBio({\n avatar,\n bio,\n className,\n label = \"Written by\",\n links = [],\n name,\n role,\n}: EditorialAuthorBioProps) {\n if (!name.trim()) return null;\n\n const visibleLinks = links.filter((link) => link.href && link.label);\n\n return (\n <aside\n className={cn(\n editorialBlock({ spacing: \"loose\", width: \"breakout\" }),\n editorialFrame({ elevation: \"resting\", radius: \"panel\" }),\n \"flex flex-col gap-4 px-6 py-6 sm:flex-row sm:gap-5\",\n className,\n )}\n >\n {avatar && (\n <span className=\"size-12 shrink-0 overflow-hidden rounded-full bg-muted\">{avatar}</span>\n )}\n <div className=\"min-w-0 flex-1\">\n <div className={EDITORIAL_EYEBROW}>{label}</div>\n <p className=\"mt-2 text-base font-semibold leading-6 text-foreground\">{name}</p>\n {role && <p className=\"mt-0.5 text-sm text-muted-foreground\">{role}</p>}\n {bio && <p className={cn(\"mt-3\", EDITORIAL_BODY)}>{bio}</p>}\n {visibleLinks.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {visibleLinks.map((link) => (\n <a\n key={link.key ?? link.href}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border px-3 py-1.5 text-sm font-medium text-foreground transition-colors hover:bg-muted\"\n href={link.href}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {link.label}\n <ArrowUpRight aria-hidden className=\"size-3.5 text-muted-foreground\" />\n </a>\n ))}\n </div>\n )}\n </div>\n </aside>\n );\n}\n","import { CheckCircle, Information, Sparkles, Warning, WarningFill } from \"@nebutra/icons\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n EDITORIAL_BODY,\n EDITORIAL_EYEBROW,\n EDITORIAL_TONE_FG,\n EDITORIAL_TONE_PLATE,\n EDITORIAL_TONE_WASH,\n type EditorialTone,\n editorialBlock,\n editorialFrame,\n editorialToneStyle,\n} from \"./editorial-surface\";\n\nconst TONE_ICON: Record<EditorialTone, ComponentType<{ className?: string }>> = {\n note: Information,\n insight: Sparkles,\n success: CheckCircle,\n warning: Warning,\n danger: WarningFill,\n};\n\nexport type EditorialCalloutProps = {\n /** Body copy. A string is wrapped in a paragraph; nodes are rendered as given. */\n children?: ReactNode;\n className?: string;\n /** Shown in the eyebrow slot when there is no title — pass a localized word. */\n label?: string;\n title?: string | null;\n tone?: EditorialTone;\n};\n\n/**\n * Aside for a note, insight, caution or correction.\n *\n * Tone is a 2px rail plus a tinted icon plate, not a filled panel: a reader\n * scrolling past four callouts should see four asides, not four highlighter\n * swipes.\n */\nexport function EditorialCallout({\n children,\n className,\n label,\n title,\n tone = \"note\",\n}: EditorialCalloutProps) {\n if (!title && !children) return null;\n\n const Icon = TONE_ICON[tone];\n const eyebrow = title ?? label ?? tone;\n\n return (\n <aside\n className={cn(\n editorialBlock({ spacing: \"normal\" }),\n editorialFrame({ elevation: \"resting\" }),\n EDITORIAL_TONE_WASH,\n \"relative overflow-hidden pl-6 pr-5 py-5\",\n className,\n )}\n style={editorialToneStyle(tone)}\n >\n <span aria-hidden className=\"absolute inset-y-0 left-0 w-0.5 bg-[var(--editorial-tone)]\" />\n <div className=\"flex gap-3.5\">\n <span\n aria-hidden\n className={cn(\n \"mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-full\",\n EDITORIAL_TONE_PLATE,\n EDITORIAL_TONE_FG,\n )}\n >\n <Icon className=\"size-3.5\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className={EDITORIAL_EYEBROW}>{eyebrow}</div>\n {typeof children === \"string\" ? (\n <p className={cn(\"mt-2.5\", EDITORIAL_BODY)}>{children}</p>\n ) : (\n children && <div className={cn(\"mt-2.5\", EDITORIAL_BODY)}>{children}</div>\n )}\n </div>\n </div>\n </aside>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n EDITORIAL_CAPTION,\n EDITORIAL_EYEBROW,\n editorialBlock,\n editorialFrame,\n} from \"./editorial-surface\";\n\nexport type EditorialChartPoint = {\n /** Optional per-point display string. Falls back to the raw value. */\n display?: string | null;\n key?: string;\n label: string;\n value: number;\n};\n\nexport type EditorialChartProps = {\n caption?: string | null;\n className?: string;\n label?: string;\n points: EditorialChartPoint[];\n title?: string | null;\n variant?: \"bar\" | \"line\";\n};\n\nconst VIEWBOX_WIDTH = 640;\nconst VIEWBOX_HEIGHT = 200;\n\nfunction formatPoint(point: EditorialChartPoint): string {\n return point.display ?? String(point.value);\n}\n\n/**\n * Horizontal bars.\n *\n * Laid out with grid and percentage widths rather than SVG: an article column\n * is narrow and reflows, and a CSS bar keeps its labels selectable, wrappable\n * and readable by assistive tech without a parallel text description.\n */\nfunction BarChart({ points, max }: { max: number; points: EditorialChartPoint[] }) {\n return (\n <div className=\"grid gap-3\">\n {points.map((point, index) => {\n // A bar with a real zero width is invisible, so the floor keeps the\n // smallest value legible as a value rather than as an empty track.\n const share = max > 0 ? Math.max((point.value / max) * 100, 1.5) : 0;\n\n return (\n <div\n key={point.key ?? `${index}-${point.label}`}\n className=\"grid grid-cols-[minmax(5rem,9rem)_1fr_auto] items-center gap-3\"\n >\n <span className=\"truncate text-sm text-muted-foreground\" title={point.label}>\n {point.label}\n </span>\n <span aria-hidden className=\"h-2.5 overflow-hidden rounded-full bg-muted\">\n {/* The measured width travels as a custom property so the class,\n not the element, still owns the `width` declaration. */}\n <span\n className=\"block h-full w-[var(--editorial-bar)] rounded-full bg-primary\"\n style={{ \"--editorial-bar\": `${share}%` } as CSSProperties}\n />\n </span>\n <span className=\"font-mono text-sm font-semibold tabular-nums text-foreground\">\n {formatPoint(point)}\n </span>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Trend line.\n *\n * SVG is the right tool once the shape between points carries the meaning. The\n * `viewBox` scales to the container, so no measurement pass and no client\n * JavaScript is required.\n */\nfunction LineChart({ max, points }: { max: number; points: EditorialChartPoint[] }) {\n const step = points.length > 1 ? VIEWBOX_WIDTH / (points.length - 1) : 0;\n const coords = points.map((point, index) => {\n const x = points.length > 1 ? index * step : VIEWBOX_WIDTH / 2;\n const y = VIEWBOX_HEIGHT - (max > 0 ? (point.value / max) * (VIEWBOX_HEIGHT - 16) : 0) - 8;\n return { x, y };\n });\n const path = coords\n .map((coord, index) => `${index === 0 ? \"M\" : \"L\"}${coord.x.toFixed(1)} ${coord.y.toFixed(1)}`)\n .join(\" \");\n\n return (\n <div>\n <svg\n aria-hidden\n className=\"h-40 w-full\"\n preserveAspectRatio=\"none\"\n viewBox={`0 0 ${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT}`}\n >\n <title>Trend</title>\n <path\n d={`${path} L${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT} L0 ${VIEWBOX_HEIGHT} Z`}\n // `--primary` is bare HSL channels; an SVG paint slot needs a colour.\n fill=\"color-mix(in srgb, hsl(var(--primary)) 10%, transparent)\"\n />\n <path\n d={path}\n fill=\"none\"\n stroke=\"hsl(var(--primary))\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n <div className=\"mt-3 flex justify-between gap-2\">\n {points.map((point, index) => (\n <div key={point.key ?? `${index}-${point.label}`} className=\"min-w-0 text-center\">\n <div className=\"font-mono text-sm font-semibold tabular-nums text-foreground\">\n {formatPoint(point)}\n </div>\n <div className=\"mt-0.5 truncate text-xs text-muted-foreground\">{point.label}</div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\n/**\n * Small inline data figure.\n *\n * Values are also emitted as a visually hidden table, so the chart is readable\n * without sight of the bars and copyable as data rather than as an image.\n */\nexport function EditorialChart({\n caption,\n className,\n label,\n points,\n title,\n variant = \"bar\",\n}: EditorialChartProps) {\n const visible = points.filter((point) => point.label.trim() && Number.isFinite(point.value));\n if (!visible.length) return null;\n\n const max = Math.max(...visible.map((point) => point.value), 0);\n\n return (\n <figure className={cn(editorialBlock({ spacing: \"loose\", width: \"breakout\" }), className)}>\n <div className={cn(editorialFrame({ elevation: \"resting\" }), \"px-5 py-5 sm:px-6\")}>\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-base font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n {variant === \"line\" ? (\n <LineChart max={max} points={visible} />\n ) : (\n <BarChart max={max} points={visible} />\n )}\n <table className=\"sr-only\">\n <caption>{title ?? label ?? \"Chart data\"}</caption>\n <tbody>\n {visible.map((point, index) => (\n <tr key={point.key ?? `${index}-${point.label}`}>\n <th scope=\"row\">{point.label}</th>\n <td>{formatPoint(point)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n {caption && <figcaption className={cn(\"mt-3\", EDITORIAL_CAPTION)}>{caption}</figcaption>}\n </figure>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport { EDITORIAL_EYEBROW, editorialBlock, editorialFrame } from \"./editorial-surface\";\n\nexport type EditorialComparisonRow = {\n cells: string[];\n key?: string;\n label: string;\n};\n\nexport type EditorialComparisonTableProps = {\n className?: string;\n columns: string[];\n /**\n * Header for the row-label column. Localize it — leaving this to a hardcoded\n * English default is how \"Dimension\" ended up in Chinese articles.\n */\n dimensionLabel?: string;\n label?: string;\n rows: EditorialComparisonRow[];\n title?: string | null;\n};\n\n/**\n * Matrix comparing options across dimensions.\n *\n * Below `md` the table restacks into one block per row and each cell carries\n * its own column label, so the reader never has to drag a table sideways on a\n * phone to find out which column a value belonged to.\n */\nexport function EditorialComparisonTable({\n className,\n columns,\n dimensionLabel = \"Dimension\",\n label,\n rows,\n title,\n}: EditorialComparisonTableProps) {\n const visibleColumns = columns.filter(Boolean);\n const visibleRows = rows.filter((row) => row.label || row.cells.some(Boolean));\n if (visibleColumns.length < 2 || !visibleRows.length) return null;\n\n return (\n <section\n className={cn(editorialBlock({ spacing: \"loose\", width: \"breakout\" }), className)}\n aria-label={title ?? label ?? undefined}\n >\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <div className={cn(editorialFrame({ elevation: \"resting\" }), \"overflow-hidden\")}>\n <table className=\"w-full border-collapse text-left text-sm\">\n <thead className=\"hidden md:table-header-group\">\n <tr className=\"bg-muted\">\n <th\n className=\"w-[22%] border-b border-border px-4 py-3 font-semibold text-foreground\"\n scope=\"col\"\n >\n {dimensionLabel}\n </th>\n {visibleColumns.map((column) => (\n <th\n key={column}\n className=\"border-b border-border px-4 py-3 font-semibold text-foreground\"\n scope=\"col\"\n >\n {column}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"block md:table-row-group\">\n {visibleRows.map((row, rowIndex) => (\n <tr\n key={row.key ?? `${rowIndex}-${row.label}`}\n className=\"block border-b border-border last:border-b-0 md:table-row\"\n >\n <th\n className=\"block bg-muted px-4 pb-2 pt-3 text-left align-top font-semibold text-foreground md:table-cell md:bg-transparent md:py-3\"\n scope=\"row\"\n >\n {row.label}\n </th>\n {visibleColumns.map((column, cellIndex) => (\n <td\n key={`${row.key ?? rowIndex}-${column}`}\n className=\"block px-4 py-2 align-top leading-6 text-muted-foreground last:pb-3 md:table-cell md:py-3 md:last:pb-3\"\n >\n <span className={cn(\"mb-1 block md:hidden\", EDITORIAL_EYEBROW)}>{column}</span>\n {row.cells[cellIndex]}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { EDITORIAL_CAPTION, editorialBlock, editorialFrame } from \"./editorial-surface\";\n\nexport type EditorialDataTableRow = {\n cells: ReactNode[];\n key: string;\n};\n\nexport type EditorialDataTableProps = {\n caption?: ReactNode;\n className?: string;\n head: ReactNode[];\n rows: EditorialDataTableRow[];\n};\n\n/**\n * Table rendered from author-written markup, where cells carry links, code and\n * inline math rather than plain strings.\n *\n * Cells are `ReactNode`, so unlike `EditorialComparisonTable` this cannot\n * restack into labelled blocks on small screens — it scrolls instead, inside a\n * framed container that makes the clipped edge obvious.\n */\nexport function EditorialDataTable({ caption, className, head, rows }: EditorialDataTableProps) {\n if (!head.length || !rows.length) return null;\n\n return (\n <figure className={cn(editorialBlock({ spacing: \"normal\", width: \"breakout\" }), className)}>\n <div className={cn(editorialFrame({ elevation: \"resting\" }), \"overflow-x-auto\")}>\n <table className=\"w-full min-w-[36rem] border-collapse text-left text-sm text-muted-foreground\">\n <thead className=\"bg-muted\">\n <tr>\n {head.map((cell, index) => (\n <th\n // Header cells are rendered nodes with no stable identity of\n // their own; column position is the identity.\n key={`head-${index}`}\n className=\"border-b border-border px-4 py-3 font-semibold text-foreground\"\n scope=\"col\"\n >\n {cell}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.key} className=\"border-b border-border last:border-b-0\">\n {row.cells.map((cell, cellIndex) => (\n <td key={`${row.key}-${cellIndex}`} className=\"px-4 py-3 align-top leading-6\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n {caption && <figcaption className={cn(\"mt-3\", EDITORIAL_CAPTION)}>{caption}</figcaption>}\n </figure>\n );\n}\n","import { cn } from \"../utils/cn\";\n\nexport type EditorialDividerProps = {\n className?: string;\n};\n\n/**\n * Section break inside an article.\n *\n * Marks a change of movement, not a new heading — an `<hr>` with a centred\n * marker rather than a rule that would read as the end of the piece.\n */\nexport function EditorialDivider({ className }: EditorialDividerProps) {\n return (\n <div className={cn(\"my-14 flex items-center gap-4\", className)}>\n <hr className=\"h-px flex-1 border-0 bg-border\" />\n <span aria-hidden className=\"size-1.5 rounded-full bg-[hsl(var(--primary))]\" />\n <hr className=\"h-px flex-1 border-0 bg-border\" />\n </div>\n );\n}\n","import { SiGithub, SiX, SiYoutube } from \"@icons-pack/react-simple-icons\";\nimport { ArrowUpRight, Globe } from \"@nebutra/icons\";\nimport type { ComponentType } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { EDITORIAL_CAPTION, editorialBlock, editorialFrame } from \"./editorial-surface\";\n\nexport const EDITORIAL_EMBED_PROVIDERS = [\"youtube\", \"x\", \"github\", \"website\"] as const;\n\nexport type EditorialEmbedProvider = (typeof EDITORIAL_EMBED_PROVIDERS)[number];\n\nconst PROVIDER_ICON: Record<EditorialEmbedProvider, ComponentType<{ className?: string }>> = {\n github: SiGithub,\n website: Globe,\n x: SiX,\n youtube: SiYoutube,\n};\n\nconst PROVIDER_NAME: Record<EditorialEmbedProvider, string> = {\n github: \"GitHub\",\n website: \"Website\",\n x: \"X\",\n youtube: \"YouTube\",\n};\n\nexport type EditorialEmbedCardProps = {\n caption?: string | null;\n className?: string;\n provider?: EditorialEmbedProvider;\n title: string;\n url: string;\n};\n\nfunction hostname(url: string): string | null {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return null;\n }\n}\n\nexport function isEditorialEmbedProvider(value: unknown): value is EditorialEmbedProvider {\n return (\n typeof value === \"string\" && (EDITORIAL_EMBED_PROVIDERS as readonly string[]).includes(value)\n );\n}\n\n/**\n * Link-out card for third-party media.\n *\n * Deliberately not an iframe: an embedded player ships the provider's scripts\n * and cookies into the article and moves the layout around while it loads. The\n * card states the provider, keeps the destination visible, and leaves the\n * decision to the reader.\n */\nexport function EditorialEmbedCard({\n caption,\n className,\n provider = \"website\",\n title,\n url,\n}: EditorialEmbedCardProps) {\n if (!title.trim() || !url.trim()) return null;\n\n const Icon = PROVIDER_ICON[provider];\n const host = hostname(url);\n\n return (\n <figure className={cn(editorialBlock({ spacing: \"normal\" }), className)}>\n <a\n className={cn(\n editorialFrame({ elevation: \"resting\" }),\n \"group flex items-center gap-4 p-4 transition-shadow hover:shadow-ambient-md\",\n )}\n href={url}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n <span\n aria-hidden\n className=\"flex size-10 shrink-0 items-center justify-center rounded-[var(--radius-md)] border border-border bg-muted text-foreground\"\n >\n <Icon className=\"size-4\" />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-[0.9375rem] font-semibold leading-6 text-foreground\">\n {title}\n </span>\n <span className=\"mt-0.5 block truncate text-sm text-muted-foreground\">\n {[PROVIDER_NAME[provider], host].filter(Boolean).join(\" · \")}\n </span>\n </span>\n <ArrowUpRight\n aria-hidden\n className=\"size-4 shrink-0 text-muted-foreground transition-colors group-hover:text-[hsl(var(--primary))]\"\n />\n </a>\n {caption && <figcaption className={cn(\"mt-2.5\", EDITORIAL_CAPTION)}>{caption}</figcaption>}\n </figure>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type EditorialEntityChipProps = {\n className?: string;\n href?: string | null;\n /** Logo slot. Apps pass their own image component so this stays framework-free. */\n logo?: ReactNode;\n name: string;\n};\n\n/**\n * Inline reference to a company, product or project.\n *\n * Sized to sit inside a sentence without changing its line height, which is\n * why the logo plate is `1em` rather than a fixed pixel size.\n */\nexport function EditorialEntityChip({ className, href, logo, name }: EditorialEntityChipProps) {\n if (!name.trim()) return null;\n\n const content = (\n <>\n {logo && (\n <span\n aria-hidden\n className=\"inline-flex size-[1.1em] shrink-0 items-center justify-center overflow-hidden rounded-[0.25em] bg-muted\"\n >\n {logo}\n </span>\n )}\n <span>{name}</span>\n </>\n );\n\n const shared = cn(\n \"mx-0.5 inline-flex items-baseline gap-1 align-baseline font-medium text-foreground\",\n className,\n );\n\n if (!href) {\n return <span className={shared}>{content}</span>;\n }\n\n return (\n <a\n className={cn(\n shared,\n \"underline decoration-border decoration-dotted underline-offset-4 transition-colors hover:decoration-[hsl(var(--primary))] hover:decoration-solid\",\n )}\n href={href}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {content}\n </a>\n );\n}\n","import { Plus } from \"@nebutra/icons\";\nimport { cn } from \"../utils/cn\";\nimport { EDITORIAL_BODY, EDITORIAL_EYEBROW, editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialFaqItem = {\n answer: string;\n key?: string;\n question: string;\n};\n\nexport type EditorialFaqProps = {\n className?: string;\n /** Open the first entry on load, for a short list where the answer is the point. */\n defaultOpenFirst?: boolean;\n items: EditorialFaqItem[];\n label?: string;\n title?: string | null;\n};\n\n/**\n * Collapsible question list.\n *\n * Built on native `<details>` rather than a JS disclosure: it costs no client\n * bundle, works before hydration, is keyboard-operable for free, and lets\n * in-page find surface answers inside collapsed entries.\n */\nexport function EditorialFaq({\n className,\n defaultOpenFirst = false,\n items,\n label,\n title,\n}: EditorialFaqProps) {\n const visible = items.filter((item) => item.question.trim() && item.answer.trim());\n if (!visible.length) return null;\n\n return (\n <section\n aria-label={title ?? label ?? undefined}\n className={cn(editorialBlock({ spacing: \"loose\" }), className)}\n >\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <div className=\"divide-y divide-border border-y border-border\">\n {visible.map((item, index) => (\n <details\n key={item.key ?? `${index}-${item.question.slice(0, 24)}`}\n className=\"group\"\n open={defaultOpenFirst && index === 0}\n >\n <summary className=\"flex cursor-pointer list-none items-start justify-between gap-4 py-4 text-[0.9375rem] font-semibold leading-6 text-foreground marker:hidden [&::-webkit-details-marker]:hidden\">\n {item.question}\n <Plus\n aria-hidden\n className=\"mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-micro group-open:rotate-45\"\n />\n </summary>\n <p className={cn(\"pb-4 pr-8\", EDITORIAL_BODY)}>{item.answer}</p>\n </details>\n ))}\n </div>\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { EDITORIAL_CAPTION, EDITORIAL_EYEBROW, editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialFigureProps = {\n caption?: ReactNode;\n className?: string;\n /**\n * Image slot. Apps pass their own image component — keeping `next/image` out\n * of this package is what lets it render in Storybook and non-Next surfaces.\n */\n media: ReactNode;\n width?: \"column\" | \"breakout\" | \"full\";\n};\n\n/** Single image with an optional caption. */\nexport function EditorialFigure({\n caption,\n className,\n media,\n width = \"column\",\n}: EditorialFigureProps) {\n return (\n <figure className={cn(editorialBlock({ spacing: \"normal\", width }), className)}>\n <div className=\"relative overflow-hidden rounded-[var(--radius-xl)] border border-border bg-muted shadow-ambient-sm\">\n {media}\n </div>\n {caption && (\n <figcaption className={cn(\"mt-3 text-center\", EDITORIAL_CAPTION)}>{caption}</figcaption>\n )}\n </figure>\n );\n}\n\nexport type EditorialFigureGroupProps = {\n className?: string;\n /** Rendered figures. Two or three read best; more should become a gallery. */\n children: ReactNode;\n label?: string;\n title?: string | null;\n variant?: \"grid\" | \"comparison\" | \"sequence\";\n};\n\nconst GROUP_LAYOUT: Record<NonNullable<EditorialFigureGroupProps[\"variant\"]>, string> = {\n comparison: \"grid gap-4 sm:grid-cols-2\",\n grid: \"grid gap-4 sm:grid-cols-2\",\n sequence: \"grid gap-4\",\n};\n\n/** Set of related figures shown together. */\nexport function EditorialFigureGroup({\n children,\n className,\n label,\n title,\n variant = \"grid\",\n}: EditorialFigureGroupProps) {\n return (\n <section\n aria-label={title ?? label ?? undefined}\n className={cn(editorialBlock({ spacing: \"loose\", width: \"breakout\" }), className)}\n >\n {(label || title) && (\n <div className=\"mb-4\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <div className={GROUP_LAYOUT[variant]}>{children}</div>\n </section>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport { EDITORIAL_EYEBROW, editorialBlock, editorialFrame } from \"./editorial-surface\";\n\nexport type EditorialKeyTakeawayItem = {\n key?: string;\n text: string;\n};\n\nexport type EditorialKeyTakeawaysProps = {\n className?: string;\n items: EditorialKeyTakeawayItem[];\n /** Eyebrow copy. Pass a localized string; the default is English. */\n label?: string;\n title?: string | null;\n};\n\n/**\n * The summary panel that opens a long piece.\n *\n * Numbering is a hairline-separated ordered list rather than bullets or cards —\n * the point is that a reader can take four lines and leave, so nothing should\n * compete with the lines themselves.\n */\nexport function EditorialKeyTakeaways({\n className,\n items,\n label = \"Key takeaways\",\n title,\n}: EditorialKeyTakeawaysProps) {\n const visible = items.filter((item) => item.text.trim());\n if (!visible.length) return null;\n\n return (\n <aside\n aria-label={title ?? label}\n className={cn(\n editorialBlock({ spacing: \"loose\", width: \"breakout\" }),\n editorialFrame({ elevation: \"resting\", radius: \"panel\" }),\n \"px-6 py-6 sm:px-8 sm:py-7\",\n className,\n )}\n >\n <div className={EDITORIAL_EYEBROW}>{label}</div>\n {title && <h2 className=\"mt-3 text-xl font-semibold leading-7 text-foreground\">{title}</h2>}\n <ol className=\"mt-5 divide-y divide-border border-t border-border\">\n {visible.map((item, index) => (\n <li\n key={item.key ?? `${index}-${item.text.slice(0, 24)}`}\n className=\"flex gap-4 py-3.5 first:pt-4\"\n >\n <span\n aria-hidden\n className=\"mt-0.5 shrink-0 font-mono text-xs font-semibold tabular-nums text-muted-foreground\"\n >\n {String(index + 1).padStart(2, \"0\")}\n </span>\n <p className=\"text-[0.9375rem] leading-7 text-foreground\">{item.text}</p>\n </li>\n ))}\n </ol>\n </aside>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport { EDITORIAL_EYEBROW } from \"./editorial-surface\";\n\nexport type EditorialMarginNoteProps = {\n children?: string | null;\n className?: string;\n label?: string;\n title?: string | null;\n};\n\n/**\n * Short aside that steps out into the right margin on wide screens.\n *\n * Below `xl` there is no margin to step into, so it degrades to an indented\n * inline note rather than a floated box that would strand a two-word orphan\n * beside it.\n */\nexport function EditorialMarginNote({\n children,\n className,\n label,\n title,\n}: EditorialMarginNoteProps) {\n if (!title && !children) return null;\n\n return (\n <aside\n className={cn(\n \"my-6 border-l-2 border-border py-1 pl-4 text-sm leading-6 text-muted-foreground\",\n \"xl:float-right xl:-mr-56 xl:my-2 xl:ml-8 xl:w-48 xl:border-l xl:pl-4\",\n className,\n )}\n >\n {label && <div className={cn(\"mb-1.5\", EDITORIAL_EYEBROW)}>{label}</div>}\n {title && <p className=\"font-semibold text-foreground\">{title}</p>}\n {children && <p className={cn(title && \"mt-1\")}>{children}</p>}\n </aside>\n );\n}\n","import { External } from \"@nebutra/icons\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialPullQuoteProps = {\n /** Name of the speaker or the work being quoted. */\n attribution?: string | null;\n className?: string;\n /** Portrait slot. Apps pass their own image component so this stays framework-free. */\n portrait?: ReactNode;\n quote: string;\n /** Title, company or context under the attribution. */\n role?: string | null;\n sourceHref?: string | null;\n};\n\n/**\n * Display quote lifted out of the reading column.\n *\n * There is no oversized quotation glyph: at this size the type itself already\n * reads as a quote, and the glyph only competes with the first word. Hairlines\n * above and below do the separating.\n */\nexport function EditorialPullQuote({\n attribution,\n className,\n portrait,\n quote,\n role,\n sourceHref,\n}: EditorialPullQuoteProps) {\n if (!quote.trim()) return null;\n\n const name = attribution ? (\n sourceHref ? (\n <a\n className=\"inline-flex items-center gap-1.5 text-foreground underline decoration-border underline-offset-4 transition-colors hover:decoration-[hsl(var(--primary))]\"\n href={sourceHref}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n {attribution}\n <External aria-hidden className=\"size-3.5 text-muted-foreground\" />\n </a>\n ) : (\n attribution\n )\n ) : null;\n\n return (\n <figure\n className={cn(\n editorialBlock({ spacing: \"loose\", width: \"breakout\" }),\n \"border-y border-border py-8 sm:py-10\",\n className,\n )}\n >\n <blockquote className=\"text-pretty text-xl font-medium leading-9 text-foreground sm:text-[1.6rem] sm:leading-[2.6rem]\">\n {quote}\n </blockquote>\n {(name || role || portrait) && (\n <figcaption className=\"mt-6 flex items-center gap-3\">\n {portrait && (\n <span className=\"size-9 shrink-0 overflow-hidden rounded-full bg-muted\">\n {portrait}\n </span>\n )}\n <span className=\"min-w-0\">\n {name && <span className=\"block text-sm font-semibold text-foreground\">{name}</span>}\n {role && <span className=\"mt-0.5 block text-sm text-muted-foreground\">{role}</span>}\n </span>\n </figcaption>\n )}\n </figure>\n );\n}\n","import { ArrowUpRight } from \"@nebutra/icons\";\nimport { cn } from \"../utils/cn\";\nimport { EDITORIAL_BODY, EDITORIAL_EYEBROW, editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialSourceItem = {\n accessedAt?: string | null;\n author?: string | null;\n key?: string;\n publisher?: string | null;\n summary?: string | null;\n title: string;\n url: string;\n};\n\nexport type EditorialSourceIndexProps = {\n className?: string;\n /** Eyebrow copy, e.g. \"Source index\" / \"资料索引\". */\n label?: string;\n sources: EditorialSourceItem[];\n /** Sentence under the eyebrow. Apps build this so pluralization stays localized. */\n summary?: string | null;\n};\n\nfunction hostname(url: string): string | null {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return null;\n }\n}\n\n/**\n * Numbered reference list closing a researched piece.\n *\n * A numbered hairline list rather than a card grid: references are read in\n * order and cited by number from the body, and boxing each one hides that\n * ordering behind a wall of equal-weight rectangles.\n */\nexport function EditorialSourceIndex({\n className,\n label = \"Source index\",\n sources,\n summary,\n}: EditorialSourceIndexProps) {\n const visible = sources.filter((source) => source.title && source.url);\n if (!visible.length) return null;\n\n return (\n <section\n aria-label={label}\n className={cn(editorialBlock({ spacing: \"loose\", width: \"breakout\" }), className)}\n >\n <div className=\"border-b border-border pb-3\">\n <div className={EDITORIAL_EYEBROW}>{label}</div>\n {summary && <p className={cn(\"mt-2\", EDITORIAL_BODY)}>{summary}</p>}\n </div>\n <ol className=\"divide-y divide-border\">\n {visible.map((source, index) => {\n const meta = [source.publisher, source.author, source.accessedAt].filter(Boolean);\n const host = hostname(source.url);\n\n return (\n <li key={source.key ?? source.url}>\n <a\n className=\"group flex gap-4 py-4 transition-colors hover:bg-muted/60\"\n href={source.url}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >\n <span\n aria-hidden\n className=\"mt-0.5 shrink-0 font-mono text-xs font-semibold tabular-nums text-muted-foreground\"\n >\n {String(index + 1).padStart(2, \"0\")}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start justify-between gap-3\">\n <span className=\"text-[0.9375rem] font-semibold leading-6 text-foreground\">\n {source.title}\n </span>\n <ArrowUpRight\n aria-hidden\n className=\"mt-0.5 size-4 shrink-0 text-muted-foreground transition-colors group-hover:text-[hsl(var(--primary))]\"\n />\n </span>\n {(meta.length > 0 || host) && (\n <span className=\"mt-1 block text-sm text-muted-foreground\">\n {(meta.length ? meta : [host]).join(\" · \")}\n </span>\n )}\n {source.summary && (\n <span className=\"mt-1.5 block text-sm leading-6 text-muted-foreground\">\n {source.summary}\n </span>\n )}\n </span>\n </a>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport {\n EDITORIAL_CAPTION,\n EDITORIAL_EYEBROW,\n EDITORIAL_FIGURE,\n editorialBlock,\n} from \"./editorial-surface\";\n\nexport type EditorialStatItem = {\n caption?: string | null;\n key?: string;\n label: string;\n value: string;\n};\n\nexport type EditorialStatGridProps = {\n className?: string;\n items: EditorialStatItem[];\n label?: string;\n title?: string | null;\n};\n\nconst COLUMNS: Record<number, string> = {\n 1: \"sm:grid-cols-1\",\n 2: \"sm:grid-cols-2\",\n 3: \"sm:grid-cols-3\",\n 4: \"sm:grid-cols-2 lg:grid-cols-4\",\n};\n\n/**\n * Row of headline figures.\n *\n * Cells are separated by shared hairlines rather than being individual cards:\n * boxing each number makes the set read as four unrelated facts, where the\n * point of a stat row is that they are one measurement taken four ways.\n */\nexport function EditorialStatGrid({ className, items, label, title }: EditorialStatGridProps) {\n const visible = items.filter((item) => item.value.trim() && item.label.trim());\n if (!visible.length) return null;\n\n const columns = COLUMNS[Math.min(visible.length, 4)] ?? COLUMNS[4];\n\n return (\n <section\n className={cn(editorialBlock({ spacing: \"loose\", width: \"breakout\" }), className)}\n aria-label={title ?? label ?? undefined}\n >\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <dl\n className={cn(\n \"grid divide-y divide-border border-y border-border\",\n columns,\n \"sm:divide-x sm:divide-y-0\",\n )}\n >\n {visible.map((item, index) => (\n <div\n key={item.key ?? `${index}-${item.label}`}\n className=\"px-0 py-5 sm:px-6 sm:first:pl-0 sm:last:pr-0\"\n >\n <dt className=\"sr-only\">{item.label}</dt>\n <dd>\n <span className={cn(\"block text-3xl leading-none sm:text-4xl\", EDITORIAL_FIGURE)}>\n {item.value}\n </span>\n <span className=\"mt-3 block text-sm font-medium text-foreground\">{item.label}</span>\n {item.caption && (\n <span className={cn(\"mt-1.5 block\", EDITORIAL_CAPTION)}>{item.caption}</span>\n )}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport { EDITORIAL_BODY, EDITORIAL_EYEBROW, editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialStep = {\n body?: string | null;\n key?: string;\n title: string;\n};\n\nexport type EditorialStepLadderProps = {\n className?: string;\n label?: string;\n steps: EditorialStep[];\n title?: string | null;\n};\n\n/**\n * Ordered procedure.\n *\n * Distinct from `EditorialTimeline`: a timeline reports what happened and is\n * marked with dates, a ladder instructs and is marked with positions the reader\n * is meant to follow in order.\n */\nexport function EditorialStepLadder({ className, label, steps, title }: EditorialStepLadderProps) {\n const visible = steps.filter((step) => step.title.trim());\n if (!visible.length) return null;\n\n return (\n <section\n aria-label={title ?? label ?? undefined}\n className={cn(editorialBlock({ spacing: \"loose\" }), className)}\n >\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <ol className=\"grid gap-0\">\n {visible.map((step, index) => (\n <li\n key={step.key ?? `${index}-${step.title}`}\n className=\"relative grid grid-cols-[2rem_1fr] gap-4 pb-6 last:pb-0\"\n >\n {index < visible.length - 1 && (\n <span\n aria-hidden\n className=\"absolute bottom-2 left-4 top-9 w-px -translate-x-1/2 bg-border\"\n />\n )}\n <span\n aria-hidden\n className=\"z-10 flex size-8 items-center justify-center rounded-full border border-border bg-background font-mono text-xs font-semibold tabular-nums text-foreground\"\n >\n {index + 1}\n </span>\n <div className=\"min-w-0 pt-1.5\">\n <h4 className=\"text-[0.9375rem] font-semibold leading-6 text-foreground\">\n {step.title}\n </h4>\n {step.body && <p className={cn(\"mt-1.5\", EDITORIAL_BODY)}>{step.body}</p>}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import { cn } from \"../utils/cn\";\nimport { EDITORIAL_BODY, EDITORIAL_EYEBROW, editorialBlock } from \"./editorial-surface\";\n\nexport type EditorialTimelineItem = {\n body?: string | null;\n /** Short marker: a year, a quarter, a version. Rendered in tabular figures. */\n marker: string;\n key?: string;\n title: string;\n};\n\nexport type EditorialTimelineProps = {\n className?: string;\n items: EditorialTimelineItem[];\n label?: string;\n title?: string | null;\n};\n\n/**\n * Chronology of events along a single rail.\n *\n * The rail is a 1px border on the list rather than a drawn line per item, so\n * it stays continuous between entries and collapses cleanly when an entry has\n * no body.\n */\nexport function EditorialTimeline({ className, items, label, title }: EditorialTimelineProps) {\n const visible = items.filter((item) => item.marker.trim() && item.title.trim());\n if (!visible.length) return null;\n\n return (\n <section\n aria-label={title ?? label ?? undefined}\n className={cn(editorialBlock({ spacing: \"loose\" }), className)}\n >\n {(label || title) && (\n <div className=\"mb-5\">\n {label && <div className={EDITORIAL_EYEBROW}>{label}</div>}\n {title && (\n <h3 className=\"mt-2 text-lg font-semibold leading-6 text-foreground\">{title}</h3>\n )}\n </div>\n )}\n <ol className=\"ml-[3.25rem] border-l border-border sm:ml-24\">\n {visible.map((item, index) => (\n <li key={item.key ?? `${index}-${item.marker}`} className=\"relative pb-7 pl-6 last:pb-0\">\n <span\n aria-hidden\n className=\"absolute -left-[0.3125rem] top-1.5 size-2.5 rounded-full border-2 border-background bg-[hsl(var(--primary))]\"\n />\n <span\n className=\"absolute right-[calc(100%+1.5rem)] top-0 whitespace-nowrap font-mono text-xs font-semibold tabular-nums leading-6 text-muted-foreground\"\n aria-hidden\n >\n {item.marker}\n </span>\n <h4 className=\"text-[0.9375rem] font-semibold leading-6 text-foreground\">\n <span className=\"sr-only\">{item.marker} — </span>\n {item.title}\n </h4>\n {item.body && <p className={cn(\"mt-1.5\", EDITORIAL_BODY)}>{item.body}</p>}\n </li>\n ))}\n </ol>\n </section>\n );\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
type EmptyStateVariant = "blank-slate" | "informational" | "educational" | "guide" | "no-results" | "cleared" | "permission" | "error";
|
|
5
|
+
type EmptyStateSize = "sm" | "md" | "lg";
|
|
6
|
+
type EmptyStateAlign = "center" | "start";
|
|
7
|
+
interface EmptyStateRootProps extends Omit<React.HTMLAttributes<HTMLElement>, "title" | "children"> {
|
|
8
|
+
title: React.ReactNode;
|
|
9
|
+
description?: React.ReactNode;
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
/** Preferred CTA slot. Use real Button/Link elements. */
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
/** Compatibility alias for the primary CTA. Prefer children for new code. */
|
|
14
|
+
action?: React.ReactNode;
|
|
15
|
+
/** Compatibility alias for the secondary CTA. Prefer children for new code. */
|
|
16
|
+
link?: React.ReactNode;
|
|
17
|
+
variant?: EmptyStateVariant;
|
|
18
|
+
size?: EmptyStateSize;
|
|
19
|
+
align?: EmptyStateAlign;
|
|
20
|
+
/** Use for empty states that appear after async filtering changes. */
|
|
21
|
+
live?: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface EmptyStateIconProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
24
|
+
icon: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
declare const EmptyStateIcon: {
|
|
27
|
+
({ className, icon, ref, ...props }: EmptyStateIconProps & {
|
|
28
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
29
|
+
}): react_jsx_runtime.JSX.Element;
|
|
30
|
+
displayName: string;
|
|
31
|
+
};
|
|
32
|
+
declare const EmptyStateRoot: {
|
|
33
|
+
({ className, title, description, icon, children, action, link, style, variant, size, align, live, ref, ...props }: EmptyStateRootProps & {
|
|
34
|
+
ref?: React.Ref<HTMLElement> | undefined;
|
|
35
|
+
}): react_jsx_runtime.JSX.Element;
|
|
36
|
+
displayName: string;
|
|
37
|
+
};
|
|
38
|
+
type EmptyStateTone = "default" | "branded" | "subtle";
|
|
39
|
+
interface EmptyStateProps {
|
|
40
|
+
/** Primary message. */
|
|
41
|
+
title: string;
|
|
42
|
+
/** Supporting description. */
|
|
43
|
+
description?: string;
|
|
44
|
+
/** Visual anchor. When omitted and `tone="branded"`, a default `<BrandMark>` is rendered. */
|
|
45
|
+
mascot?: React.ReactNode;
|
|
46
|
+
/** Inline icon shown above the title. Ignored when `mascot` is provided. */
|
|
47
|
+
icon?: React.ReactNode;
|
|
48
|
+
/** Primary call-to-action node. */
|
|
49
|
+
action?: React.ReactNode;
|
|
50
|
+
/** Secondary call-to-action node. */
|
|
51
|
+
secondaryAction?: React.ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Visual tone.
|
|
54
|
+
* - `default`: neutral bordered state
|
|
55
|
+
* - `branded`: BrandMark anchor for first-touch panels
|
|
56
|
+
* - `subtle`: quieter inline state
|
|
57
|
+
*/
|
|
58
|
+
tone?: EmptyStateTone;
|
|
59
|
+
size?: EmptyStateSize;
|
|
60
|
+
className?: string;
|
|
61
|
+
}
|
|
62
|
+
/** The simple form: props in, a composed Root out. */
|
|
63
|
+
declare function EmptyStateSimple({ title, description, mascot, icon, action, secondaryAction, tone, size, className, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
|
|
64
|
+
/**
|
|
65
|
+
* One EmptyState, two forms. `<EmptyState title … />` renders the simple form;
|
|
66
|
+
* `EmptyState.Root` / `EmptyState.Icon` compose it by hand. It used to be two
|
|
67
|
+
* symbols with one name — a component from @nebutra/ui/layout and a plain
|
|
68
|
+
* `{ Root, Icon }` object from /primitives — so the import path decided
|
|
69
|
+
* whether `<EmptyState />` rendered or threw.
|
|
70
|
+
*/
|
|
71
|
+
declare const EmptyState: typeof EmptyStateSimple & {
|
|
72
|
+
Root: {
|
|
73
|
+
({ className, title, description, icon, children, action, link, style, variant, size, align, live, ref, ...props }: EmptyStateRootProps & {
|
|
74
|
+
ref?: React.Ref<HTMLElement> | undefined;
|
|
75
|
+
}): react_jsx_runtime.JSX.Element;
|
|
76
|
+
displayName: string;
|
|
77
|
+
};
|
|
78
|
+
Icon: {
|
|
79
|
+
({ className, icon, ref, ...props }: EmptyStateIconProps & {
|
|
80
|
+
ref?: React.Ref<HTMLDivElement> | undefined;
|
|
81
|
+
}): react_jsx_runtime.JSX.Element;
|
|
82
|
+
displayName: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export { EmptyState as E, type EmptyStateProps as a, type EmptyStateAlign as b, EmptyStateIcon as c, type EmptyStateIconProps as d, EmptyStateRoot as e, type EmptyStateRootProps as f, type EmptyStateSize as g, type EmptyStateVariant as h };
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -87,6 +87,23 @@ declare function useDebouncedValue<T>(value: T, delay?: number): T;
|
|
|
87
87
|
*/
|
|
88
88
|
declare function useMediaQuery(query: string): boolean;
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Whether a pending indicator should be on screen right now.
|
|
92
|
+
*
|
|
93
|
+
* A spinner that flashes for 80ms reads as a glitch, and one that appears and
|
|
94
|
+
* disappears inside 200ms reads as jank. So: stay hidden until the wait is
|
|
95
|
+
* noticeable (`showDelayMs`), and once shown, stay long enough to be read
|
|
96
|
+
* (`minVisibleMs`) even if the work finished in between. Defaults come from the
|
|
97
|
+
* interaction contract (Vercel Web Interface Guidelines).
|
|
98
|
+
*
|
|
99
|
+
* const visible = usePendingVisible(isPending);
|
|
100
|
+
* return visible ? <Spinner /> : null;
|
|
101
|
+
*/
|
|
102
|
+
declare function usePendingVisible(pending: boolean, { showDelayMs, minVisibleMs, }?: {
|
|
103
|
+
showDelayMs?: number;
|
|
104
|
+
minVisibleMs?: number;
|
|
105
|
+
}): boolean;
|
|
106
|
+
|
|
90
107
|
/**
|
|
91
108
|
* Returns true if the user has enabled prefers-reduced-motion.
|
|
92
109
|
* Use this to disable animations, skip transitions, or simplify motion.
|
|
@@ -150,4 +167,4 @@ interface DwellState {
|
|
|
150
167
|
*/
|
|
151
168
|
declare function useScrollDwell(ref: RefObject<HTMLElement | null>, config?: DwellConfig): DwellState;
|
|
152
169
|
|
|
153
|
-
export { type DwellConfig, DwellHint, type DwellHintProps, type DwellState, useDebouncedRefresh, useDebouncedValue, useMediaQuery, useReducedMotion, useScrollDwell };
|
|
170
|
+
export { type DwellConfig, DwellHint, type DwellHintProps, type DwellState, useDebouncedRefresh, useDebouncedValue, useMediaQuery, usePendingVisible, useReducedMotion, useScrollDwell };
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,13 +1,87 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import * as
|
|
2
|
+
import * as React2 from 'react';
|
|
3
3
|
import { useRef, useEffect, useCallback, useState } from 'react';
|
|
4
4
|
import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
|
-
import {
|
|
6
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
7
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
8
8
|
import { useDebounceCallback, useDebounceValue, useMediaQuery as useMediaQuery$1 } from 'usehooks-ts';
|
|
9
9
|
|
|
10
10
|
// src/hooks/DwellHint.tsx
|
|
11
|
+
|
|
12
|
+
// src/utils/tw-merge-theme.generated.ts
|
|
13
|
+
var TW_MERGE_THEME = {
|
|
14
|
+
breakpoint: ["3xl", "shell", "tight", "xs"],
|
|
15
|
+
container: ["content", "text", "wide"],
|
|
16
|
+
ease: ["brand", "in", "in-out", "out", "spring"],
|
|
17
|
+
font: ["cn", "display", "heading", "mono", "sans"],
|
|
18
|
+
leading: ["display", "heading"],
|
|
19
|
+
radius: ["2xl", "3xl", "button", "card", "full", "lg", "md", "none", "panel", "sm", "xl", "xs"],
|
|
20
|
+
shadow: [
|
|
21
|
+
"2xl",
|
|
22
|
+
"ambient-glow",
|
|
23
|
+
"ambient-lg",
|
|
24
|
+
"ambient-md",
|
|
25
|
+
"ambient-sm",
|
|
26
|
+
"brand",
|
|
27
|
+
"brand-lg",
|
|
28
|
+
"glass-lg",
|
|
29
|
+
"glass-md",
|
|
30
|
+
"glass-sm",
|
|
31
|
+
"glow-accent",
|
|
32
|
+
"glow-accent-lg",
|
|
33
|
+
"glow-accent-sm",
|
|
34
|
+
"glow-primary",
|
|
35
|
+
"lg",
|
|
36
|
+
"md",
|
|
37
|
+
"sheen",
|
|
38
|
+
"sm",
|
|
39
|
+
"xl",
|
|
40
|
+
"xs"
|
|
41
|
+
],
|
|
42
|
+
text: [
|
|
43
|
+
"2xl",
|
|
44
|
+
"2xs",
|
|
45
|
+
"3xl",
|
|
46
|
+
"4xl",
|
|
47
|
+
"5xl",
|
|
48
|
+
"6xl",
|
|
49
|
+
"7xl",
|
|
50
|
+
"8xl",
|
|
51
|
+
"9xl",
|
|
52
|
+
"base",
|
|
53
|
+
"body",
|
|
54
|
+
"display",
|
|
55
|
+
"label",
|
|
56
|
+
"lg",
|
|
57
|
+
"meta",
|
|
58
|
+
"sm",
|
|
59
|
+
"ui",
|
|
60
|
+
"xl",
|
|
61
|
+
"xs"
|
|
62
|
+
],
|
|
63
|
+
tracking: ["display", "heading", "label", "tight"]
|
|
64
|
+
};
|
|
65
|
+
var TW_MERGE_CLASS_GROUPS = {
|
|
66
|
+
duration: [{ duration: ["cinematic", "flow", "micro", "reveal"] }]
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/utils/cn.ts
|
|
70
|
+
var twMerge = extendTailwindMerge({
|
|
71
|
+
extend: {
|
|
72
|
+
theme: Object.fromEntries(
|
|
73
|
+
Object.entries(TW_MERGE_THEME).map(([key, values]) => [key, [...values]])
|
|
74
|
+
),
|
|
75
|
+
classGroups: Object.fromEntries(
|
|
76
|
+
Object.entries(TW_MERGE_CLASS_GROUPS).map(([key, groups]) => [
|
|
77
|
+
key,
|
|
78
|
+
groups.map(
|
|
79
|
+
(group) => Object.fromEntries(Object.entries(group).map(([k, v]) => [k, [...v]]))
|
|
80
|
+
)
|
|
81
|
+
])
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
});
|
|
11
85
|
function cn(...inputs) {
|
|
12
86
|
return twMerge(clsx(inputs));
|
|
13
87
|
}
|
|
@@ -16,7 +90,7 @@ var POSITION_CLASSES = {
|
|
|
16
90
|
bottom: "bottom-0 translate-y-full mt-2",
|
|
17
91
|
center: "top-1/2 -translate-y-1/2"
|
|
18
92
|
};
|
|
19
|
-
var DwellHint =
|
|
93
|
+
var DwellHint = React2.forwardRef(
|
|
20
94
|
({ show, message, icon, position = "bottom", className, ...props }, ref) => {
|
|
21
95
|
const shouldReduceMotion = useReducedMotion();
|
|
22
96
|
const resolvedPosition = position ?? "bottom";
|
|
@@ -48,7 +122,7 @@ var DwellHint = React.forwardRef(
|
|
|
48
122
|
"flex items-center gap-2 px-4 py-2.5",
|
|
49
123
|
"bg-background/95 backdrop-blur-md",
|
|
50
124
|
"border border-border/50 rounded-[var(--radius-lg)]",
|
|
51
|
-
"shadow-lg shadow-
|
|
125
|
+
"shadow-lg shadow-foreground/5",
|
|
52
126
|
"text-sm text-muted-foreground"
|
|
53
127
|
),
|
|
54
128
|
children: [
|
|
@@ -97,6 +171,47 @@ function useMediaQuery(query) {
|
|
|
97
171
|
return useMediaQuery$1(query, { initializeWithValue: false });
|
|
98
172
|
}
|
|
99
173
|
|
|
174
|
+
// src/tokens/components/interaction.ts
|
|
175
|
+
var interaction = {
|
|
176
|
+
/**
|
|
177
|
+
* Pending states. A spinner that flashes for 80ms reads as a glitch; one
|
|
178
|
+
* that appears and vanishes in 200ms reads as jank. Show only after the
|
|
179
|
+
* wait is noticeable, then keep it long enough to be read.
|
|
180
|
+
* Vercel Web Interface Guidelines: show-delay ~150–300ms, minimum visible
|
|
181
|
+
* ~300–500ms.
|
|
182
|
+
*/
|
|
183
|
+
pending: { showDelayMs: 200, minVisibleMs: 400 }};
|
|
184
|
+
|
|
185
|
+
// src/hooks/use-pending-visible.ts
|
|
186
|
+
function usePendingVisible(pending, {
|
|
187
|
+
showDelayMs = interaction.pending.showDelayMs,
|
|
188
|
+
minVisibleMs = interaction.pending.minVisibleMs
|
|
189
|
+
} = {}) {
|
|
190
|
+
const [visible, setVisible] = React2.useState(false);
|
|
191
|
+
const shownAt = React2.useRef(null);
|
|
192
|
+
React2.useEffect(() => {
|
|
193
|
+
if (pending) {
|
|
194
|
+
if (visible) return;
|
|
195
|
+
const timer2 = setTimeout(() => {
|
|
196
|
+
shownAt.current = Date.now();
|
|
197
|
+
setVisible(true);
|
|
198
|
+
}, showDelayMs);
|
|
199
|
+
return () => clearTimeout(timer2);
|
|
200
|
+
}
|
|
201
|
+
if (!visible) return;
|
|
202
|
+
const elapsed = Date.now() - (shownAt.current ?? 0);
|
|
203
|
+
const timer = setTimeout(
|
|
204
|
+
() => {
|
|
205
|
+
shownAt.current = null;
|
|
206
|
+
setVisible(false);
|
|
207
|
+
},
|
|
208
|
+
Math.max(0, minVisibleMs - elapsed)
|
|
209
|
+
);
|
|
210
|
+
return () => clearTimeout(timer);
|
|
211
|
+
}, [pending, visible, showDelayMs, minVisibleMs]);
|
|
212
|
+
return visible;
|
|
213
|
+
}
|
|
214
|
+
|
|
100
215
|
// src/hooks/use-reduced-motion.ts
|
|
101
216
|
function useReducedMotion2() {
|
|
102
217
|
return useReducedMotion() ?? false;
|
|
@@ -199,6 +314,6 @@ function useScrollDwell(ref, config = {}) {
|
|
|
199
314
|
};
|
|
200
315
|
}
|
|
201
316
|
|
|
202
|
-
export { DwellHint, useDebouncedRefresh, useDebouncedValue, useMediaQuery, useReducedMotion2 as useReducedMotion, useScrollDwell };
|
|
317
|
+
export { DwellHint, useDebouncedRefresh, useDebouncedValue, useMediaQuery, usePendingVisible, useReducedMotion2 as useReducedMotion, useScrollDwell };
|
|
203
318
|
//# sourceMappingURL=index.js.map
|
|
204
319
|
//# sourceMappingURL=index.js.map
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/cn.ts","../../src/hooks/DwellHint.tsx","../../src/hooks/use-debounced-refresh.ts","../../src/hooks/use-media-query.ts","../../src/hooks/use-reduced-motion.ts","../../src/hooks/useScrollDwell.ts"],"names":["useMediaQueryBase","useReducedMotion","useRef","useCallback","useEffect"],"mappings":";;;;;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACsCA,IAAM,gBAAA,GAAsD;AAAA,EAC1D,GAAA,EAAK,8BAAA;AAAA,EACL,MAAA,EAAQ,gCAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAA;AAEO,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA;AAAA,EAC7B,CAAC,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,QAAA,GAAW,QAAA,EAAU,SAAA,EAAW,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC1E,IAAA,MAAM,qBAAqB,gBAAA,EAAiB;AAG5C,IAAA,MAAM,mBAAsC,QAAA,IAAY,QAAA;AAExD,IAAA,uBACE,GAAA,CAAC,eAAA,EAAA,EAAgB,OAAA,EAAS,CAAC,oBACxB,QAAA,EAAA,IAAA,oBACC,GAAA;AAAA,MAAC,MAAA,CAAO,GAAA;AAAA,MAAP;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,yCAAA;AAAA,UACA,iBAAiB,gBAAgB,CAAA;AAAA,UACjC;AAAA,SACF;AAAA,QACA,OAAA,EACE,kBAAA,GACI,EAAE,OAAA,EAAS,GAAE,GACb;AAAA,UACE,OAAA,EAAS,CAAA;AAAA,UACT,CAAA,EAAG,gBAAA,KAAqB,KAAA,GAAQ,GAAA,GAAM,EAAA;AAAA,UACtC,KAAA,EAAO;AAAA,SACT;AAAA,QAEN,OAAA,EAAS,kBAAA,GAAqB,EAAE,OAAA,EAAS,CAAA,EAAE,GAAI,EAAE,OAAA,EAAS,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,CAAA,EAAE;AAAA,QAC5E,IAAA,EACE,kBAAA,GACI,EAAE,OAAA,EAAS,GAAE,GACb,EAAE,OAAA,EAAS,CAAA,EAAG,GAAG,gBAAA,KAAqB,KAAA,GAAQ,EAAA,GAAK,CAAA,EAAG,OAAO,IAAA,EAAK;AAAA,QAExE,UAAA,EACE,kBAAA,GACI,EAAE,QAAA,EAAU,GAAE,GACd;AAAA,UACE,QAAA,EAAU,GAAA;AAAA,UACV,IAAA,EAAM,CAAC,IAAA,EAAM,IAAA,EAAM,MAAM,CAAC;AAAA,SAC5B;AAAA,QAEL,GAAG,KAAA;AAAA,QAEJ,QAAA,kBAAA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,qCAAA;AAAA,cACA,mCAAA;AAAA,cACA,oDAAA;AAAA,cACA,0BAAA;AAAA,cACA;AAAA,aACF;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,8BAC1D,GAAA,CAAC,UAAM,QAAA,EAAA,OAAA,EAAQ;AAAA;AAAA;AAAA;AACjB;AAAA,KACF,EAEJ,CAAA;AAAA,EAEJ;AACF;AAEA,SAAA,CAAU,WAAA,GAAc,WAAA;ACvEjB,SAAS,mBAAA,CAAoB,QAAA,EAAsB,KAAA,GAAQ,GAAA,EAA6B;AAC7F,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AAGnC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EACxB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAGb,EAAA,MAAM,SAAA,GAAY,mBAAA;AAAA,IAChB,MAAM;AACJ,MAAA,WAAA,CAAY,OAAA,EAAQ;AAAA,IACtB,CAAA;AAAA,IACA,KAAA;AAAA,IACA,EAAE,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,IAAA;AAAK,GACnC;AAEA,EAAA,MAAM,QAAA,GAAW,YAAY,MAAM;AACjC,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,MAAA,GAAS,YAAY,MAAM;AAC/B,IAAA,SAAA,CAAU,MAAA,EAAO;AAAA,EACnB,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,SAAA,GAAY,YAAY,MAAM;AAClC,IAAA,OAAO,UAAU,SAAA,EAAU;AAAA,EAC7B,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,SAAA,CAAU,KAAA,EAAM;AAAA,EAClB,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAGd,EAAA,SAAA,CAAU,MAAM,MAAA,EAAQ,CAAC,MAAM,CAAC,CAAA;AAEhC,EAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAM;AAC9C;AAsBO,SAAS,iBAAA,CAAqB,KAAA,EAAU,KAAA,GAAQ,GAAA,EAAQ;AAC7D,EAAA,MAAM,CAAC,cAAc,CAAA,GAAI,gBAAA,CAAiB,OAAO,KAAK,CAAA;AACtD,EAAA,OAAO,cAAA;AACT;ACtFO,SAAS,cAAc,KAAA,EAAwB;AACpD,EAAA,OAAOA,eAAA,CAAkB,KAAA,EAAO,EAAE,mBAAA,EAAqB,OAAO,CAAA;AAChE;;;ACFO,SAASC,iBAAAA,GAA4B;AAC1C,EAAA,OAAO,kBAAuB,IAAK,KAAA;AACrC;ACqCO,SAAS,cAAA,CACd,GAAA,EACA,MAAA,GAAsB,EAAC,EACX;AACZ,EAAA,MAAM,EAAE,YAAY,GAAA,EAAK,QAAA,GAAW,KAAM,OAAA,EAAS,cAAA,GAAiB,MAAK,GAAI,MAAA;AAE7E,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,CAAC,CAAA;AACpD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AAEtD,EAAA,MAAM,aAAA,GAAgBC,OAA8B,IAAI,CAAA;AACxD,EAAA,MAAM,mBAAA,GAAsBA,OAA8B,IAAI,CAAA;AAC9D,EAAA,MAAM,gBAAA,GAAmBA,OAA8B,IAAI,CAAA;AAC3D,EAAA,MAAM,iBAAA,GAAoBA,MAAAA,CAAe,IAAA,CAAK,GAAA,EAAK,CAAA;AACnD,EAAA,MAAM,eAAA,GAAkBA,OAAO,KAAK,CAAA;AAEpC,EAAA,MAAM,WAAA,GAAcC,YAAY,MAAM;AACpC,IAAA,IAAI,cAAc,OAAA,EAAS;AACzB,MAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,MAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AAAA,IAC1B;AACA,IAAA,IAAI,oBAAoB,OAAA,EAAS;AAC/B,MAAA,aAAA,CAAc,oBAAoB,OAAO,CAAA;AACzC,MAAA,mBAAA,CAAoB,OAAA,GAAU,IAAA;AAAA,IAChC;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQA,YAAY,MAAM;AAC9B,IAAA,eAAA,CAAgB,KAAK,CAAA;AACrB,IAAA,aAAA,CAAc,KAAK,CAAA;AACnB,IAAA,gBAAA,CAAiB,CAAC,CAAA;AAClB,IAAA,eAAA,CAAgB,OAAA,GAAU,KAAA;AAC1B,IAAA,IAAI,iBAAiB,OAAA,EAAS;AAC5B,MAAA,YAAA,CAAa,iBAAiB,OAAO,CAAA;AACrC,MAAA,gBAAA,CAAiB,OAAA,GAAU,IAAA;AAAA,IAC7B;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,gBAAA,GAAmBA,YAAY,MAAM;AACzC,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,EAAS,OAAO,KAAA;AACzB,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,CAAQ,qBAAA,EAAsB;AAC/C,IAAA,MAAM,eAAe,MAAA,CAAO,WAAA;AAG5B,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,YAAY,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,EAAK,CAAC,CAAA;AAChF,IAAA,MAAM,gBAAgB,IAAA,CAAK,MAAA;AAE3B,IAAA,OAAO,gBAAgB,aAAA,GAAgB,GAAA;AAAA,EACzC,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,MAAM,eAAA,GAAkBA,YAAY,MAAM;AACxC,IAAA,IAAI,eAAA,CAAgB,WAAW,YAAA,EAAc;AAC7C,IAAA,IAAI,cAAA,IAAkB,CAAC,gBAAA,EAAiB,EAAG;AAE3C,IAAA,WAAA,EAAY;AAGZ,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,mBAAA,CAAoB,OAAA,GAAU,YAAY,MAAM;AAC9C,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAC7B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,OAAA,GAAU,WAAW,CAAC,CAAA;AAChD,MAAA,gBAAA,CAAiB,QAAQ,CAAA;AAEzB,MAAA,IAAI,YAAY,CAAA,EAAG;AACjB,QAAA,IAAI,mBAAA,CAAoB,OAAA,EAAS,aAAA,CAAc,mBAAA,CAAoB,OAAO,CAAA;AAAA,MAC5E;AAAA,IACF,GAAG,EAAE,CAAA;AAGL,IAAA,aAAA,CAAc,OAAA,GAAU,WAAW,MAAM;AACvC,MAAA,aAAA,CAAc,IAAI,CAAA;AAClB,MAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,MAAA,OAAA,IAAU;AAGV,MAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAC1B,MAAA,gBAAA,CAAiB,OAAA,GAAU,WAAW,MAAM;AAC1C,QAAA,eAAA,CAAgB,OAAA,GAAU,KAAA;AAC1B,QAAA,eAAA,CAAgB,KAAK,CAAA;AACrB,QAAA,gBAAA,CAAiB,CAAC,CAAA;AAAA,MACpB,GAAG,QAAQ,CAAA;AAAA,IACb,GAAG,SAAS,CAAA;AAAA,EACd,CAAA,EAAG,CAAC,SAAA,EAAW,QAAA,EAAU,SAAS,cAAA,EAAgB,YAAA,EAAc,gBAAA,EAAkB,WAAW,CAAC,CAAA;AAE9F,EAAA,MAAM,YAAA,GAAeA,YAAY,MAAM;AACrC,IAAA,iBAAA,CAAkB,OAAA,GAAU,KAAK,GAAA,EAAI;AACrC,IAAA,aAAA,CAAc,KAAK,CAAA;AACnB,IAAA,gBAAA,CAAiB,CAAC,CAAA;AAClB,IAAA,WAAA,EAAY;AAGZ,IAAA,UAAA,CAAW,MAAM;AACf,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,EAAI,GAAI,iBAAA,CAAkB,OAAA;AACvD,MAAA,IAAI,mBAAmB,GAAA,EAAK;AAC1B,QAAA,eAAA,EAAgB;AAAA,MAClB;AAAA,IACF,GAAG,GAAG,CAAA;AAAA,EACR,CAAA,EAAG,CAAC,WAAA,EAAa,eAAe,CAAC,CAAA;AAEjC,EAAAC,UAAU,MAAM;AACd,IAAA,MAAA,CAAO,iBAAiB,QAAA,EAAU,YAAA,EAAc,EAAE,OAAA,EAAS,MAAM,CAAA;AAGjE,IAAA,IAAI,cAAA,IAAkB,kBAAiB,EAAG;AACxC,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA,MAAA,IAAW,CAAC,cAAA,EAAgB;AAC1B,MAAA,eAAA,EAAgB;AAAA,IAClB;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,YAAY,CAAA;AACjD,MAAA,WAAA,EAAY;AACZ,MAAA,IAAI,iBAAiB,OAAA,EAAS;AAC5B,QAAA,YAAA,CAAa,iBAAiB,OAAO,CAAA;AAAA,MACvC;AAAA,IACF,CAAA;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,iBAAiB,cAAA,EAAgB,gBAAA,EAAkB,WAAW,CAAC,CAAA;AAEjF,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF","file":"index.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n AnimatePresence,\n type HTMLMotionProps,\n motion,\n useReducedMotion,\n} from \"../shared/animation/motion\";\nimport { cn } from \"../utils/cn\";\n\nexport type DwellHintPosition = \"top\" | \"bottom\" | \"center\";\n\nexport interface DwellHintProps\n extends Omit<\n HTMLMotionProps<\"div\">,\n \"children\" | \"initial\" | \"animate\" | \"exit\" | \"transition\" | \"position\"\n > {\n /** Whether the hint is visible */\n show: boolean;\n /** The hint message to display */\n message: string;\n /** Optional icon to display before the message */\n icon?: React.ReactNode;\n /** Position of the hint relative to content (default: \"bottom\") */\n position?: DwellHintPosition;\n}\n\n/**\n * DwellHint - A contextual hint that appears when user dwells on content.\n *\n * Use with useScrollDwell hook to show helpful messages when users\n * pause scrolling and appear to be reading content.\n *\n * @example\n * const { hasTriggered } = useScrollDwell(sectionRef, { threshold: 1000 });\n *\n * <DwellHint\n * show={hasTriggered}\n * message=\"This is why production-ready matters.\"\n * icon={<Lightbulb className=\"w-4 h-4\" />}\n * />\n */\nconst POSITION_CLASSES: Record<DwellHintPosition, string> = {\n top: \"top-0 -translate-y-full mb-2\",\n bottom: \"bottom-0 translate-y-full mt-2\",\n center: \"top-1/2 -translate-y-1/2\",\n};\n\nexport const DwellHint = React.forwardRef<HTMLDivElement, DwellHintProps>(\n ({ show, message, icon, position = \"bottom\", className, ...props }, ref) => {\n const shouldReduceMotion = useReducedMotion();\n // Narrow after destructure: HTMLMotionProps intersections can widen\n // `position` to `any` under tsup DTS emit, which then fails TS7053.\n const resolvedPosition: DwellHintPosition = position ?? \"bottom\";\n\n return (\n <AnimatePresence initial={!shouldReduceMotion}>\n {show && (\n <motion.div\n ref={ref}\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 z-10\",\n POSITION_CLASSES[resolvedPosition],\n className,\n )}\n initial={\n shouldReduceMotion\n ? { opacity: 1 }\n : {\n opacity: 0,\n y: resolvedPosition === \"top\" ? -10 : 10,\n scale: 0.95,\n }\n }\n animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0, scale: 1 }}\n exit={\n shouldReduceMotion\n ? { opacity: 0 }\n : { opacity: 0, y: resolvedPosition === \"top\" ? -5 : 5, scale: 0.98 }\n }\n transition={\n shouldReduceMotion\n ? { duration: 0 }\n : {\n duration: 0.4,\n ease: [0.34, 1.56, 0.64, 1],\n }\n }\n {...props}\n >\n <div\n className={cn(\n \"flex items-center gap-2 px-4 py-2.5\",\n \"bg-background/95 backdrop-blur-md\",\n \"border border-border/50 rounded-[var(--radius-lg)]\",\n \"shadow-lg shadow-black/5\",\n \"text-sm text-muted-foreground\",\n )}\n >\n {icon && <span className=\"text-primary/70 shrink-0\">{icon}</span>}\n <span>{message}</span>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n );\n },\n);\n\nDwellHint.displayName = \"DwellHint\";\n","/**\n * Debounced Refresh Hook\n *\n * Wraps usehooks-ts (already a workspace dependency) so the rest of the\n * monorepo gets a single canonical debounced hook surface:\n * - cancellable\n * - configurable delay\n * - leading / trailing modes\n */\n\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useDebounceCallback, useDebounceValue } from \"usehooks-ts\";\n\ntype DebouncedRefreshResult = {\n schedule: () => void;\n cancel: () => void;\n isPending: () => boolean;\n flush: () => void;\n};\n\n/**\n * 防抖刷新 Hook\n *\n * 用于限制频繁触发的刷新操作\n *\n * @param callback - 要执行的回调函数\n * @param delay - 延迟时间 (毫秒)\n * @returns 控制对象 { schedule, cancel, isPending, flush }\n *\n * @example\n * const { schedule, cancel } = useDebouncedRefresh(() => {\n * refetch();\n * }, 400);\n *\n * // 在数据变化时调用\n * useEffect(() => {\n * schedule();\n * }, [data]);\n */\nexport function useDebouncedRefresh(callback: () => void, delay = 400): DebouncedRefreshResult {\n const callbackRef = useRef(callback);\n\n // 保持回调引用最新\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n // 使用 usehooks-ts 的 useDebounceCallback\n const debounced = useDebounceCallback(\n () => {\n callbackRef.current();\n },\n delay,\n { leading: false, trailing: true },\n );\n\n const schedule = useCallback(() => {\n debounced();\n }, [debounced]);\n\n const cancel = useCallback(() => {\n debounced.cancel();\n }, [debounced]);\n\n const isPending = useCallback(() => {\n return debounced.isPending();\n }, [debounced]);\n\n const flush = useCallback(() => {\n debounced.flush();\n }, [debounced]);\n\n // 组件卸载时取消\n useEffect(() => cancel, [cancel]);\n\n return { schedule, cancel, isPending, flush };\n}\n\n/**\n * 防抖值 Hook\n *\n * Thin wrapper over usehooks-ts useDebounceValue so consumers can import\n * the canonical hook from @nebutra/ui/hooks alongside useDebouncedRefresh.\n *\n * @param value - 要防抖的值\n * @param delay - 延迟时间 (毫秒)\n * @returns 防抖后的值\n *\n * @example\n * const [searchTerm, setSearchTerm] = useState(\"\");\n * const debouncedSearch = useDebouncedValue(searchTerm, 300);\n *\n * useEffect(() => {\n * if (debouncedSearch) {\n * performSearch(debouncedSearch);\n * }\n * }, [debouncedSearch]);\n */\nexport function useDebouncedValue<T>(value: T, delay = 500): T {\n const [debouncedValue] = useDebounceValue(value, delay);\n return debouncedValue;\n}\n","import { useMediaQuery as useMediaQueryBase } from \"usehooks-ts\";\n\n/**\n * Hook to detect media query matches.\n *\n * Delegates to usehooks-ts `useMediaQuery` with `initializeWithValue: false`\n * so the initial render always returns `false` — SSR-safe, matching the\n * previous hand-rolled behaviour (no `window` access during SSR/hydration).\n *\n * @example\n * ```tsx\n * const isMobile = useMediaQuery(\"(max-width: 768px)\");\n * const prefersDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n * ```\n */\nexport function useMediaQuery(query: string): boolean {\n return useMediaQueryBase(query, { initializeWithValue: false });\n}\n","\"use client\";\n\nimport { useReducedMotion as useSharedReducedMotion } from \"../shared/animation/motion\";\n\n/**\n * Returns true if the user has enabled prefers-reduced-motion.\n * Use this to disable animations, skip transitions, or simplify motion.\n *\n * Wraps framer-motion's `useReducedMotion` so callers don't need framer-motion\n * as a direct import just for accessibility checks.\n *\n * @example\n * const shouldReduce = useReducedMotion();\n * const transition = shouldReduce ? { duration: 0 } : brandSpring.default;\n */\nexport function useReducedMotion(): boolean {\n return useSharedReducedMotion() ?? false;\n}\n","\"use client\";\n\nimport { type RefObject, useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface DwellConfig {\n /** Time in ms before dwell is triggered (default: 800) */\n threshold?: number;\n /** Cooldown in ms between triggers (default: 5000) */\n cooldown?: number;\n /** Callback when dwell is detected */\n onDwell?: () => void;\n /** Only trigger when element is in viewport (default: true) */\n requireVisible?: boolean;\n}\n\nexport interface DwellState {\n /** Whether the user is currently dwelling */\n isDwelling: boolean;\n /** Progress toward trigger threshold (0-1) */\n dwellProgress: number;\n /** Whether dwell was triggered (resets after cooldown) */\n hasTriggered: boolean;\n /** Manually reset the triggered state */\n reset: () => void;\n}\n\n/**\n * useScrollDwell - Detects when a user pauses scrolling over an element.\n *\n * This hook monitors scroll activity and detects \"dwell\" behavior where\n * the user stops scrolling for a specified duration. Useful for showing\n * contextual hints, tooltips, or triggering animations when a user\n * appears to be reading or studying content.\n *\n * @param ref - Reference to the element to monitor\n * @param config - Configuration options\n * @returns DwellState object with current dwell status\n *\n * @example\n * function FeatureSection() {\n * const sectionRef = useRef<HTMLDivElement>(null);\n * const { isDwelling, hasTriggered } = useScrollDwell(sectionRef, {\n * threshold: 1000,\n * cooldown: 10000,\n * onDwell: () => console.log(\"User is reading this section\"),\n * });\n *\n * return (\n * <div ref={sectionRef}>\n * {hasTriggered && <DwellHint message=\"Take a closer look!\" />}\n * </div>\n * );\n * }\n */\nexport function useScrollDwell(\n ref: RefObject<HTMLElement | null>,\n config: DwellConfig = {},\n): DwellState {\n const { threshold = 800, cooldown = 5000, onDwell, requireVisible = true } = config;\n\n const [isDwelling, setIsDwelling] = useState(false);\n const [dwellProgress, setDwellProgress] = useState(0);\n const [hasTriggered, setHasTriggered] = useState(false);\n\n const dwellTimerRef = useRef<NodeJS.Timeout | null>(null);\n const progressIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const cooldownTimerRef = useRef<NodeJS.Timeout | null>(null);\n const lastScrollTimeRef = useRef<number>(Date.now());\n const isInCooldownRef = useRef(false);\n\n const clearTimers = useCallback(() => {\n if (dwellTimerRef.current) {\n clearTimeout(dwellTimerRef.current);\n dwellTimerRef.current = null;\n }\n if (progressIntervalRef.current) {\n clearInterval(progressIntervalRef.current);\n progressIntervalRef.current = null;\n }\n }, []);\n\n const reset = useCallback(() => {\n setHasTriggered(false);\n setIsDwelling(false);\n setDwellProgress(0);\n isInCooldownRef.current = false;\n if (cooldownTimerRef.current) {\n clearTimeout(cooldownTimerRef.current);\n cooldownTimerRef.current = null;\n }\n }, []);\n\n const isElementVisible = useCallback(() => {\n if (!ref.current) return false;\n const rect = ref.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Element is visible if at least 50% is in viewport\n const visibleHeight = Math.min(rect.bottom, windowHeight) - Math.max(rect.top, 0);\n const elementHeight = rect.height;\n\n return visibleHeight / elementHeight > 0.5;\n }, [ref]);\n\n const startDwellTimer = useCallback(() => {\n if (isInCooldownRef.current || hasTriggered) return;\n if (requireVisible && !isElementVisible()) return;\n\n clearTimers();\n\n // Start progress tracking\n const startTime = Date.now();\n progressIntervalRef.current = setInterval(() => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / threshold, 1);\n setDwellProgress(progress);\n\n if (progress >= 1) {\n if (progressIntervalRef.current) clearInterval(progressIntervalRef.current);\n }\n }, 50);\n\n // Set up dwell trigger\n dwellTimerRef.current = setTimeout(() => {\n setIsDwelling(true);\n setHasTriggered(true);\n onDwell?.();\n\n // Start cooldown\n isInCooldownRef.current = true;\n cooldownTimerRef.current = setTimeout(() => {\n isInCooldownRef.current = false;\n setHasTriggered(false);\n setDwellProgress(0);\n }, cooldown);\n }, threshold);\n }, [threshold, cooldown, onDwell, requireVisible, hasTriggered, isElementVisible, clearTimers]);\n\n const handleScroll = useCallback(() => {\n lastScrollTimeRef.current = Date.now();\n setIsDwelling(false);\n setDwellProgress(0);\n clearTimers();\n\n // Restart dwell detection after a short delay\n setTimeout(() => {\n const timeSinceScroll = Date.now() - lastScrollTimeRef.current;\n if (timeSinceScroll >= 100) {\n startDwellTimer();\n }\n }, 100);\n }, [clearTimers, startDwellTimer]);\n\n useEffect(() => {\n window.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n // Start initial dwell timer if element is already visible\n if (requireVisible && isElementVisible()) {\n startDwellTimer();\n } else if (!requireVisible) {\n startDwellTimer();\n }\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll);\n clearTimers();\n if (cooldownTimerRef.current) {\n clearTimeout(cooldownTimerRef.current);\n }\n };\n }, [handleScroll, startDwellTimer, requireVisible, isElementVisible, clearTimers]);\n\n return {\n isDwelling,\n dwellProgress,\n hasTriggered,\n reset,\n };\n}\n\nexport default useScrollDwell;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/tw-merge-theme.generated.ts","../../src/utils/cn.ts","../../src/hooks/DwellHint.tsx","../../src/hooks/use-debounced-refresh.ts","../../src/hooks/use-media-query.ts","../../src/tokens/components/interaction.ts","../../src/hooks/use-pending-visible.ts","../../src/hooks/use-reduced-motion.ts","../../src/hooks/useScrollDwell.ts"],"names":["React","useMediaQueryBase","timer","useReducedMotion","useState","useRef","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["// GENERATED by packages/design/ui/scripts/gen-tw-merge-theme.mjs — do not edit.\n// Source: the @theme blocks in packages/design/tokens/{styles,recipe}.css.\n\nexport const TW_MERGE_THEME = {\n breakpoint: [\"3xl\", \"shell\", \"tight\", \"xs\"],\n container: [\"content\", \"text\", \"wide\"],\n ease: [\"brand\", \"in\", \"in-out\", \"out\", \"spring\"],\n font: [\"cn\", \"display\", \"heading\", \"mono\", \"sans\"],\n leading: [\"display\", \"heading\"],\n radius: [\"2xl\", \"3xl\", \"button\", \"card\", \"full\", \"lg\", \"md\", \"none\", \"panel\", \"sm\", \"xl\", \"xs\"],\n shadow: [\n \"2xl\",\n \"ambient-glow\",\n \"ambient-lg\",\n \"ambient-md\",\n \"ambient-sm\",\n \"brand\",\n \"brand-lg\",\n \"glass-lg\",\n \"glass-md\",\n \"glass-sm\",\n \"glow-accent\",\n \"glow-accent-lg\",\n \"glow-accent-sm\",\n \"glow-primary\",\n \"lg\",\n \"md\",\n \"sheen\",\n \"sm\",\n \"xl\",\n \"xs\",\n ],\n text: [\n \"2xl\",\n \"2xs\",\n \"3xl\",\n \"4xl\",\n \"5xl\",\n \"6xl\",\n \"7xl\",\n \"8xl\",\n \"9xl\",\n \"base\",\n \"body\",\n \"display\",\n \"label\",\n \"lg\",\n \"meta\",\n \"sm\",\n \"ui\",\n \"xl\",\n \"xs\",\n ],\n tracking: [\"display\", \"heading\", \"label\", \"tight\"],\n} as const;\n\nexport const TW_MERGE_CLASS_GROUPS = {\n duration: [{ duration: [\"cinematic\", \"flow\", \"micro\", \"reveal\"] }],\n} as const;\n","import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\nimport { TW_MERGE_CLASS_GROUPS, TW_MERGE_THEME } from \"./tw-merge-theme.generated\";\n\n/**\n * tailwind-merge only knows Tailwind's default scale. Every utility the design\n * tokens add (text-label, shadow-ambient-md, rounded-card, ease-brand,\n * max-w-wide, …) was otherwise an unknown class: `cn(\"text-label\n * text-destructive-strong\")` returned \"text-destructive-strong\" and the size fell away, and\n * `cn(\"rounded-card\", \"rounded-lg\")` kept both so the winner depended on\n * stylesheet order. The theme below is generated from the tokens' @theme blocks\n * (scripts/gen-tw-merge-theme.mjs), so a new token utility is known here the\n * moment it exists; a test fails if the generated file goes stale.\n */\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: Object.fromEntries(\n Object.entries(TW_MERGE_THEME).map(([key, values]) => [key, [...values]]),\n ),\n classGroups: Object.fromEntries(\n Object.entries(TW_MERGE_CLASS_GROUPS).map(([key, groups]) => [\n key,\n groups.map((group) =>\n Object.fromEntries(Object.entries(group).map(([k, v]) => [k, [...v]])),\n ),\n ]),\n ),\n },\n});\n\n/** Kept for callers and tests that enumerate the design-system text steps. */\nexport const DESIGN_SYSTEM_TEXT_SIZES = TW_MERGE_THEME.text;\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n AnimatePresence,\n type HTMLMotionProps,\n motion,\n useReducedMotion,\n} from \"../shared/animation/motion\";\nimport { cn } from \"../utils/cn\";\n\nexport type DwellHintPosition = \"top\" | \"bottom\" | \"center\";\n\nexport interface DwellHintProps\n extends Omit<\n HTMLMotionProps<\"div\">,\n \"children\" | \"initial\" | \"animate\" | \"exit\" | \"transition\" | \"position\"\n > {\n /** Whether the hint is visible */\n show: boolean;\n /** The hint message to display */\n message: string;\n /** Optional icon to display before the message */\n icon?: React.ReactNode;\n /** Position of the hint relative to content (default: \"bottom\") */\n position?: DwellHintPosition;\n}\n\n/**\n * DwellHint - A contextual hint that appears when user dwells on content.\n *\n * Use with useScrollDwell hook to show helpful messages when users\n * pause scrolling and appear to be reading content.\n *\n * @example\n * const { hasTriggered } = useScrollDwell(sectionRef, { threshold: 1000 });\n *\n * <DwellHint\n * show={hasTriggered}\n * message=\"This is why production-ready matters.\"\n * icon={<Lightbulb className=\"w-4 h-4\" />}\n * />\n */\nconst POSITION_CLASSES: Record<DwellHintPosition, string> = {\n top: \"top-0 -translate-y-full mb-2\",\n bottom: \"bottom-0 translate-y-full mt-2\",\n center: \"top-1/2 -translate-y-1/2\",\n};\n\nexport const DwellHint = React.forwardRef<HTMLDivElement, DwellHintProps>(\n ({ show, message, icon, position = \"bottom\", className, ...props }, ref) => {\n const shouldReduceMotion = useReducedMotion();\n // Narrow after destructure: HTMLMotionProps intersections can widen\n // `position` to `any` under tsup DTS emit, which then fails TS7053.\n const resolvedPosition: DwellHintPosition = position ?? \"bottom\";\n\n return (\n <AnimatePresence initial={!shouldReduceMotion}>\n {show && (\n <motion.div\n ref={ref}\n className={cn(\n \"absolute left-1/2 -translate-x-1/2 z-10\",\n POSITION_CLASSES[resolvedPosition],\n className,\n )}\n initial={\n shouldReduceMotion\n ? { opacity: 1 }\n : {\n opacity: 0,\n y: resolvedPosition === \"top\" ? -10 : 10,\n scale: 0.95,\n }\n }\n animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0, scale: 1 }}\n exit={\n shouldReduceMotion\n ? { opacity: 0 }\n : { opacity: 0, y: resolvedPosition === \"top\" ? -5 : 5, scale: 0.98 }\n }\n transition={\n shouldReduceMotion\n ? { duration: 0 }\n : {\n duration: 0.4,\n ease: [0.34, 1.56, 0.64, 1],\n }\n }\n {...props}\n >\n <div\n className={cn(\n \"flex items-center gap-2 px-4 py-2.5\",\n \"bg-background/95 backdrop-blur-md\",\n \"border border-border/50 rounded-[var(--radius-lg)]\",\n \"shadow-lg shadow-foreground/5\",\n \"text-sm text-muted-foreground\",\n )}\n >\n {icon && <span className=\"text-primary/70 shrink-0\">{icon}</span>}\n <span>{message}</span>\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n );\n },\n);\n\nDwellHint.displayName = \"DwellHint\";\n","/**\n * Debounced Refresh Hook\n *\n * Wraps usehooks-ts (already a workspace dependency) so the rest of the\n * monorepo gets a single canonical debounced hook surface:\n * - cancellable\n * - configurable delay\n * - leading / trailing modes\n */\n\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useDebounceCallback, useDebounceValue } from \"usehooks-ts\";\n\ntype DebouncedRefreshResult = {\n schedule: () => void;\n cancel: () => void;\n isPending: () => boolean;\n flush: () => void;\n};\n\n/**\n * 防抖刷新 Hook\n *\n * 用于限制频繁触发的刷新操作\n *\n * @param callback - 要执行的回调函数\n * @param delay - 延迟时间 (毫秒)\n * @returns 控制对象 { schedule, cancel, isPending, flush }\n *\n * @example\n * const { schedule, cancel } = useDebouncedRefresh(() => {\n * refetch();\n * }, 400);\n *\n * // 在数据变化时调用\n * useEffect(() => {\n * schedule();\n * }, [data]);\n */\nexport function useDebouncedRefresh(callback: () => void, delay = 400): DebouncedRefreshResult {\n const callbackRef = useRef(callback);\n\n // 保持回调引用最新\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n // 使用 usehooks-ts 的 useDebounceCallback\n const debounced = useDebounceCallback(\n () => {\n callbackRef.current();\n },\n delay,\n { leading: false, trailing: true },\n );\n\n const schedule = useCallback(() => {\n debounced();\n }, [debounced]);\n\n const cancel = useCallback(() => {\n debounced.cancel();\n }, [debounced]);\n\n const isPending = useCallback(() => {\n return debounced.isPending();\n }, [debounced]);\n\n const flush = useCallback(() => {\n debounced.flush();\n }, [debounced]);\n\n // 组件卸载时取消\n useEffect(() => cancel, [cancel]);\n\n return { schedule, cancel, isPending, flush };\n}\n\n/**\n * 防抖值 Hook\n *\n * Thin wrapper over usehooks-ts useDebounceValue so consumers can import\n * the canonical hook from @nebutra/ui/hooks alongside useDebouncedRefresh.\n *\n * @param value - 要防抖的值\n * @param delay - 延迟时间 (毫秒)\n * @returns 防抖后的值\n *\n * @example\n * const [searchTerm, setSearchTerm] = useState(\"\");\n * const debouncedSearch = useDebouncedValue(searchTerm, 300);\n *\n * useEffect(() => {\n * if (debouncedSearch) {\n * performSearch(debouncedSearch);\n * }\n * }, [debouncedSearch]);\n */\nexport function useDebouncedValue<T>(value: T, delay = 500): T {\n const [debouncedValue] = useDebounceValue(value, delay);\n return debouncedValue;\n}\n","import { useMediaQuery as useMediaQueryBase } from \"usehooks-ts\";\n\n/**\n * Hook to detect media query matches.\n *\n * Delegates to usehooks-ts `useMediaQuery` with `initializeWithValue: false`\n * so the initial render always returns `false` — SSR-safe, matching the\n * previous hand-rolled behaviour (no `window` access during SSR/hydration).\n *\n * @example\n * ```tsx\n * const isMobile = useMediaQuery(\"(max-width: 768px)\");\n * const prefersDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n * ```\n */\nexport function useMediaQuery(query: string): boolean {\n return useMediaQueryBase(query, { initializeWithValue: false });\n}\n","/**\n * Interaction contract — the timing and feel every product surface shares.\n *\n * One place for the numbers that make an interface feel deliberate rather than\n * merely animated. Each value is taken from a shipped, measured source rather\n * than tuned by eye; the source is named beside it so a change has to argue\n * with the evidence. Components read these; apps never restate them.\n *\n * Sources: sonner, vaul and Radix Tooltip source code; Vercel Web Interface\n * Guidelines; Emil Kowalski's animation guidance (author of sonner and vaul).\n */\n\nexport const interaction = {\n /**\n * Tooltips. The first one waits so a sweeping pointer does not strobe;\n * once one is open, its neighbours open instantly if the pointer arrives\n * within the skip window. Radix Tooltip defaults: delayDuration 700,\n * skipDelayDuration 300. Vercel/Kowalski: \"delay the first tooltip only\".\n */\n tooltip: { delayMs: 700, skipWindowMs: 300 },\n\n /**\n * Pending states. A spinner that flashes for 80ms reads as a glitch; one\n * that appears and vanishes in 200ms reads as jank. Show only after the\n * wait is noticeable, then keep it long enough to be read.\n * Vercel Web Interface Guidelines: show-delay ~150–300ms, minimum visible\n * ~300–500ms.\n */\n pending: { showDelayMs: 200, minVisibleMs: 400 },\n\n /**\n * Press feedback. A slight scale-down on :active, fast. Kowalski:\n * scale(0.97) at ~150ms. Never animate keyboard-initiated activation.\n */\n press: { scale: 0.97, durationMs: 150 },\n\n /**\n * Entering overlays start close to their final size, never from zero.\n * Kowalski: \"never enter from scale(0)\"; 0.9–0.95 reads as arrival.\n */\n enter: { fromScale: 0.96 },\n\n /**\n * Enter/exit asymmetry. Things arrive with a considered ease-out and leave\n * faster: the user already decided they are done. sonner: enter 300ms,\n * exit 200ms.\n */\n toast: { enterMs: 300, exitMs: 200, lifetimeMs: 4000, stackGapPx: 14 },\n\n /**\n * Sheets and drawers. vaul uses one curve for every drawer transition:\n * cubic-bezier(0.32, 0.72, 0, 1) over 500ms.\n */\n drawer: { ease: [0.32, 0.72, 0, 1] as const, durationMs: 500 },\n\n /**\n * Mutation latency budget. Past this, show optimistic state or progress.\n * Vercel Web Interface Guidelines: keep mutations under 500ms.\n */\n mutationBudgetMs: 500,\n} as const;\n\nexport type Interaction = typeof interaction;\n","\"use client\";\n\nimport * as React from \"react\";\nimport { interaction } from \"../tokens/components/interaction\";\n\n/**\n * Whether a pending indicator should be on screen right now.\n *\n * A spinner that flashes for 80ms reads as a glitch, and one that appears and\n * disappears inside 200ms reads as jank. So: stay hidden until the wait is\n * noticeable (`showDelayMs`), and once shown, stay long enough to be read\n * (`minVisibleMs`) even if the work finished in between. Defaults come from the\n * interaction contract (Vercel Web Interface Guidelines).\n *\n * const visible = usePendingVisible(isPending);\n * return visible ? <Spinner /> : null;\n */\nexport function usePendingVisible(\n pending: boolean,\n {\n showDelayMs = interaction.pending.showDelayMs,\n minVisibleMs = interaction.pending.minVisibleMs,\n }: { showDelayMs?: number; minVisibleMs?: number } = {},\n): boolean {\n const [visible, setVisible] = React.useState(false);\n const shownAt = React.useRef<number | null>(null);\n\n React.useEffect(() => {\n if (pending) {\n if (visible) return;\n const timer = setTimeout(() => {\n shownAt.current = Date.now();\n setVisible(true);\n }, showDelayMs);\n return () => clearTimeout(timer);\n }\n if (!visible) return;\n const elapsed = Date.now() - (shownAt.current ?? 0);\n const timer = setTimeout(\n () => {\n shownAt.current = null;\n setVisible(false);\n },\n Math.max(0, minVisibleMs - elapsed),\n );\n return () => clearTimeout(timer);\n }, [pending, visible, showDelayMs, minVisibleMs]);\n\n return visible;\n}\n","\"use client\";\n\nimport { useReducedMotion as useSharedReducedMotion } from \"../shared/animation/motion\";\n\n/**\n * Returns true if the user has enabled prefers-reduced-motion.\n * Use this to disable animations, skip transitions, or simplify motion.\n *\n * Wraps framer-motion's `useReducedMotion` so callers don't need framer-motion\n * as a direct import just for accessibility checks.\n *\n * @example\n * const shouldReduce = useReducedMotion();\n * const transition = shouldReduce ? { duration: 0 } : brandSpring.default;\n */\nexport function useReducedMotion(): boolean {\n return useSharedReducedMotion() ?? false;\n}\n","\"use client\";\n\nimport { type RefObject, useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface DwellConfig {\n /** Time in ms before dwell is triggered (default: 800) */\n threshold?: number;\n /** Cooldown in ms between triggers (default: 5000) */\n cooldown?: number;\n /** Callback when dwell is detected */\n onDwell?: () => void;\n /** Only trigger when element is in viewport (default: true) */\n requireVisible?: boolean;\n}\n\nexport interface DwellState {\n /** Whether the user is currently dwelling */\n isDwelling: boolean;\n /** Progress toward trigger threshold (0-1) */\n dwellProgress: number;\n /** Whether dwell was triggered (resets after cooldown) */\n hasTriggered: boolean;\n /** Manually reset the triggered state */\n reset: () => void;\n}\n\n/**\n * useScrollDwell - Detects when a user pauses scrolling over an element.\n *\n * This hook monitors scroll activity and detects \"dwell\" behavior where\n * the user stops scrolling for a specified duration. Useful for showing\n * contextual hints, tooltips, or triggering animations when a user\n * appears to be reading or studying content.\n *\n * @param ref - Reference to the element to monitor\n * @param config - Configuration options\n * @returns DwellState object with current dwell status\n *\n * @example\n * function FeatureSection() {\n * const sectionRef = useRef<HTMLDivElement>(null);\n * const { isDwelling, hasTriggered } = useScrollDwell(sectionRef, {\n * threshold: 1000,\n * cooldown: 10000,\n * onDwell: () => console.log(\"User is reading this section\"),\n * });\n *\n * return (\n * <div ref={sectionRef}>\n * {hasTriggered && <DwellHint message=\"Take a closer look!\" />}\n * </div>\n * );\n * }\n */\nexport function useScrollDwell(\n ref: RefObject<HTMLElement | null>,\n config: DwellConfig = {},\n): DwellState {\n const { threshold = 800, cooldown = 5000, onDwell, requireVisible = true } = config;\n\n const [isDwelling, setIsDwelling] = useState(false);\n const [dwellProgress, setDwellProgress] = useState(0);\n const [hasTriggered, setHasTriggered] = useState(false);\n\n const dwellTimerRef = useRef<NodeJS.Timeout | null>(null);\n const progressIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const cooldownTimerRef = useRef<NodeJS.Timeout | null>(null);\n const lastScrollTimeRef = useRef<number>(Date.now());\n const isInCooldownRef = useRef(false);\n\n const clearTimers = useCallback(() => {\n if (dwellTimerRef.current) {\n clearTimeout(dwellTimerRef.current);\n dwellTimerRef.current = null;\n }\n if (progressIntervalRef.current) {\n clearInterval(progressIntervalRef.current);\n progressIntervalRef.current = null;\n }\n }, []);\n\n const reset = useCallback(() => {\n setHasTriggered(false);\n setIsDwelling(false);\n setDwellProgress(0);\n isInCooldownRef.current = false;\n if (cooldownTimerRef.current) {\n clearTimeout(cooldownTimerRef.current);\n cooldownTimerRef.current = null;\n }\n }, []);\n\n const isElementVisible = useCallback(() => {\n if (!ref.current) return false;\n const rect = ref.current.getBoundingClientRect();\n const windowHeight = window.innerHeight;\n\n // Element is visible if at least 50% is in viewport\n const visibleHeight = Math.min(rect.bottom, windowHeight) - Math.max(rect.top, 0);\n const elementHeight = rect.height;\n\n return visibleHeight / elementHeight > 0.5;\n }, [ref]);\n\n const startDwellTimer = useCallback(() => {\n if (isInCooldownRef.current || hasTriggered) return;\n if (requireVisible && !isElementVisible()) return;\n\n clearTimers();\n\n // Start progress tracking\n const startTime = Date.now();\n progressIntervalRef.current = setInterval(() => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / threshold, 1);\n setDwellProgress(progress);\n\n if (progress >= 1) {\n if (progressIntervalRef.current) clearInterval(progressIntervalRef.current);\n }\n }, 50);\n\n // Set up dwell trigger\n dwellTimerRef.current = setTimeout(() => {\n setIsDwelling(true);\n setHasTriggered(true);\n onDwell?.();\n\n // Start cooldown\n isInCooldownRef.current = true;\n cooldownTimerRef.current = setTimeout(() => {\n isInCooldownRef.current = false;\n setHasTriggered(false);\n setDwellProgress(0);\n }, cooldown);\n }, threshold);\n }, [threshold, cooldown, onDwell, requireVisible, hasTriggered, isElementVisible, clearTimers]);\n\n const handleScroll = useCallback(() => {\n lastScrollTimeRef.current = Date.now();\n setIsDwelling(false);\n setDwellProgress(0);\n clearTimers();\n\n // Restart dwell detection after a short delay\n setTimeout(() => {\n const timeSinceScroll = Date.now() - lastScrollTimeRef.current;\n if (timeSinceScroll >= 100) {\n startDwellTimer();\n }\n }, 100);\n }, [clearTimers, startDwellTimer]);\n\n useEffect(() => {\n window.addEventListener(\"scroll\", handleScroll, { passive: true });\n\n // Start initial dwell timer if element is already visible\n if (requireVisible && isElementVisible()) {\n startDwellTimer();\n } else if (!requireVisible) {\n startDwellTimer();\n }\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll);\n clearTimers();\n if (cooldownTimerRef.current) {\n clearTimeout(cooldownTimerRef.current);\n }\n };\n }, [handleScroll, startDwellTimer, requireVisible, isElementVisible, clearTimers]);\n\n return {\n isDwelling,\n dwellProgress,\n hasTriggered,\n reset,\n };\n}\n\nexport default useScrollDwell;\n"]}
|