@vegastack/design 0.4.1 → 0.6.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.
@@ -0,0 +1,103 @@
1
+ // src/index.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge as tailwindMerge } from "tailwind-merge";
4
+
5
+ // src/prose.ts
6
+ var prose = {
7
+ /** The root's own ink and size — every rule below is relative to this. */
8
+ root: "text-sm text-foreground",
9
+ // Headings. `scroll-m-20` keeps an anchored heading clear of a sticky header; the weight is
10
+ // `font-semibold`, the ordinary Tailwind weight upstream uses — Batch 1 of the shadcn reset
11
+ // deleted both the 400/500 ladder and the `text-h*` roles this comment used to name.
12
+ h1: "[&_h1]:mt-6 [&_h1]:mb-3 [&_h1]:scroll-m-20 [&_h1]:text-3xl [&_h1]:font-semibold [&_h1]:text-foreground [&_h1]:first:mt-0",
13
+ h2: "[&_h2]:mt-6 [&_h2]:mb-3 [&_h2]:scroll-m-20 [&_h2]:text-2xl [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:first:mt-0",
14
+ h3: "[&_h3]:mt-5 [&_h3]:mb-2 [&_h3]:scroll-m-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:text-foreground [&_h3]:first:mt-0",
15
+ h4: "[&_h4]:mt-4 [&_h4]:mb-2 [&_h4]:scroll-m-20 [&_h4]:text-base [&_h4]:font-medium [&_h4]:text-foreground [&_h4]:first:mt-0",
16
+ // h5/h6 leave the display tier and become labels — the type scale has no sixth heading size.
17
+ h5: "[&_h5]:mt-4 [&_h5]:mb-2 [&_h5]:text-sm [&_h5]:font-medium [&_h5]:text-foreground [&_h5]:first:mt-0",
18
+ h6: "[&_h6]:mt-4 [&_h6]:mb-2 [&_h6]:text-sm [&_h6]:font-medium [&_h6]:text-muted-foreground [&_h6]:first:mt-0",
19
+ p: "[&_p]:my-3 [&_p]:leading-relaxed [&_p]:text-foreground [&_p]:first:mt-0 [&_p]:last:mb-0",
20
+ // Marks. Links are `info` ink per design.md §Colours; `s` is Tiptap's strike element and `del`
21
+ // is GFM's — the same mark from two producers.
22
+ a: "[&_a]:font-medium [&_a]:text-info-text [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-info-text/88",
23
+ strong: "[&_strong]:font-medium [&_strong]:text-foreground",
24
+ em: "[&_em]:italic",
25
+ del: "[&_del]:text-muted-foreground [&_del]:line-through [&_s]:text-muted-foreground [&_s]:line-through",
26
+ // Lists. A GFM task list carries `contains-task-list` and its checkbox IS the marker, so the
27
+ // disc goes — expressed as a second, more specific descendant rule rather than a class on the
28
+ // element, which would lose the cascade (see the header).
29
+ ul: "[&_ul]:my-3 [&_ul]:ms-6 [&_ul]:list-disc [&_ul]:text-foreground [&_ul]:marker:text-muted-foreground [&_ul.contains-task-list]:list-none",
30
+ ol: "[&_ol]:my-3 [&_ol]:ms-6 [&_ol]:list-decimal [&_ol]:text-foreground [&_ol]:marker:text-muted-foreground",
31
+ li: "[&_li]:mt-1.5 [&_li]:leading-relaxed",
32
+ blockquote: "[&_blockquote]:my-3 [&_blockquote]:border-s-2 [&_blockquote]:border-border [&_blockquote]:ps-4 [&_blockquote]:text-muted-foreground [&_blockquote]:italic",
33
+ // Inline code is a chip. Code inside a `pre` is not: it inherits the panel's ground, so the chip
34
+ // is undone at higher specificity (`[&_pre_code]` is (0,1,2) against the chip's (0,1,1)).
35
+ code: "[&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-sm [&_code]:text-foreground",
36
+ // A bare `<pre>` wears `CodeBlock`'s surface — the same sunken panel, one vocabulary (B4-09).
37
+ // `CodeBlock`'s own `pre` is excluded: it already sits inside a `figure` carrying the border,
38
+ // radius and ground, and re-applying them here would draw a second panel inside the first.
39
+ pre: "[&_pre:not([data-slot='code-block-pre'])]:my-3 [&_pre:not([data-slot='code-block-pre'])]:overflow-x-auto [&_pre:not([data-slot='code-block-pre'])]:rounded-lg [&_pre:not([data-slot='code-block-pre'])]:border [&_pre:not([data-slot='code-block-pre'])]:border-border [&_pre:not([data-slot='code-block-pre'])]:bg-muted [&_pre:not([data-slot='code-block-pre'])]:p-4 [&_pre:not([data-slot='code-block-pre'])]:text-foreground",
40
+ preCode: "[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:font-mono [&_pre_code]:text-sm [&_pre_code]:text-foreground",
41
+ hr: "[&_hr]:my-6 [&_hr]:border-border",
42
+ // GFM tables. The scroll container is structural and belongs to the consumer (MarkdownView wraps
43
+ // the table in an `overflow-x-auto` div); these are the cell and rule tokens.
44
+ table: "[&_table]:w-full [&_table]:border-collapse [&_table]:text-sm [&_table]:text-foreground [&_thead]:border-b [&_thead]:border-border [&_tr]:border-b [&_tr]:border-border [&_tr]:last:border-0 [&_th]:px-3 [&_th]:py-2 [&_th]:text-start [&_th]:font-medium [&_th]:text-foreground [&_td]:px-3 [&_td]:py-2 [&_td]:text-muted-foreground",
45
+ img: "[&_img]:my-3 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
46
+ };
47
+ var proseClassName = Object.values(prose).join(" ");
48
+
49
+ // src/index.ts
50
+ var twMerge = tailwindMerge;
51
+ function cn(...inputs) {
52
+ return twMerge(clsx(inputs));
53
+ }
54
+ var TIMINGS = {
55
+ /** How long transient success feedback holds before reverting (CopyButton "Copied ✓"). */
56
+ feedbackRevertMs: 1500,
57
+ /** Debounce before auto-persisting a text field (AutoSaveInput). */
58
+ autoSaveDebounceMs: 800,
59
+ /** Hover delay before a rich preview (HoverCard) opens — guards accidental opens. */
60
+ hoverOpenDelayMs: 700,
61
+ /** Hover delay before a rich preview closes — lets the pointer travel into the card. */
62
+ hoverCloseDelayMs: 300,
63
+ /**
64
+ * Hover delay before a tooltip opens. A tooltip is a cheap label, not a preview, so it is
65
+ * deliberately much faster than {@link TIMINGS.hoverOpenDelayMs} — long enough that sweeping
66
+ * across a toolbar does not flash five tips, short enough that a deliberate hover feels
67
+ * instant. Base UI's `Tooltip.Provider` grouping then opens adjacent tips with no delay at
68
+ * all. Set once, in the app-root provider.
69
+ */
70
+ tooltipOpenDelayMs: 300,
71
+ /**
72
+ * Delay before a tooltip closes. Zero: a tooltip has nothing to travel into (it is not
73
+ * hoverable content, unlike a HoverCard), so holding it after the pointer leaves only
74
+ * obscures what the user moved on to.
75
+ */
76
+ tooltipCloseDelayMs: 0
77
+ };
78
+ var FLOATING = {
79
+ sideOffsetAttached: 4,
80
+ sideOffsetDetached: 8,
81
+ collisionPadding: 8
82
+ };
83
+ function mergeRefs(...refs) {
84
+ return (node) => {
85
+ for (const ref of refs) {
86
+ if (ref == null) continue;
87
+ if (typeof ref === "function") {
88
+ ref(node);
89
+ } else {
90
+ ref.current = node;
91
+ }
92
+ }
93
+ };
94
+ }
95
+
96
+ export {
97
+ prose,
98
+ proseClassName,
99
+ cn,
100
+ TIMINGS,
101
+ FLOATING,
102
+ mergeRefs
103
+ };
@@ -41,60 +41,10 @@ var import_react = require("motion/react");
41
41
  // src/index.ts
