@vegastack/design 0.8.11 → 0.8.12
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/{chunk-R6IZOGT5.js → chunk-DG7GQHEH.js} +35 -0
- package/dist/create-animated-icon.cjs +125 -0
- package/dist/create-animated-icon.js +1 -1
- package/dist/icons/index.cjs +125 -0
- package/dist/icons/index.js +1 -1
- package/dist/index.cjs +39 -2
- package/dist/index.d.cts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +7 -3
- package/package.json +2 -2
- package/skills/vegastack-design-system/references/components.md +3 -2
|
@@ -91,6 +91,35 @@ var prose = {
|
|
|
91
91
|
img: "[&_img]:my-2 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
|
|
92
92
|
};
|
|
93
93
|
var proseClassName = Object.values(prose).join(" ");
|
|
94
|
+
var proseDocument = {
|
|
95
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
96
|
+
root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5",
|
|
97
|
+
// Headings: semibold (the base recipe's weight), more room above than below. The first block
|
|
98
|
+
// keeps `first:mt-0` from the base recipe. `scroll-mt-18` clears a 56px sticky header + 16.
|
|
99
|
+
h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8",
|
|
100
|
+
h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7",
|
|
101
|
+
h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7",
|
|
102
|
+
h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5",
|
|
103
|
+
// A 12px gap between paragraphs; none before the first or after the last.
|
|
104
|
+
p: "[&_p]:my-3",
|
|
105
|
+
// Lists indent 24, items 4 apart, a nested list 4 below its item's text.
|
|
106
|
+
ul: "[&_ul]:my-3 [&_ul]:ms-6",
|
|
107
|
+
ol: "[&_ol]:my-3 [&_ol]:ms-6",
|
|
108
|
+
li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0",
|
|
109
|
+
// A quote is a rule and an indent, never italic; blocks breathe 16 apart.
|
|
110
|
+
blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4",
|
|
111
|
+
// No orange in documents: inline code is a grey chip in the body's own ink.
|
|
112
|
+
code: "[&_code]:text-foreground",
|
|
113
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4",
|
|
114
|
+
hr: "[&_hr]:my-6",
|
|
115
|
+
img: "[&_img]:my-4",
|
|
116
|
+
// Tables read at 14/20 at every pointer, 16 from the blocks around them (the scroll box is the
|
|
117
|
+
// consumer's: `MarkdownView`'s `markdown-table`, the editor's `.tableWrapper`).
|
|
118
|
+
table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4",
|
|
119
|
+
// Callouts, toggles, code blocks and media sit 16 from their neighbours; a toggle's summary is
|
|
120
|
+
// a 24px row, 44px on a coarse pointer.
|
|
121
|
+
blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11"
|
|
122
|
+
};
|
|
94
123
|
|
|
95
124
|
// src/index.ts
|
|
96
125
|
var twMerge = tailwindMerge;
|
|
@@ -132,6 +161,10 @@ var FLOATING = {
|
|
|
132
161
|
sideOffsetDetached: 8,
|
|
133
162
|
collisionPadding: 8
|
|
134
163
|
};
|
|
164
|
+
var proseDocumentClassName = cn(
|
|
165
|
+
proseClassName,
|
|
166
|
+
Object.values(proseDocument).join(" ")
|
|
167
|
+
);
|
|
135
168
|
function mergeRefs(...refs) {
|
|
136
169
|
return (node) => {
|
|
137
170
|
const cleanups = refs.map((ref) => {
|
|
@@ -166,8 +199,10 @@ function mergeRefs(...refs) {
|
|
|
166
199
|
export {
|
|
167
200
|
prose,
|
|
168
201
|
proseClassName,
|
|
202
|
+
proseDocument,
|
|
169
203
|
cn,
|
|
170
204
|
TIMINGS,
|
|
171
205
|
FLOATING,
|
|
206
|
+
proseDocumentClassName,
|
|
172
207
|
mergeRefs
|
|
173
208
|
};
|
|
@@ -41,10 +41,135 @@ 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
|
+
|
|
45
|
+
// src/prose.ts
|
|
46
|
+
var prose = {
|
|
47
|
+
/**
|
|
48
|
+
* The root's own FAMILY, ink and size — every rule below is relative to this.
|
|
49
|
+
*
|
|
50
|
+
* `font-sans` is load-bearing and was missing. A prose root has to be self-describing, because
|
|
51
|
+
* neither of its two consumers sets a family of its own: `MarkdownView` and `TextEdit` both wear
|
|
52
|
+
* nothing but `proseClassName`. With no family declared here, prose inherited whatever surrounded
|
|
53
|
+
* it — drop either surface inside a mono container (`terminal-body` is one in this very
|
|
54
|
+
* registry, and a chat or log panel is the obvious consumer case) and the WHOLE tree went mono:
|
|
55
|
+
* headings, paragraphs, table cells, and the `1.` / `2.` markers of an ordered list, because
|
|
56
|
+
* `::marker` inherits font properties from its originating element.
|
|
57
|
+
*
|
|
58
|
+
* Geist Mono is now the exception the recipe names explicitly — `code`, `pre` and `pre code` —
|
|
59
|
+
* rather than something prose falls into by accident. A consumer who genuinely wants mono prose
|
|
60
|
+
* still says so on the root, where it reads as a decision.
|
|
61
|
+
*
|
|
62
|
+
* `min-w-0 wrap-anywhere` is the no-horizontal-overflow contract (2026-09-26): a long word, URL
|
|
63
|
+
* or inline code run breaks inside the line instead of widening the page, and `anywhere` (not
|
|
64
|
+
* `break-word`) also lowers the min-content width, so a prose root inside a flex item shrinks.
|
|
65
|
+
* Fenced code (`white-space: pre`) and tables keep their lines and scroll inside their own box.
|
|
66
|
+
*/
|
|
67
|
+
root: "font-sans text-sm font-normal text-foreground min-w-0 wrap-anywhere",
|
|
68
|
+
// Headings follow the app's type scale (design.md §Headings), not a document scale: the page
|
|
69
|
+
// title is the only `text-2xl`, so a heading inside rendered text stops at `text-lg` for `#`,
|
|
70
|
+
// the section size (`text-base`) for `##`, and body size for everything below — weight carries
|
|
71
|
+
// the rest. Every heading wears `font-heading` like the app's own titles.
|
|
72
|
+
h1: "[&_h1]:mt-5 [&_h1]:mb-2 [&_h1]:scroll-m-20 [&_h1]:font-heading [&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-foreground [&_h1]:first:mt-0",
|
|
73
|
+
h2: "[&_h2]:mt-4 [&_h2]:mb-2 [&_h2]:scroll-m-20 [&_h2]:font-heading [&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:first:mt-0",
|
|
74
|
+
h3: "[&_h3]:mt-4 [&_h3]:mb-1.5 [&_h3]:scroll-m-20 [&_h3]:font-heading [&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-foreground [&_h3]:first:mt-0",
|
|
75
|
+
h4: "[&_h4]:mt-3 [&_h4]:mb-1.5 [&_h4]:font-heading [&_h4]:text-sm [&_h4]:font-medium [&_h4]:text-foreground [&_h4]:first:mt-0",
|
|
76
|
+
h5: "[&_h5]:mt-3 [&_h5]:mb-1.5 [&_h5]:font-heading [&_h5]:text-sm [&_h5]:font-medium [&_h5]:text-foreground [&_h5]:first:mt-0",
|
|
77
|
+
h6: "[&_h6]:mt-3 [&_h6]:mb-1.5 [&_h6]:font-heading [&_h6]:text-sm [&_h6]:font-medium [&_h6]:text-foreground [&_h6]:first:mt-0",
|
|
78
|
+
// Body text is the app's body text — size, leading and ink inherit from the root, so a paragraph
|
|
79
|
+
// here is indistinguishable from any other `text-sm` paragraph in the product. No prose look.
|
|
80
|
+
p: "[&_p]:my-2 [&_p]:first:mt-0 [&_p]:last:mb-0",
|
|
81
|
+
// Marks. Links are `info` ink per design.md §Colours at body weight; `s` is Tiptap's strike
|
|
82
|
+
// element and `del` is GFM's — the same mark from two producers.
|
|
83
|
+
a: "[&_a]:text-info-text [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-info-text/88",
|
|
84
|
+
strong: "[&_strong]:font-semibold",
|
|
85
|
+
em: "[&_em]:italic",
|
|
86
|
+
del: "[&_del]:line-through [&_s]:line-through",
|
|
87
|
+
// Lists. Items and markers are body text: family, size and ink inherit (a `::marker` takes the
|
|
88
|
+
// item's font), so `1.` and `•` never read as a second typeface or a second colour. One thing
|
|
89
|
+
// does NOT inherit: the user-agent stylesheet gives `::marker` `font-variant-numeric:
|
|
90
|
+
// tabular-nums`, and Geist's tabular figures are fixed-width — that is what made ordered-list
|
|
91
|
+
// numbers look monospaced. `marker:normal-nums` restores the body's proportional figures. A GFM task
|
|
92
|
+
// list carries `contains-task-list` and its checkbox IS the marker, so the disc goes — expressed
|
|
93
|
+
// as a second, more specific descendant rule rather than a class on the element, which would
|
|
94
|
+
// lose the cascade (see the header).
|
|
95
|
+
ul: "[&_ul]:my-2 [&_ul]:ms-5 [&_ul]:list-disc [&_ul.contains-task-list]:list-none",
|
|
96
|
+
ol: "[&_ol]:my-2 [&_ol]:ms-5 [&_ol]:list-decimal",
|
|
97
|
+
li: "[&_li]:mt-1 [&_li]:marker:normal-nums [&_li]:marker:text-inherit [&_li_p]:my-0",
|
|
98
|
+
// Task lists, one shape for both producers: `MarkdownView` tags the GFM list
|
|
99
|
+
// `data-type="taskList"` and each item `data-type="taskItem"` with its body in a
|
|
100
|
+
// `data-slot="task-item-content"` box, which is exactly the DOM Tiptap's `TaskItem` node view
|
|
101
|
+
// renders — so the checkbox IS the marker, the body wraps beside it, and a nested list indents
|
|
102
|
+
// under the body in view and edit alike. The checkbox's hit area is trimmed to exactly 24px tall
|
|
103
|
+
// here (`after:-inset-y-1.25` — the pseudo insets from inside the 1px border — not its own 30px) and items sit 26px apart (`mt-1.5`), so each
|
|
104
|
+
// checkbox owns a whole 24px target with a hair to spare instead of reaching into its
|
|
105
|
+
// neighbour's.
|
|
106
|
+
taskList: "[&_ul[data-type=taskList]]:ms-0 [&_ul[data-type=taskList]]:list-none [&_li[data-type=taskItem]]:mt-1.5 [&_li[data-type=taskItem]]:flex [&_li[data-type=taskItem]]:items-start [&_li[data-type=taskItem]]:gap-2 [&_li[data-type=taskItem]_[data-slot=checkbox]]:mt-0.5 [&_li[data-type=taskItem]_[data-slot=checkbox]]:me-0 [&_li[data-type=taskItem]_[data-slot=checkbox]]:after:-inset-y-1.25 [&_[data-slot=task-item-content]]:min-w-0 [&_[data-slot=task-item-content]]:flex-1",
|
|
107
|
+
blockquote: "[&_blockquote]:my-2 [&_blockquote]:border-s-2 [&_blockquote]:border-border [&_blockquote]:ps-3",
|
|
108
|
+
// Inline code is a chip. Code inside a `pre` is not: it inherits the panel's ground, so the chip
|
|
109
|
+
// is undone at higher specificity (`[&_pre_code]` is (0,1,2) against the chip's (0,1,1)).
|
|
110
|
+
// Slack/Notion: a neutral grey chip with orange text (the syntax palette's literal colour), so
|
|
111
|
+
// inline code reads apart from prose in both themes; `tag-orange-text` on `muted` clears AA.
|
|
112
|
+
code: "[&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-sm [&_code]:text-tag-orange-text",
|
|
113
|
+
// A bare `<pre>` wears `CodeBlock`'s surface — the same sunken panel, one vocabulary (B4-09).
|
|
114
|
+
// `CodeBlock`'s own `pre` is excluded: it already sits inside a `figure` carrying the border,
|
|
115
|
+
// radius and ground, and re-applying them here would draw a second panel inside the first.
|
|
116
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-2 [&_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",
|
|
117
|
+
preCode: "[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:font-mono [&_pre_code]:text-sm [&_pre_code]:text-foreground",
|
|
118
|
+
hr: "[&_hr]:my-4 [&_hr]:border-border",
|
|
119
|
+
// GFM tables, Notion's simple table: a rounded outer border, a rule between every cell, and a
|
|
120
|
+
// header row on a subtle muted ground at medium weight. The scroll container is structural and
|
|
121
|
+
// belongs to the consumer (MarkdownView and TextEdit each wrap the table in an `overflow-x-auto`
|
|
122
|
+
// box); these are the cell and rule tokens. `border-separate` with zero spacing is what lets the
|
|
123
|
+
// table itself take the radius (a collapsed table cannot); each cell draws only its bottom and
|
|
124
|
+
// end rule, the last row and column drop theirs against the outer border, and the corner cells
|
|
125
|
+
// take the radius so a header or selected fill never pokes past the curve. Cells take
|
|
126
|
+
// `break-word`, not the root's `anywhere`, so a column keeps its words whole and the table scrolls
|
|
127
|
+
// in its box rather than crushing to one character per line.
|
|
128
|
+
table: "[&_table]:w-full [&_table]:border-separate [&_table]:border-spacing-0 [&_table]:rounded-lg [&_table]:border [&_table]:border-border",
|
|
129
|
+
tableRules: "[&_th]:border-e [&_th]:border-b [&_th]:border-border [&_td]:border-e [&_td]:border-b [&_td]:border-border [&_tr>*:last-child]:border-e-0 [&_tbody>tr:last-child>*]:border-b-0 [&_tr:first-child>*:first-child]:rounded-ss-lg [&_tr:first-child>*:last-child]:rounded-se-lg [&_tbody>tr:last-child>*:first-child]:rounded-es-lg [&_tbody>tr:last-child>*:last-child]:rounded-ee-lg",
|
|
130
|
+
tableCells: "[&_th]:bg-muted/50 [&_th]:px-3 [&_th]:py-2 [&_th]:text-start [&_th]:align-top [&_th]:font-medium [&_td]:px-3 [&_td]:py-2 [&_td]:align-top [&_td_p]:my-0 [&_th_p]:my-0 [&_th]:wrap-break-word [&_td]:wrap-break-word",
|
|
131
|
+
img: "[&_img]:my-2 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
|
|
132
|
+
};
|
|
133
|
+
var proseClassName = Object.values(prose).join(" ");
|
|
134
|
+
var proseDocument = {
|
|
135
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
136
|
+
root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5",
|
|
137
|
+
// Headings: semibold (the base recipe's weight), more room above than below. The first block
|
|
138
|
+
// keeps `first:mt-0` from the base recipe. `scroll-mt-18` clears a 56px sticky header + 16.
|
|
139
|
+
h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8",
|
|
140
|
+
h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7",
|
|
141
|
+
h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7",
|
|
142
|
+
h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5",
|
|
143
|
+
// A 12px gap between paragraphs; none before the first or after the last.
|
|
144
|
+
p: "[&_p]:my-3",
|
|
145
|
+
// Lists indent 24, items 4 apart, a nested list 4 below its item's text.
|
|
146
|
+
ul: "[&_ul]:my-3 [&_ul]:ms-6",
|
|
147
|
+
ol: "[&_ol]:my-3 [&_ol]:ms-6",
|
|
148
|
+
li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0",
|
|
149
|
+
// A quote is a rule and an indent, never italic; blocks breathe 16 apart.
|
|
150
|
+
blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4",
|
|
151
|
+
// No orange in documents: inline code is a grey chip in the body's own ink.
|
|
152
|
+
code: "[&_code]:text-foreground",
|
|
153
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4",
|
|
154
|
+
hr: "[&_hr]:my-6",
|
|
155
|
+
img: "[&_img]:my-4",
|
|
156
|
+
// Tables read at 14/20 at every pointer, 16 from the blocks around them (the scroll box is the
|
|
157
|
+
// consumer's: `MarkdownView`'s `markdown-table`, the editor's `.tableWrapper`).
|
|
158
|
+
table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4",
|
|
159
|
+
// Callouts, toggles, code blocks and media sit 16 from their neighbours; a toggle's summary is
|
|
160
|
+
// a 24px row, 44px on a coarse pointer.
|
|
161
|
+
blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11"
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/index.ts
|
|
44
165
|
var twMerge = import_tailwind_merge.twMerge;
|
|
45
166
|
function cn(...inputs) {
|
|
46
167
|
return twMerge((0, import_clsx.clsx)(inputs));
|
|
47
168
|
}
|
|
169
|
+
var proseDocumentClassName = cn(
|
|
170
|
+
proseClassName,
|
|
171
|
+
Object.values(proseDocument).join(" ")
|
|
172
|
+
);
|
|
48
173
|
|
|
49
174
|
// src/icons/create-animated-icon.tsx
|
|
50
175
|
var import_jsx_runtime = require("react/jsx-runtime");
|
package/dist/icons/index.cjs
CHANGED
|
@@ -55,10 +55,135 @@ 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
|
+
|
|
59
|
+
// src/prose.ts
|
|
60
|
+
var prose = {
|
|
61
|
+
/**
|
|
62
|
+
* The root's own FAMILY, ink and size — every rule below is relative to this.
|
|
63
|
+
*
|
|
64
|
+
* `font-sans` is load-bearing and was missing. A prose root has to be self-describing, because
|
|
65
|
+
* neither of its two consumers sets a family of its own: `MarkdownView` and `TextEdit` both wear
|
|
66
|
+
* nothing but `proseClassName`. With no family declared here, prose inherited whatever surrounded
|
|
67
|
+
* it — drop either surface inside a mono container (`terminal-body` is one in this very
|
|
68
|
+
* registry, and a chat or log panel is the obvious consumer case) and the WHOLE tree went mono:
|
|
69
|
+
* headings, paragraphs, table cells, and the `1.` / `2.` markers of an ordered list, because
|
|
70
|
+
* `::marker` inherits font properties from its originating element.
|
|
71
|
+
*
|
|
72
|
+
* Geist Mono is now the exception the recipe names explicitly — `code`, `pre` and `pre code` —
|
|
73
|
+
* rather than something prose falls into by accident. A consumer who genuinely wants mono prose
|
|
74
|
+
* still says so on the root, where it reads as a decision.
|
|
75
|
+
*
|
|
76
|
+
* `min-w-0 wrap-anywhere` is the no-horizontal-overflow contract (2026-09-26): a long word, URL
|
|
77
|
+
* or inline code run breaks inside the line instead of widening the page, and `anywhere` (not
|
|
78
|
+
* `break-word`) also lowers the min-content width, so a prose root inside a flex item shrinks.
|
|
79
|
+
* Fenced code (`white-space: pre`) and tables keep their lines and scroll inside their own box.
|
|
80
|
+
*/
|
|
81
|
+
root: "font-sans text-sm font-normal text-foreground min-w-0 wrap-anywhere",
|
|
82
|
+
// Headings follow the app's type scale (design.md §Headings), not a document scale: the page
|
|
83
|
+
// title is the only `text-2xl`, so a heading inside rendered text stops at `text-lg` for `#`,
|
|
84
|
+
// the section size (`text-base`) for `##`, and body size for everything below — weight carries
|
|
85
|
+
// the rest. Every heading wears `font-heading` like the app's own titles.
|
|
86
|
+
h1: "[&_h1]:mt-5 [&_h1]:mb-2 [&_h1]:scroll-m-20 [&_h1]:font-heading [&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-foreground [&_h1]:first:mt-0",
|
|
87
|
+
h2: "[&_h2]:mt-4 [&_h2]:mb-2 [&_h2]:scroll-m-20 [&_h2]:font-heading [&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-foreground [&_h2]:first:mt-0",
|
|
88
|
+
h3: "[&_h3]:mt-4 [&_h3]:mb-1.5 [&_h3]:scroll-m-20 [&_h3]:font-heading [&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-foreground [&_h3]:first:mt-0",
|
|
89
|
+
h4: "[&_h4]:mt-3 [&_h4]:mb-1.5 [&_h4]:font-heading [&_h4]:text-sm [&_h4]:font-medium [&_h4]:text-foreground [&_h4]:first:mt-0",
|
|
90
|
+
h5: "[&_h5]:mt-3 [&_h5]:mb-1.5 [&_h5]:font-heading [&_h5]:text-sm [&_h5]:font-medium [&_h5]:text-foreground [&_h5]:first:mt-0",
|
|
91
|
+
h6: "[&_h6]:mt-3 [&_h6]:mb-1.5 [&_h6]:font-heading [&_h6]:text-sm [&_h6]:font-medium [&_h6]:text-foreground [&_h6]:first:mt-0",
|
|
92
|
+
// Body text is the app's body text — size, leading and ink inherit from the root, so a paragraph
|
|
93
|
+
// here is indistinguishable from any other `text-sm` paragraph in the product. No prose look.
|
|
94
|
+
p: "[&_p]:my-2 [&_p]:first:mt-0 [&_p]:last:mb-0",
|
|
95
|
+
// Marks. Links are `info` ink per design.md §Colours at body weight; `s` is Tiptap's strike
|
|
96
|
+
// element and `del` is GFM's — the same mark from two producers.
|
|
97
|
+
a: "[&_a]:text-info-text [&_a]:underline [&_a]:underline-offset-4 [&_a]:hover:text-info-text/88",
|
|
98
|
+
strong: "[&_strong]:font-semibold",
|
|
99
|
+
em: "[&_em]:italic",
|
|
100
|
+
del: "[&_del]:line-through [&_s]:line-through",
|
|
101
|
+
// Lists. Items and markers are body text: family, size and ink inherit (a `::marker` takes the
|
|
102
|
+
// item's font), so `1.` and `•` never read as a second typeface or a second colour. One thing
|
|
103
|
+
// does NOT inherit: the user-agent stylesheet gives `::marker` `font-variant-numeric:
|
|
104
|
+
// tabular-nums`, and Geist's tabular figures are fixed-width — that is what made ordered-list
|
|
105
|
+
// numbers look monospaced. `marker:normal-nums` restores the body's proportional figures. A GFM task
|
|
106
|
+
// list carries `contains-task-list` and its checkbox IS the marker, so the disc goes — expressed
|
|
107
|
+
// as a second, more specific descendant rule rather than a class on the element, which would
|
|
108
|
+
// lose the cascade (see the header).
|
|
109
|
+
ul: "[&_ul]:my-2 [&_ul]:ms-5 [&_ul]:list-disc [&_ul.contains-task-list]:list-none",
|
|
110
|
+
ol: "[&_ol]:my-2 [&_ol]:ms-5 [&_ol]:list-decimal",
|
|
111
|
+
li: "[&_li]:mt-1 [&_li]:marker:normal-nums [&_li]:marker:text-inherit [&_li_p]:my-0",
|
|
112
|
+
// Task lists, one shape for both producers: `MarkdownView` tags the GFM list
|
|
113
|
+
// `data-type="taskList"` and each item `data-type="taskItem"` with its body in a
|
|
114
|
+
// `data-slot="task-item-content"` box, which is exactly the DOM Tiptap's `TaskItem` node view
|
|
115
|
+
// renders — so the checkbox IS the marker, the body wraps beside it, and a nested list indents
|
|
116
|
+
// under the body in view and edit alike. The checkbox's hit area is trimmed to exactly 24px tall
|
|
117
|
+
// here (`after:-inset-y-1.25` — the pseudo insets from inside the 1px border — not its own 30px) and items sit 26px apart (`mt-1.5`), so each
|
|
118
|
+
// checkbox owns a whole 24px target with a hair to spare instead of reaching into its
|
|
119
|
+
// neighbour's.
|
|
120
|
+
taskList: "[&_ul[data-type=taskList]]:ms-0 [&_ul[data-type=taskList]]:list-none [&_li[data-type=taskItem]]:mt-1.5 [&_li[data-type=taskItem]]:flex [&_li[data-type=taskItem]]:items-start [&_li[data-type=taskItem]]:gap-2 [&_li[data-type=taskItem]_[data-slot=checkbox]]:mt-0.5 [&_li[data-type=taskItem]_[data-slot=checkbox]]:me-0 [&_li[data-type=taskItem]_[data-slot=checkbox]]:after:-inset-y-1.25 [&_[data-slot=task-item-content]]:min-w-0 [&_[data-slot=task-item-content]]:flex-1",
|
|
121
|
+
blockquote: "[&_blockquote]:my-2 [&_blockquote]:border-s-2 [&_blockquote]:border-border [&_blockquote]:ps-3",
|
|
122
|
+
// Inline code is a chip. Code inside a `pre` is not: it inherits the panel's ground, so the chip
|
|
123
|
+
// is undone at higher specificity (`[&_pre_code]` is (0,1,2) against the chip's (0,1,1)).
|
|
124
|
+
// Slack/Notion: a neutral grey chip with orange text (the syntax palette's literal colour), so
|
|
125
|
+
// inline code reads apart from prose in both themes; `tag-orange-text` on `muted` clears AA.
|
|
126
|
+
code: "[&_code]:rounded-sm [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-sm [&_code]:text-tag-orange-text",
|
|
127
|
+
// A bare `<pre>` wears `CodeBlock`'s surface — the same sunken panel, one vocabulary (B4-09).
|
|
128
|
+
// `CodeBlock`'s own `pre` is excluded: it already sits inside a `figure` carrying the border,
|
|
129
|
+
// radius and ground, and re-applying them here would draw a second panel inside the first.
|
|
130
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-2 [&_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",
|
|
131
|
+
preCode: "[&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:font-mono [&_pre_code]:text-sm [&_pre_code]:text-foreground",
|
|
132
|
+
hr: "[&_hr]:my-4 [&_hr]:border-border",
|
|
133
|
+
// GFM tables, Notion's simple table: a rounded outer border, a rule between every cell, and a
|
|
134
|
+
// header row on a subtle muted ground at medium weight. The scroll container is structural and
|
|
135
|
+
// belongs to the consumer (MarkdownView and TextEdit each wrap the table in an `overflow-x-auto`
|
|
136
|
+
// box); these are the cell and rule tokens. `border-separate` with zero spacing is what lets the
|
|
137
|
+
// table itself take the radius (a collapsed table cannot); each cell draws only its bottom and
|
|
138
|
+
// end rule, the last row and column drop theirs against the outer border, and the corner cells
|
|
139
|
+
// take the radius so a header or selected fill never pokes past the curve. Cells take
|
|
140
|
+
// `break-word`, not the root's `anywhere`, so a column keeps its words whole and the table scrolls
|
|
141
|
+
// in its box rather than crushing to one character per line.
|
|
142
|
+
table: "[&_table]:w-full [&_table]:border-separate [&_table]:border-spacing-0 [&_table]:rounded-lg [&_table]:border [&_table]:border-border",
|
|
143
|
+
tableRules: "[&_th]:border-e [&_th]:border-b [&_th]:border-border [&_td]:border-e [&_td]:border-b [&_td]:border-border [&_tr>*:last-child]:border-e-0 [&_tbody>tr:last-child>*]:border-b-0 [&_tr:first-child>*:first-child]:rounded-ss-lg [&_tr:first-child>*:last-child]:rounded-se-lg [&_tbody>tr:last-child>*:first-child]:rounded-es-lg [&_tbody>tr:last-child>*:last-child]:rounded-ee-lg",
|
|
144
|
+
tableCells: "[&_th]:bg-muted/50 [&_th]:px-3 [&_th]:py-2 [&_th]:text-start [&_th]:align-top [&_th]:font-medium [&_td]:px-3 [&_td]:py-2 [&_td]:align-top [&_td_p]:my-0 [&_th_p]:my-0 [&_th]:wrap-break-word [&_td]:wrap-break-word",
|
|
145
|
+
img: "[&_img]:my-2 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
|
|
146
|
+
};
|
|
147
|
+
var proseClassName = Object.values(prose).join(" ");
|
|
148
|
+
var proseDocument = {
|
|
149
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
150
|
+
root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5",
|
|
151
|
+
// Headings: semibold (the base recipe's weight), more room above than below. The first block
|
|
152
|
+
// keeps `first:mt-0` from the base recipe. `scroll-mt-18` clears a 56px sticky header + 16.
|
|
153
|
+
h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8",
|
|
154
|
+
h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7",
|
|
155
|
+
h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7",
|
|
156
|
+
h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5",
|
|
157
|
+
// A 12px gap between paragraphs; none before the first or after the last.
|
|
158
|
+
p: "[&_p]:my-3",
|
|
159
|
+
// Lists indent 24, items 4 apart, a nested list 4 below its item's text.
|
|
160
|
+
ul: "[&_ul]:my-3 [&_ul]:ms-6",
|
|
161
|
+
ol: "[&_ol]:my-3 [&_ol]:ms-6",
|
|
162
|
+
li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0",
|
|
163
|
+
// A quote is a rule and an indent, never italic; blocks breathe 16 apart.
|
|
164
|
+
blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4",
|
|
165
|
+
// No orange in documents: inline code is a grey chip in the body's own ink.
|
|
166
|
+
code: "[&_code]:text-foreground",
|
|
167
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4",
|
|
168
|
+
hr: "[&_hr]:my-6",
|
|
169
|
+
img: "[&_img]:my-4",
|
|
170
|
+
// Tables read at 14/20 at every pointer, 16 from the blocks around them (the scroll box is the
|
|
171
|
+
// consumer's: `MarkdownView`'s `markdown-table`, the editor's `.tableWrapper`).
|
|
172
|
+
table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4",
|
|
173
|
+
// Callouts, toggles, code blocks and media sit 16 from their neighbours; a toggle's summary is
|
|
174
|
+
// a 24px row, 44px on a coarse pointer.
|
|
175
|
+
blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11"
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/index.ts
|
|
58
179
|
var twMerge = import_tailwind_merge.twMerge;
|
|
59
180
|
function cn(...inputs) {
|
|
60
181
|
return twMerge((0, import_clsx.clsx)(inputs));
|
|
61
182
|
}
|
|
183
|
+
var proseDocumentClassName = cn(
|
|
184
|
+
proseClassName,
|
|
185
|
+
Object.values(proseDocument).join(" ")
|
|
186
|
+
);
|
|
62
187
|
|
|
63
188
|
// src/icons/brand-icon.tsx
|
|
64
189
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
package/dist/icons/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,9 @@ __export(src_exports, {
|
|
|
25
25
|
cn: () => cn,
|
|
26
26
|
mergeRefs: () => mergeRefs,
|
|
27
27
|
prose: () => prose,
|
|
28
|
-
proseClassName: () => proseClassName
|
|
28
|
+
proseClassName: () => proseClassName,
|
|
29
|
+
proseDocument: () => proseDocument,
|
|
30
|
+
proseDocumentClassName: () => proseDocumentClassName
|
|
29
31
|
});
|
|
30
32
|
module.exports = __toCommonJS(src_exports);
|
|
31
33
|
var import_clsx = require("clsx");
|
|
@@ -120,6 +122,35 @@ var prose = {
|
|
|
120
122
|
img: "[&_img]:my-2 [&_img]:max-w-full [&_img]:rounded-lg [&_img]:border [&_img]:border-border"
|
|
121
123
|
};
|
|
122
124
|
var proseClassName = Object.values(prose).join(" ");
|
|
125
|
+
var proseDocument = {
|
|
126
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
127
|
+
root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5",
|
|
128
|
+
// Headings: semibold (the base recipe's weight), more room above than below. The first block
|
|
129
|
+
// keeps `first:mt-0` from the base recipe. `scroll-mt-18` clears a 56px sticky header + 16.
|
|
130
|
+
h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8",
|
|
131
|
+
h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7",
|
|
132
|
+
h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7",
|
|
133
|
+
h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5",
|
|
134
|
+
// A 12px gap between paragraphs; none before the first or after the last.
|
|
135
|
+
p: "[&_p]:my-3",
|
|
136
|
+
// Lists indent 24, items 4 apart, a nested list 4 below its item's text.
|
|
137
|
+
ul: "[&_ul]:my-3 [&_ul]:ms-6",
|
|
138
|
+
ol: "[&_ol]:my-3 [&_ol]:ms-6",
|
|
139
|
+
li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0",
|
|
140
|
+
// A quote is a rule and an indent, never italic; blocks breathe 16 apart.
|
|
141
|
+
blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4",
|
|
142
|
+
// No orange in documents: inline code is a grey chip in the body's own ink.
|
|
143
|
+
code: "[&_code]:text-foreground",
|
|
144
|
+
pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4",
|
|
145
|
+
hr: "[&_hr]:my-6",
|
|
146
|
+
img: "[&_img]:my-4",
|
|
147
|
+
// Tables read at 14/20 at every pointer, 16 from the blocks around them (the scroll box is the
|
|
148
|
+
// consumer's: `MarkdownView`'s `markdown-table`, the editor's `.tableWrapper`).
|
|
149
|
+
table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4",
|
|
150
|
+
// Callouts, toggles, code blocks and media sit 16 from their neighbours; a toggle's summary is
|
|
151
|
+
// a 24px row, 44px on a coarse pointer.
|
|
152
|
+
blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11"
|
|
153
|
+
};
|
|
123
154
|
|
|
124
155
|
// src/index.ts
|
|
125
156
|
var twMerge = import_tailwind_merge.twMerge;
|
|
@@ -161,6 +192,10 @@ var FLOATING = {
|
|
|
161
192
|
sideOffsetDetached: 8,
|
|
162
193
|
collisionPadding: 8
|
|
163
194
|
};
|
|
195
|
+
var proseDocumentClassName = cn(
|
|
196
|
+
proseClassName,
|
|
197
|
+
Object.values(proseDocument).join(" ")
|
|
198
|
+
);
|
|
164
199
|
function mergeRefs(...refs) {
|
|
165
200
|
return (node) => {
|
|
166
201
|
const cleanups = refs.map((ref) => {
|
|
@@ -198,5 +233,7 @@ function mergeRefs(...refs) {
|
|
|
198
233
|
cn,
|
|
199
234
|
mergeRefs,
|
|
200
235
|
prose,
|
|
201
|
-
proseClassName
|
|
236
|
+
proseClassName,
|
|
237
|
+
proseDocument,
|
|
238
|
+
proseDocumentClassName
|
|
202
239
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -96,6 +96,45 @@ type ProseElement = keyof typeof prose;
|
|
|
96
96
|
* string that never changes.
|
|
97
97
|
*/
|
|
98
98
|
declare const proseClassName: string;
|
|
99
|
+
/**
|
|
100
|
+
* THE document type scale — `typeScale="document"` on `MarkdownView` and `TextEdit` (TYP-20, MK
|
|
101
|
+
* 2026-10-14, Regent Pages v2 Round 2). A page read as a document: calm 14/24 body text on a fine
|
|
102
|
+
* pointer, 16/26 on a coarse pointer or a narrow window (the same 16px INT-13 already gives a
|
|
103
|
+
* touch editor, so reading and editing never jump and iOS never zooms), a 12px paragraph gap,
|
|
104
|
+
* and headings H1 24 · H2 20 · H3 16 with more room above than below. On 16px body text H3 steps
|
|
105
|
+
* up to 18 and H4 to 16, so a heading never sits at the body's own size.
|
|
106
|
+
*
|
|
107
|
+
* It is an OVERLAY on `prose`, never a replacement: compose it after the base recipe through
|
|
108
|
+
* `cn` (tailwind-merge resolves each `[&_h1]:text-lg` against its `[&_h1]:text-2xl/8`), or use
|
|
109
|
+
* `proseDocumentClassName`, which is that composition done once.
|
|
110
|
+
*
|
|
111
|
+
* The measure (about 67 characters a line) is the layout's, not the recipe's: `DocumentLayout`
|
|
112
|
+
* caps its text column at `--document-measure` (47ch), in the same font size this recipe sets.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* <div className={cn(proseClassName, proseDocument.root, proseDocument.h1)} />
|
|
116
|
+
*/
|
|
117
|
+
declare const proseDocument: {
|
|
118
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
119
|
+
readonly root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5";
|
|
120
|
+
readonly h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8";
|
|
121
|
+
readonly h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7";
|
|
122
|
+
readonly h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7";
|
|
123
|
+
readonly h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5";
|
|
124
|
+
readonly p: "[&_p]:my-3";
|
|
125
|
+
readonly ul: "[&_ul]:my-3 [&_ul]:ms-6";
|
|
126
|
+
readonly ol: "[&_ol]:my-3 [&_ol]:ms-6";
|
|
127
|
+
readonly li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0";
|
|
128
|
+
readonly blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4";
|
|
129
|
+
readonly code: "[&_code]:text-foreground";
|
|
130
|
+
readonly pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4";
|
|
131
|
+
readonly hr: "[&_hr]:my-6";
|
|
132
|
+
readonly img: "[&_img]:my-4";
|
|
133
|
+
readonly table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4";
|
|
134
|
+
readonly blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11";
|
|
135
|
+
};
|
|
136
|
+
/** The element roles the document overlay covers. */
|
|
137
|
+
type ProseDocumentElement = keyof typeof proseDocument;
|
|
99
138
|
|
|
100
139
|
/**
|
|
101
140
|
* Merges Tailwind CSS class names with intelligent conflict resolution.
|
|
@@ -180,6 +219,16 @@ declare const FLOATING: {
|
|
|
180
219
|
readonly collisionPadding: 8;
|
|
181
220
|
};
|
|
182
221
|
|
|
222
|
+
/**
|
|
223
|
+
* The document type scale as one class string: the base `prose` recipe with the `proseDocument`
|
|
224
|
+
* overlay merged over it (TYP-20) — what `MarkdownView` and `TextEdit` wear with
|
|
225
|
+
* `typeScale="document"`. Merged once here, through `cn`, so every `[&_h1]:text-lg` of the base
|
|
226
|
+
* recipe yields to its document value and nothing pays for a `tailwind-merge` pass per render.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* <article className={proseDocumentClassName}>…</article>
|
|
230
|
+
*/
|
|
231
|
+
declare const proseDocumentClassName: string;
|
|
183
232
|
/**
|
|
184
233
|
* Fan one DOM node out to several refs — a forwarded `ref` prop plus one or more internal
|
|
185
234
|
* refs — as a single ref callback. Skips `null`/`undefined` entries, so an optional
|
|
@@ -210,4 +259,4 @@ declare const FLOATING: {
|
|
|
210
259
|
*/
|
|
211
260
|
declare function mergeRefs<T>(...refs: Array<React.Ref<T> | null | undefined>): React.RefCallback<T>;
|
|
212
261
|
|
|
213
|
-
export { FLOATING, type ProseElement, TIMINGS, cn, mergeRefs, prose, proseClassName };
|
|
262
|
+
export { FLOATING, type ProseDocumentElement, type ProseElement, TIMINGS, cn, mergeRefs, prose, proseClassName, proseDocument, proseDocumentClassName };
|
package/dist/index.d.ts
CHANGED
|
@@ -96,6 +96,45 @@ type ProseElement = keyof typeof prose;
|
|
|
96
96
|
* string that never changes.
|
|
97
97
|
*/
|
|
98
98
|
declare const proseClassName: string;
|
|
99
|
+
/**
|
|
100
|
+
* THE document type scale — `typeScale="document"` on `MarkdownView` and `TextEdit` (TYP-20, MK
|
|
101
|
+
* 2026-10-14, Regent Pages v2 Round 2). A page read as a document: calm 14/24 body text on a fine
|
|
102
|
+
* pointer, 16/26 on a coarse pointer or a narrow window (the same 16px INT-13 already gives a
|
|
103
|
+
* touch editor, so reading and editing never jump and iOS never zooms), a 12px paragraph gap,
|
|
104
|
+
* and headings H1 24 · H2 20 · H3 16 with more room above than below. On 16px body text H3 steps
|
|
105
|
+
* up to 18 and H4 to 16, so a heading never sits at the body's own size.
|
|
106
|
+
*
|
|
107
|
+
* It is an OVERLAY on `prose`, never a replacement: compose it after the base recipe through
|
|
108
|
+
* `cn` (tailwind-merge resolves each `[&_h1]:text-lg` against its `[&_h1]:text-2xl/8`), or use
|
|
109
|
+
* `proseDocumentClassName`, which is that composition done once.
|
|
110
|
+
*
|
|
111
|
+
* The measure (about 67 characters a line) is the layout's, not the recipe's: `DocumentLayout`
|
|
112
|
+
* caps its text column at `--document-measure` (47ch), in the same font size this recipe sets.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* <div className={cn(proseClassName, proseDocument.root, proseDocument.h1)} />
|
|
116
|
+
*/
|
|
117
|
+
declare const proseDocument: {
|
|
118
|
+
/** Body: 14/24 on a fine pointer, 16/26 on a coarse pointer or below the `sm` width. */
|
|
119
|
+
readonly root: "text-sm/6 pointer-coarse:text-base/6.5 max-sm:text-base/6.5";
|
|
120
|
+
readonly h1: "[&_h1]:mt-8 [&_h1]:mb-3 [&_h1]:scroll-mt-18 [&_h1]:text-2xl/8";
|
|
121
|
+
readonly h2: "[&_h2]:mt-7 [&_h2]:mb-2 [&_h2]:scroll-mt-18 [&_h2]:text-xl/7";
|
|
122
|
+
readonly h3: "[&_h3]:mt-6 [&_h3]:mb-1.5 [&_h3]:scroll-mt-18 [&_h3]:text-base/6 pointer-coarse:[&_h3]:text-lg/7 max-sm:[&_h3]:text-lg/7";
|
|
123
|
+
readonly h4: "[&_h4]:mt-5 [&_h4]:mb-1 [&_h4]:scroll-mt-18 [&_h4]:text-sm/6 [&_h4]:font-semibold pointer-coarse:[&_h4]:text-base/6.5 max-sm:[&_h4]:text-base/6.5";
|
|
124
|
+
readonly p: "[&_p]:my-3";
|
|
125
|
+
readonly ul: "[&_ul]:my-3 [&_ul]:ms-6";
|
|
126
|
+
readonly ol: "[&_ol]:my-3 [&_ol]:ms-6";
|
|
127
|
+
readonly li: "[&_li_ul]:mt-1 [&_li_ul]:mb-0 [&_li_ol]:mt-1 [&_li_ol]:mb-0";
|
|
128
|
+
readonly blockquote: "[&_blockquote]:my-4 [&_blockquote]:ps-4";
|
|
129
|
+
readonly code: "[&_code]:text-foreground";
|
|
130
|
+
readonly pre: "[&_pre:not([data-slot='code-block-pre'])]:my-4";
|
|
131
|
+
readonly hr: "[&_hr]:my-6";
|
|
132
|
+
readonly img: "[&_img]:my-4";
|
|
133
|
+
readonly table: "[&_th]:text-sm/5 [&_td]:text-sm/5 [&_[data-slot=markdown-table]]:my-4 [&_.tableWrapper]:my-4";
|
|
134
|
+
readonly blocks: "[&_[data-slot=callout]]:my-4 [&_[data-slot=code-block]]:my-4 [&_details]:my-4 [&_video]:my-4 [&_audio]:my-4 [&_summary]:min-h-6 pointer-coarse:[&_summary]:min-h-11";
|
|
135
|
+
};
|
|
136
|
+
/** The element roles the document overlay covers. */
|
|
137
|
+
type ProseDocumentElement = keyof typeof proseDocument;
|
|
99
138
|
|
|
100
139
|
/**
|
|
101
140
|
* Merges Tailwind CSS class names with intelligent conflict resolution.
|
|
@@ -180,6 +219,16 @@ declare const FLOATING: {
|
|
|
180
219
|
readonly collisionPadding: 8;
|
|
181
220
|
};
|
|
182
221
|
|
|
222
|
+
/**
|
|
223
|
+
* The document type scale as one class string: the base `prose` recipe with the `proseDocument`
|
|
224
|
+
* overlay merged over it (TYP-20) — what `MarkdownView` and `TextEdit` wear with
|
|
225
|
+
* `typeScale="document"`. Merged once here, through `cn`, so every `[&_h1]:text-lg` of the base
|
|
226
|
+
* recipe yields to its document value and nothing pays for a `tailwind-merge` pass per render.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* <article className={proseDocumentClassName}>…</article>
|
|
230
|
+
*/
|
|
231
|
+
declare const proseDocumentClassName: string;
|
|
183
232
|
/**
|
|
184
233
|
* Fan one DOM node out to several refs — a forwarded `ref` prop plus one or more internal
|
|
185
234
|
* refs — as a single ref callback. Skips `null`/`undefined` entries, so an optional
|
|
@@ -210,4 +259,4 @@ declare const FLOATING: {
|
|
|
210
259
|
*/
|
|
211
260
|
declare function mergeRefs<T>(...refs: Array<React.Ref<T> | null | undefined>): React.RefCallback<T>;
|
|
212
261
|
|
|
213
|
-
export { FLOATING, type ProseElement, TIMINGS, cn, mergeRefs, prose, proseClassName };
|
|
262
|
+
export { FLOATING, type ProseDocumentElement, type ProseElement, TIMINGS, cn, mergeRefs, prose, proseClassName, proseDocument, proseDocumentClassName };
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,17 @@ import {
|
|
|
4
4
|
cn,
|
|
5
5
|
mergeRefs,
|
|
6
6
|
prose,
|
|
7
|
-
proseClassName
|
|
8
|
-
|
|
7
|
+
proseClassName,
|
|
8
|
+
proseDocument,
|
|
9
|
+
proseDocumentClassName
|
|
10
|
+
} from "./chunk-DG7GQHEH.js";
|
|
9
11
|
export {
|
|
10
12
|
FLOATING,
|
|
11
13
|
TIMINGS,
|
|
12
14
|
cn,
|
|
13
15
|
mergeRefs,
|
|
14
16
|
prose,
|
|
15
|
-
proseClassName
|
|
17
|
+
proseClassName,
|
|
18
|
+
proseDocument,
|
|
19
|
+
proseDocumentClassName
|
|
16
20
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vegastack/design",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.12",
|
|
4
4
|
"description": "VegaStack design system — cn utility, icon runtime, Tailwind v4 preset, and the vegastack-design CLI (tokens ship separately as @vegastack/design-tokens)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"test": "node test/compare.test.mjs && node test/check-updates.test.mjs && node test/skills-install.test.mjs && node test/doctor.test.mjs && node --test test/merge-refs.test.mjs test/registry-credentials.test.mjs"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@vegastack/design-tokens": "^0.8.
|
|
73
|
+
"@vegastack/design-tokens": "^0.8.12",
|
|
74
74
|
"clsx": "^2.1.1",
|
|
75
75
|
"tailwind-merge": "^3.6.0",
|
|
76
76
|
"tsconfig-paths": "^4.2.0",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<!-- GENERATED — do not hand-edit. Regenerated from the design system's component contract,
|
|
4
4
|
which is the authority for membership and counts. -->
|
|
5
5
|
|
|
6
|
-
**
|
|
6
|
+
**161 components**, plus 467 animated-icon items, 15 hooks (`use-animation-replay`, `use-announcer`, `use-async-search`, `use-drag-reorder`, `use-file-drop`, `use-inline-edit`, `use-list-nav`, `use-media-query`, `use-mobile`, `use-modal-inert`, `use-optimistic-action`, `use-overflow`, `use-platform`, `use-tabs-swipe`, `use-view-transition`), 15 starter blocks (`app-shell-01`, `board-01`, `issue-detail-01`, `page-editor-01`, `command-search-01`, `list-page-01`, `library-01`, `login-01`, `notifications-01`, `review-split-01`, `settings-01`, `settings-02`, `status-pages-01`, `email-kit`, `share-01`), 68 chart blocks across 7 families, and 19 data libs (`code-highlight`, `date-time`, `geo-data`, `emoji-data`, `drag-item`, `text-anchor`, `text-anchor-doc`, `text-edit-grammar`, `text-edit-schema`, `text-edit-markdown`, `file-kind`, `upload-progress`, `media-probe`, `page-layout`, `tile-overlay`, `icon-data`, `icon-components`, `picker-search`, `picker-preferences`) — 745 registry items in total.
|
|
7
7
|
|
|
8
8
|
Install any of them with `shadcn add @vegastack/<name>`. Animated icons install as
|
|
9
9
|
`@vegastack/icon-<name>`; the bare name is reserved for components, so a component whose name
|
|
@@ -82,7 +82,7 @@ starts with `icon-` is a component and never an icon.
|
|
|
82
82
|
- **`inline-chip`** — The one inline reference in running text — a person, page, file, task, meeting, customer or project — on the text's baseline at its size, tinted by kind; a person previews avatar, name and email on hover, the rest open on click with ⌘-click for a new tab.
|
|
83
83
|
- **`item`** — A composable row for list and feed content — media, title, description, actions — with a highlighted flash for a just-changed row.
|
|
84
84
|
- **`kbd`** — A keyboard-key chip, and a group that lays several of them out inline.
|
|
85
|
-
- **`markdown-view`** — Render a markdown string to safe, token-styled HTML — headings (with optional ids), lists, code, blockquotes, links, GFM tables, mention and file chips, callouts and toggles — XSS-safe,
|
|
85
|
+
- **`markdown-view`** — Render a markdown string to safe, token-styled HTML — headings (with optional ids and copy links), lists, code, blockquotes, links, GFM tables that fade at a scrolling edge, mention and file chips, callouts and toggles — XSS-safe; at the document type scale, a page's read view with comment highlights, an outline, per-reader toggles and find.
|
|
86
86
|
- **`priority-icon`** — A flag marking priority — urgent, high, medium, low, none — each in a semantic color with filled, outline or dashed fill.
|
|
87
87
|
- **`relative-time`** — One Intl-based dates & times module — formatRelative, formatDuration, formatDate, formatDateTime, formatDateRange, formatTimeOfDay, formatDueLabel, groupByDay, time-zone cookie + provider — and the RelativeTime, DateTime, Duration and DueLabel components with absolute-time tooltips.
|
|
88
88
|
- **`status-icon`** — A small workflow status icon in Linear's set — backlog, todo, in progress, in review, done, canceled, duplicate, triage — each a hand-drawn 16-unit glyph in a semantic color.
|
|
@@ -165,6 +165,7 @@ starts with `icon-` is a component and never an icon.
|
|
|
165
165
|
- **`aspect-ratio`** — Constrains its children to a given width-to-height ratio.
|
|
166
166
|
- **`board`** — Kanban lanes — full-height lanes that scroll their cards inside, sticky headers with a collapse button left of the ⋯ menu, a subtle top-down fade on each lane, + Add after the last card (the empty lane's action when it has none), Nothing here / Drop here empty zones, per-lane skeletons and load-on-scroll paging; live pointer and touch drag (lift, make room, settle, edge auto-scroll), a keyboard pick-up/move/drop model, a per-card ⋯ menu of the card's own actions, optimistic moves with rollback and a toast, and one lane at a time on a phone.
|
|
167
167
|
- **`direction`** — Base UI's DirectionProvider and useDirection — the text-direction context components read.
|
|
168
|
+
- **`document-layout`** — A page read as a document — the title area, the text at a reading measure, what follows it, a contents column and a comment margin — on one grid with four tiers by its own width, plus its skeleton and a tier hook.
|
|
168
169
|
- **`record-layout`** — A record page's main column beside a sticky right rail of cards, with an ⓘ Details sheet in its place on small screens.
|
|
169
170
|
- **`resizable`** — Accessible resizable panel groups and layouts with keyboard support — horizontal or vertical, nestable, with an optional visible grip.
|
|
170
171
|
- **`scroll-area`** — Augments native scroll functionality for custom, cross-browser styling — a viewport, an auto-hiding scrollbar, and a corner.
|