42
42
  var import_clsx = require("clsx");
43
43
  var import_tailwind_merge = require("tailwind-merge");
44
- var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
45
- extend: {
46
- classGroups: {
47
- "font-size": [
48
- {
49
- text: [
50
- "h1",
51
- "h2",
52
- "h3",
53
- "h4",
54
- "label",
55
- "label-sm",
56
- "code",
57
- "code-sm",
58
- "mono-label",
59
- "display-sm",
60
- "display-md",
61
- "display-lg",
62
- "display-xl"
63
- ]
64
- }
65
- ]
66
- }
67
- }
68
- });
44
+ var twMerge = import_tailwind_merge.twMerge;
69
45
  function cn(...inputs) {
70
46
  return twMerge((0, import_clsx.clsx)(inputs));
71
47
  }
72
- var fieldControl = [
73
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
74
- "placeholder:text-muted-foreground-faint",
75
- "not-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
76
- "focus:border-ring/(--alpha-tint-border)",
77
- "not-focus:aria-invalid:border-destructive-border/(--alpha-tint-border)",
78
- "not-focus:data-invalid:border-destructive-border/(--alpha-tint-border)",
79
- "disabled:cursor-not-allowed disabled:bg-surface-1 disabled:opacity-(--opacity-dim)",
80
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
81
- ].join(" ");
82
- var fieldControlGroup = [
83
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
84
- "not-has-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
85
- "focus-within:border-ring/(--alpha-tint-border)",
86
- "data-focused:border-ring/(--alpha-tint-border)",
87
- // Both the SELF and the DESCENDANT form of the invalid tint (2026-09-09). `has-aria-invalid:` is
88
- // a `:has()` over descendants, so a group that carries `aria-invalid` on ITSELF — which is where
89
- // `<NumberField aria-invalid />` lands the attribute, on the `[data-field-group]` element —
90
- // matched nothing and measured the neutral `--input` border. Inside a `Field` the state arrives
91
- // as `data-invalid` on the group and was always correct; this is the standalone path.
92
- "not-focus-within:aria-invalid:border-destructive-border/(--alpha-tint-border)",
93
- "not-focus-within:has-aria-invalid:border-destructive-border/(--alpha-tint-border)",
94
- "not-focus-within:data-invalid:border-destructive-border/(--alpha-tint-border)",
95
- "has-disabled:cursor-not-allowed has-disabled:bg-surface-1 has-disabled:opacity-(--opacity-dim)",
96
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
97
- ].join(" ");
98
48
 
99
49
  // src/icons/create-animated-icon.tsx
100
50
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -239,7 +189,7 @@ function createAnimatedIcon(spec) {
239
189
  const RootTag = rootTag === "motion.svg" ? import_react.motion.svg : "svg";
240
190
  function AnimatedIconComponent({
241
191
  className,
242
- size = "var(--icon-default)",
192
+ size = "1rem",
243
193
  ref,
244
194
  onPointerEnter,
245
195
  onPointerLeave,
@@ -177,7 +177,7 @@ interface AnimatedIconSpec {
177
177
  stop?: (choreography: AnimatedIconChoreography) => void | Promise<void>;
178
178
  }
179
179
  interface AnimatedIconOwnProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "ref"> {
180
- /** Any CSS length. Defaults to the `--icon-default` role token. */
180
+ /** Any CSS length. Defaults to the `size-4` role token. */
181
181
  size?: number | string;
182
182
  ref?: React.Ref<AnimatedIconHandle>;
183
183
  }
@@ -177,7 +177,7 @@ interface AnimatedIconSpec {
177
177
  stop?: (choreography: AnimatedIconChoreography) => void | Promise<void>;
178
178
  }
179
179
  interface AnimatedIconOwnProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "ref"> {
180
- /** Any CSS length. Defaults to the `--icon-default` role token. */
180
+ /** Any CSS length. Defaults to the `size-4` role token. */
181
181
  size?: number | string;
182
182
  ref?: React.Ref<AnimatedIconHandle>;
183
183
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  cn
4
- } from "./chunk-DS7SBEDS.js";
4
+ } from "./chunk-42HJ4OYZ.js";
5
5
 
6
6
  // src/icons/create-animated-icon.tsx
7
7
  import * as React from "react";
@@ -153,7 +153,7 @@ function createAnimatedIcon(spec) {
153
153
  const RootTag = rootTag === "motion.svg" ? motion.svg : "svg";
154
154
  function AnimatedIconComponent({
155
155
  className,
156
- size = "var(--icon-default)",
156
+ size = "1rem",
157
157
  ref,
158
158
  onPointerEnter,
159
159
  onPointerLeave,
@@ -55,60 +55,10 @@ var React2 = require("react");
55
55
  // src/index.ts
56
56
  var import_clsx = require("clsx");
57
57
  var import_tailwind_merge = require("tailwind-merge");
58
- var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
59
- extend: {
60
- classGroups: {
61
- "font-size": [
62
- {
63
- text: [
64
- "h1",
65
- "h2",
66
- "h3",
67
- "h4",
68
- "label",
69
- "label-sm",
70
- "code",
71
- "code-sm",
72
- "mono-label",
73
- "display-sm",
74
- "display-md",
75
- "display-lg",
76
- "display-xl"
77
- ]
78
- }
79
- ]
80
- }
81
- }
82
- });
58
+ var twMerge = import_tailwind_merge.twMerge;
83
59
  function cn(...inputs) {
84
60
  return twMerge((0, import_clsx.clsx)(inputs));
85
61
  }
86
- var fieldControl = [
87
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
88
- "placeholder:text-muted-foreground-faint",
89
- "not-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
90
- "focus:border-ring/(--alpha-tint-border)",
91
- "not-focus:aria-invalid:border-destructive-border/(--alpha-tint-border)",
92
- "not-focus:data-invalid:border-destructive-border/(--alpha-tint-border)",
93
- "disabled:cursor-not-allowed disabled:bg-surface-1 disabled:opacity-(--opacity-dim)",
94
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
95
- ].join(" ");
96
- var fieldControlGroup = [
97
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
98
- "not-has-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
99
- "focus-within:border-ring/(--alpha-tint-border)",
100
- "data-focused:border-ring/(--alpha-tint-border)",
101
- // Both the SELF and the DESCENDANT form of the invalid tint (2026-09-09). `has-aria-invalid:` is
102
- // a `:has()` over descendants, so a group that carries `aria-invalid` on ITSELF — which is where
103
- // `<NumberField aria-invalid />` lands the attribute, on the `[data-field-group]` element —
104
- // matched nothing and measured the neutral `--input` border. Inside a `Field` the state arrives
105
- // as `data-invalid` on the group and was always correct; this is the standalone path.
106
- "not-focus-within:aria-invalid:border-destructive-border/(--alpha-tint-border)",
107
- "not-focus-within:has-aria-invalid:border-destructive-border/(--alpha-tint-border)",
108
- "not-focus-within:data-invalid:border-destructive-border/(--alpha-tint-border)",
109
- "has-disabled:cursor-not-allowed has-disabled:bg-surface-1 has-disabled:opacity-(--opacity-dim)",
110
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
111
- ].join(" ");
112
62
 
113
63
  // src/icons/brand-icon.tsx
114
64
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -193,10 +143,10 @@ function BrandIcon({
193
143
  var React3 = require("react");
194
144
  var import_jsx_runtime3 = require("react/jsx-runtime");
195
145
  var SIZES2 = {
196
- xs: "var(--icon-inline)",
197
- sm: "var(--icon-default)",
198
- md: "var(--icon-action)",
199
- lg: "var(--icon-feature)"
146
+ xs: "0.875rem",
147
+ sm: "1rem",
148
+ md: "1.25rem",
149
+ lg: "1.5rem"
200
150
  };
201
151
  function AnimatedIcon({
202
152
  as: Cmp,
@@ -92,12 +92,19 @@ interface BrandIconProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "ch
92
92
  */
93
93
  declare function BrandIcon({ icon, variant, size, "aria-label": label, className, ...props }: BrandIconProps): React.JSX.Element;
94
94
 
95
- /** Runtime icon-role tokens — resolves in the consumer's active theme. */
95
+ /**
96
+ * The four animated-icon sizes, as literal rem values.
97
+ *
98
+ * They were `var(size-3.5|default|action|feature)` until the shadcn reset deleted the
99
+ * `--icon-*` role family (ICO-2 = shadcn: upstream sizes icons with a plain `size-4` on the
100
+ * parent). The rendered sizes are unchanged — 14 / 16 / 20 / 24px — and they are literals here
101
+ * because this value is passed to `motion.svg` as a `size` prop, not compiled as a utility.
102
+ */
96
103
  declare const SIZES: {
97
- readonly xs: "var(--icon-inline)";
98
- readonly sm: "var(--icon-default)";
99
- readonly md: "var(--icon-action)";
100
- readonly lg: "var(--icon-feature)";
104
+ readonly xs: "0.875rem";
105
+ readonly sm: "1rem";
106
+ readonly md: "1.25rem";
107
+ readonly lg: "1.5rem";
101
108
  };
102
109
  type AnimatedIconSize = keyof typeof SIZES;
103
110
  /**
@@ -125,7 +132,7 @@ interface AnimatedIconProps extends Omit<React.HTMLAttributes<HTMLSpanElement>,
125
132
  /** A mirrored lucide-animated icon component, e.g. `import { ActivityIcon } from '@/components/ui/activity'`. */
126
133
  as: AnimatedIconComponent;
127
134
  /**
128
- * Size role — resolves through `--icon-inline/default/action/feature` at runtime.
135
+ * Size role — resolves through `size-3.5/default/action/feature` at runtime.
129
136
  * @default 'md'
130
137
  */
131
138
  size?: AnimatedIconSize;
@@ -92,12 +92,19 @@ interface BrandIconProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "ch
92
92
  */
93
93
  declare function BrandIcon({ icon, variant, size, "aria-label": label, className, ...props }: BrandIconProps): React.JSX.Element;
94
94
 
95
- /** Runtime icon-role tokens — resolves in the consumer's active theme. */
95
+ /**
96
+ * The four animated-icon sizes, as literal rem values.
97
+ *
98
+ * They were `var(size-3.5|default|action|feature)` until the shadcn reset deleted the
99
+ * `--icon-*` role family (ICO-2 = shadcn: upstream sizes icons with a plain `size-4` on the
100
+ * parent). The rendered sizes are unchanged — 14 / 16 / 20 / 24px — and they are literals here
101
+ * because this value is passed to `motion.svg` as a `size` prop, not compiled as a utility.
102
+ */
96
103
  declare const SIZES: {
97
- readonly xs: "var(--icon-inline)";
98
- readonly sm: "var(--icon-default)";
99
- readonly md: "var(--icon-action)";
100
- readonly lg: "var(--icon-feature)";
104
+ readonly xs: "0.875rem";
105
+ readonly sm: "1rem";
106
+ readonly md: "1.25rem";
107
+ readonly lg: "1.5rem";
101
108
  };
102
109
  type AnimatedIconSize = keyof typeof SIZES;
103
110
  /**
@@ -125,7 +132,7 @@ interface AnimatedIconProps extends Omit<React.HTMLAttributes<HTMLSpanElement>,
125
132
  /** A mirrored lucide-animated icon component, e.g. `import { ActivityIcon } from '@/components/ui/activity'`. */
126
133
  as: AnimatedIconComponent;
127
134
  /**
128
- * Size role — resolves through `--icon-inline/default/action/feature` at runtime.
135
+ * Size role — resolves through `size-3.5/default/action/feature` at runtime.
129
136
  * @default 'md'
130
137
  */
131
138
  size?: AnimatedIconSize;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cn
3
- } from "../chunk-DS7SBEDS.js";
3
+ } from "../chunk-42HJ4OYZ.js";
4
4
 
5
5
  // src/icons/icon.tsx
6
6
  import "react";
@@ -109,10 +109,10 @@ function BrandIcon({
109
109
  import "react";
110
110
  import { jsx as jsx3 } from "react/jsx-runtime";
111
111
  var SIZES2 = {
112
- xs: "var(--icon-inline)",
113
- sm: "var(--icon-default)",
114
- md: "var(--icon-action)",
115
- lg: "var(--icon-feature)"
112
+ xs: "0.875rem",
113
+ sm: "1rem",
114
+ md: "1.25rem",
115
+ lg: "1.5rem"
116
116
  };
117
117
  function AnimatedIcon({
118
118
  as: Cmp,
package/dist/index.cjs CHANGED
@@ -23,15 +23,9 @@ __export(src_exports, {
23
23
  FLOATING: () => FLOATING,
24
24
  TIMINGS: () => TIMINGS,
25
25
  cn: () => cn,
26
- fieldControl: () => fieldControl,
27
- fieldControlGroup: () => fieldControlGroup,
28
- fillInteractive: () => fillInteractive,
29
26
  mergeRefs: () => mergeRefs,
30
27
  prose: () => prose,
31
- proseClassName: () => proseClassName,
32
- selectedChipVariants: () => selectedChipVariants,
33
- surfaceInteractive: () => surfaceInteractive,
34
- surfaceInteractiveGroup: () => surfaceInteractiveGroup
28
+ proseClassName: () => proseClassName
35
29
  });
36
30
  module.exports = __toCommonJS(src_exports);
37
31
  var import_clsx = require("clsx");
@@ -40,20 +34,21 @@ var import_tailwind_merge = require("tailwind-merge");
40
34
  // src/prose.ts
41
35
  var prose = {
42
36
  /** The root's own ink and size — every rule below is relative to this. */
43
- root: "text-base text-foreground",
44
- // Headings. `scroll-m-20` keeps an anchored heading clear of a sticky header; the weight ladder
45
- // caps at 500, which the `text-h*` roles already carry.
46
- h1: "[&_h1]:mt-6 [&_h1]:mb-3 [&_h1]:scroll-m-20 [&_h1]:text-h1 [&_h1]:text-foreground [&_h1]:first:mt-0",
47
- h2: "[&_h2]:mt-6 [&_h2]:mb-3 [&_h2]:scroll-m-20 [&_h2]:text-h2 [&_h2]:text-foreground [&_h2]:first:mt-0",
48
- h3: "[&_h3]:mt-5 [&_h3]:mb-2 [&_h3]:scroll-m-20 [&_h3]:text-h3 [&_h3]:text-foreground [&_h3]:first:mt-0",
49
- h4: "[&_h4]:mt-4 [&_h4]:mb-2 [&_h4]:scroll-m-20 [&_h4]:text-h4 [&_h4]:text-foreground [&_h4]:first:mt-0",
37
+ root: "text-sm text-foreground",
38
+ // Headings. `scroll-m-20` keeps an anchored heading clear of a sticky header; the weight is
39
+ // `font-semibold`, the ordinary Tailwind weight upstream uses — Batch 1 of the shadcn reset
40
+ // deleted both the 400/500 ladder and the `text-h*` roles this comment used to name.
41
+ h1: "[&_h1]:mt-6 [&_h1]:mb-3 [&_h1]:scroll-m-20 [&_h1]:text-3xl [&_h1]:font-semibold [&_h1]:text-foreground [&_h1]:first:mt-0",
42
+ h2: "[&_h2]:mt-6 [&_h2]:mb-3 [&_h2]:scroll-m-20 [&_h2]:text-2xl [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:first:mt-0",
43
+ h3: "[&_h3]:mt-5 [&_h3]:mb-2 [&_h3]:scroll-m-20 [&_h3]:text-xl [&_h3]:font-semibold [&_h3]:text-foreground [&_h3]:first:mt-0",
44
+ h4: "[&_h4]:mt-4 [&_h4]:mb-2 [&_h4]:scroll-m-20 [&_h4]:text-base [&_h4]:font-medium [&_h4]:text-foreground [&_h4]:first:mt-0",
50
45
  // h5/h6 leave the display tier and become labels — the type scale has no sixth heading size.
51
- h5: "[&_h5]:mt-4 [&_h5]:mb-2 [&_h5]:text-label [&_h5]:text-foreground [&_h5]:first:mt-0",
52
- h6: "[&_h6]:mt-4 [&_h6]:mb-2 [&_h6]:text-label [&_h6]:text-muted-foreground [&_h6]:first:mt-0",
46
+ h5: "[&_h5]:mt-4 [&_h5]:mb-2 [&_h5]:text-sm [&_h5]:font-medium [&_h5]:text-foreground [&_h5]:first:mt-0",
47
+ h6: "[&_h6]:mt-4 [&_h6]:mb-2 [&_h6]:text-sm [&_h6]:font-medium [&_h6]:text-muted-foreground [&_h6]:first:mt-0",
53
48
  p: "[&_p]:my-3 [&_p]:leading-relaxed [&_p]:text-foreground [&_p]:first:mt-0 [&_p]:last:mb-0",
54
49
  // Marks. Links are `info` ink per design.md §Colours; `s` is Tiptap's strike element and `del`
55
50
  // is GFM's — the same mark from two producers.
56
- a: "[&_a]:font-medium [&_a]:text-info-text [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-info-text/(--alpha-link-hover)",
51
+ a: "[&_a]:font-medium [&_a]:text-info-text [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-info-text/88",
57
52
  strong: "[&_strong]:font-medium [&_strong]:text-foreground",
58
53
  em: "[&_em]:italic",
59
54
  del: "[&_del]:text-muted-foreground [&_del]:line-through [&_s]:text-muted-foreground [&_s]:line-through",
@@ -66,103 +61,25 @@ var prose = {
66
61
  blockquote: "[&_blockquote]:my-3 [&_blockquote]:border-s-2 [&_blockquote]:border-border [&_blockquote]:ps-4 [&_blockquote]:text-muted-foreground [&_blockquote]:italic",
67
62
  // Inline code is a chip. Code inside a `pre` is not: it inherits the panel's ground, so the chip
68
63
  // is undone at higher specificity (`[&_pre_code]` is (0,1,2) against the chip's (0,1,1)).
69
- code: "[&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-base [&_code]:text-foreground",
64
+ code: "[&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-sm [&_code]:text-foreground",
70
65
  // A bare `<pre>` wears `CodeBlock`'s surface — the same sunken panel, one vocabulary (B4-09).
71
66
  // `CodeBlock`'s own `pre` is excluded: it already sits inside a `figure` carrying the border,
72
67
  // radius and ground, and re-applying them here would draw a second panel inside the first.
73
68
  pre: "[&_pre:not([data-slot='code-block-pre'])]:my-3 [&_pre:not([data-slot='code-block-pre'])]:overflow-x-auto [&_pre:not([data-slot='code-block-pre'])]:rounded-lg [&_pre:not([data-slot='code-block-pre'])]:border [&_pre:not([data-slot='code-block-pre'])]:border-border [&_pre:not([data-slot='code-block-pre'])]:bg-muted [&_pre:not([data-slot='code-block-pre'])]:p-4 [&_pre:not([data-slot='code-block-pre'])]:text-foreground",
74
- preCode: "[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:font-mono [&_pre_code]:text-code [&_pre_code]:text-foreground",
69
+ preCode: "[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:font-mono [&_pre_code]:text-sm [&_pre_code]:text-foreground",
75
70
  hr: "[&_hr]:my-6 [&_hr]:border-border",
76
71
  // GFM tables. The scroll container is structural and belongs to the consumer (MarkdownView wraps
77
72
  // the table in an `overflow-x-auto` div); these are the cell and rule tokens.
78
- table: "[&_table]:w-full [&_table]:border-collapse [&_table]:text-base [&_table]:text-foreground [&_thead]:border-b [&_thead]:border-border [&_tr]:border-b [&_tr]:border-border [&_tr]:last:border-0 [&_th]:px-3 [&_th]:py-2 [&_th]:text-start [&_th]:font-medium [&_th]:text-foreground [&_td]:px-3 [&_td]:py-2 [&_td]:text-muted-foreground",
73
+ table: "[&_table]:w-full [&_table]:border-collapse [&_table]:text-sm [&_table]:text-foreground [&_thead]:border-b [&_thead]:border-border [&_tr]:border-b [&_tr]:border-border [&_tr]:last:border-0 [&_th]:px-3 [&_th]:py-2 [&_th]:text-start [&_th]:font-medium [&_th]:text-foreground [&_td]:px-3 [&_td]:py-2 [&_td]:text-muted-foreground",
79
74
  img: "[&_img]:my-3 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
80
75
  };
81
76
  var proseClassName = Object.values(prose).join(" ");
82
77
 
83
78
  // src/index.ts
84
- var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
85
- extend: {
86
- classGroups: {
87
- "font-size": [
88
- {
89
- text: [
90
- "h1",
91
- "h2",
92
- "h3",
93
- "h4",
94
- "label",
95
- "label-sm",
96
- "code",
97
- "code-sm",
98
- "mono-label",
99
- "display-sm",
100
- "display-md",
101
- "display-lg",
102
- "display-xl"
103
- ]
104
- }
105
- ]
106
- }
107
- }
108
- });
79
+ var twMerge = import_tailwind_merge.twMerge;
109
80
  function cn(...inputs) {
110
81
  return twMerge((0, import_clsx.clsx)(inputs));
111
82
  }
112
- var surfaceInteractive = "hover:bg-surface-2 active:bg-surface-3";
113
- var surfaceInteractiveGroup = "group-hover/wash:bg-surface-2 group-active/wash:bg-surface-3";
114
- var fillInteractive = {
115
- foreground: "hover:bg-foreground/(--alpha-hover) active:bg-foreground/(--alpha-pressed)",
116
- primary: "hover:bg-primary/(--alpha-hover) active:bg-primary/(--alpha-pressed)",
117
- destructive: "hover:bg-destructive/(--alpha-hover) active:bg-destructive/(--alpha-pressed)",
118
- success: "hover:bg-success/(--alpha-hover) active:bg-success/(--alpha-pressed)",
119
- warning: "hover:bg-warning/(--alpha-hover) active:bg-warning/(--alpha-pressed)",
120
- info: "hover:bg-info/(--alpha-hover) active:bg-info/(--alpha-pressed)",
121
- brand: "hover:bg-brand/(--alpha-hover) active:bg-brand/(--alpha-pressed)"
122
- };
123
- var fieldControl = [
124
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
125
- "placeholder:text-muted-foreground-faint",
126
- "not-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
127
- "focus:border-ring/(--alpha-tint-border)",
128
- "not-focus:aria-invalid:border-destructive-border/(--alpha-tint-border)",
129
- "not-focus:data-invalid:border-destructive-border/(--alpha-tint-border)",
130
- "disabled:cursor-not-allowed disabled:bg-surface-1 disabled:opacity-(--opacity-dim)",
131
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
132
- ].join(" ");
133
- var fieldControlGroup = [
134
- "rounded-md border border-input bg-transparent dark:bg-input/(--alpha-input)",
135
- "not-has-disabled:not-data-disabled:hover:border-foreground/(--alpha-border-subtle)",
136
- "focus-within:border-ring/(--alpha-tint-border)",
137
- "data-focused:border-ring/(--alpha-tint-border)",
138
- // Both the SELF and the DESCENDANT form of the invalid tint (2026-09-09). `has-aria-invalid:` is
139
- // a `:has()` over descendants, so a group that carries `aria-invalid` on ITSELF — which is where
140
- // `<NumberField aria-invalid />` lands the attribute, on the `[data-field-group]` element —
141
- // matched nothing and measured the neutral `--input` border. Inside a `Field` the state arrives
142
- // as `data-invalid` on the group and was always correct; this is the standalone path.
143
- "not-focus-within:aria-invalid:border-destructive-border/(--alpha-tint-border)",
144
- "not-focus-within:has-aria-invalid:border-destructive-border/(--alpha-tint-border)",
145
- "not-focus-within:data-invalid:border-destructive-border/(--alpha-tint-border)",
146
- "has-disabled:cursor-not-allowed has-disabled:bg-surface-1 has-disabled:opacity-(--opacity-dim)",
147
- "data-disabled:cursor-not-allowed data-disabled:bg-surface-1 data-disabled:opacity-(--opacity-dim)"
148
- ].join(" ");
149
- var selectedChipVariants = {
150
- /**
151
- * The muted track the chips sit in — the ladder's well rung with a drawn inset boundary. The
152
- * pseudo-element keeps the 28 / 32px track boxes unchanged; a real root border would add 2px and
153
- * silently break the shared control scale.
154
- */
155
- track: "relative bg-surface-1 after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:border after:border-border after:content-['']",
156
- /**
157
- * Chrome shared by every chip: a transparent hairline reserved at rest (so selecting adds no
158
- * layout shift) and the muted→ink text step.
159
- */
160
- item: "border border-transparent hover:text-foreground",
161
- /** Selected keyed on Base UI's `data-pressed` — Toggle, ToggleGroup, Segmented. */
162
- pressed: "not-data-pressed:hover:bg-foreground/(--alpha-hover) not-data-pressed:active:bg-foreground/(--alpha-pressed) data-pressed:border-border data-pressed:bg-foreground/(--alpha-ink-tint) data-pressed:text-foreground data-pressed:hover:bg-foreground/(--alpha-ink-tint-strong) data-pressed:active:bg-foreground/(--alpha-ink-tint)",
163
- /** Selected keyed on Base UI's `data-active` — Tabs. */
164
- active: "not-data-[active]:hover:bg-foreground/(--alpha-hover) not-data-[active]:active:bg-foreground/(--alpha-pressed) data-[active]:border-border data-[active]:bg-foreground/(--alpha-ink-tint) data-[active]:text-foreground data-[active]:hover:bg-foreground/(--alpha-ink-tint-strong) data-[active]:active:bg-foreground/(--alpha-ink-tint)"
165
- };
166
83
  var TIMINGS = {
167
84
  /** How long transient success feedback holds before reverting (CopyButton "Copied ✓"). */
168
85
  feedbackRevertMs: 1500,
@@ -209,13 +126,7 @@ function mergeRefs(...refs) {
209
126
  FLOATING,
210
127
  TIMINGS,
211
128
  cn,
212
- fieldControl,
213
- fieldControlGroup,
214
- fillInteractive,
215
129
  mergeRefs,
216
130
  prose,
217
- proseClassName,
218
- selectedChipVariants,
219
- surfaceInteractive,
220
- surfaceInteractiveGroup
131
+ proseClassName
221
132
  });