@nuucognition/ncm-ui 0.1.0-dev.1 → 0.1.1-beta.1
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/README.md +90 -0
- package/dist/blocks/admonition/index.d.ts +2 -3
- package/dist/blocks/admonition/index.js +79 -23
- package/dist/blocks/aside/index.d.ts +2 -3
- package/dist/blocks/aside/index.js +79 -23
- package/dist/blocks/attribution/index.d.ts +2 -3
- package/dist/blocks/blockquote/index.d.ts +5 -4
- package/dist/blocks/blockquote/index.js +52 -7
- package/dist/blocks/chart/index.d.ts +2 -3
- package/dist/blocks/chart/index.js +2 -1
- package/dist/blocks/code/index.d.ts +2 -3
- package/dist/blocks/code/index.js +2 -2
- package/dist/blocks/container/index.d.ts +2 -3
- package/dist/blocks/container/index.js +50 -5
- package/dist/blocks/custom-code/index.d.ts +2 -3
- package/dist/blocks/custom-code/index.js +1 -1
- package/dist/blocks/dataview/index.d.ts +2 -3
- package/dist/blocks/dataview/index.js +2 -1
- package/dist/blocks/definition/index.d.ts +2 -3
- package/dist/blocks/definition/index.js +79 -23
- package/dist/blocks/embed/index.d.ts +2 -3
- package/dist/blocks/embedding/index.d.ts +2 -3
- package/dist/blocks/embedding/index.js +50 -5
- package/dist/blocks/figure/index.d.ts +2 -3
- package/dist/blocks/figure/index.js +50 -5
- package/dist/blocks/footnote/index.d.ts +2 -3
- package/dist/blocks/footnote/index.js +79 -23
- package/dist/blocks/frontmatter/index.d.ts +2 -3
- package/dist/blocks/header/index.d.ts +2 -3
- package/dist/blocks/header/index.js +50 -5
- package/dist/blocks/horizontal-rule/index.d.ts +2 -3
- package/dist/blocks/html/index.d.ts +3 -4
- package/dist/blocks/html/index.js +2 -1
- package/dist/blocks/index.d.ts +1 -2
- package/dist/blocks/index.js +79 -23
- package/dist/blocks/latex/index.d.ts +2 -3
- package/dist/blocks/latex/index.js +2 -2
- package/dist/blocks/link/index.d.ts +2 -3
- package/dist/blocks/list/index.d.ts +2 -3
- package/dist/blocks/list/index.js +57 -7
- package/dist/blocks/math/index.d.ts +2 -3
- package/dist/blocks/math/index.js +3 -2
- package/dist/blocks/mermaid/index.d.ts +2 -3
- package/dist/blocks/mermaid/index.js +2 -1
- package/dist/blocks/page-breaker/index.d.ts +2 -3
- package/dist/blocks/paragraph/index.d.ts +2 -3
- package/dist/blocks/paragraph/index.js +50 -5
- package/dist/blocks/spoiler/index.d.ts +2 -3
- package/dist/blocks/spoiler/index.js +79 -23
- package/dist/blocks/table/index.d.ts +2 -3
- package/dist/blocks/table/index.js +51 -6
- package/dist/blocks/task-list/index.d.ts +2 -3
- package/dist/blocks/task-list/index.js +52 -6
- package/dist/components/index.d.ts +34 -4
- package/dist/components/index.js +117 -25
- package/dist/components/ncm-block.d.ts +2 -3
- package/dist/components/ncm-block.js +79 -23
- package/dist/components/ncm-document.d.ts +4 -4
- package/dist/components/ncm-document.js +79 -23
- package/dist/context/index.d.ts +2 -3
- package/dist/hooks/index.d.ts +1 -2
- package/dist/hooks/index.js +79 -23
- package/dist/hooks/use-block-renderer.js +79 -23
- package/dist/hooks/use-ncm-config.d.ts +1 -2
- package/dist/index.d.ts +3 -4
- package/dist/index.js +118 -26
- package/dist/inline/index.d.ts +4 -4
- package/dist/inline/index.js +51 -6
- package/dist/lib/defaults.js +79 -23
- package/dist/{references-Bs5wJybr.d.ts → references-BYW5pnj_.d.ts} +4 -4
- package/dist/styles/nuu.css +329 -44
- package/dist/styles/paper.css +62 -1
- package/dist/{use-ncm-config-D0doMYTH.d.ts → use-ncm-config-CnntcShj.d.ts} +55 -4
- package/package.json +5 -5
package/dist/styles/nuu.css
CHANGED
|
@@ -8,10 +8,25 @@
|
|
|
8
8
|
* Selectors target the data attributes emitted by ncm-ui block components.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/*
|
|
12
|
+
* Read mode and edit mode are ONE document at two moments, so they render at
|
|
13
|
+
* one size. The base and the heading ladder below are copied from the editor's
|
|
14
|
+
* own scale (`@nuucognition/nuu-editor`, `src/nuu-editor/nuu-editor.scss`):
|
|
15
|
+
* 1rem body at 1.65, headings 1.75 / 1.56 / 1.39 / 1.24 / 1.1em. Switching
|
|
16
|
+
* view must not resize a single glyph. Since the flow-block rhythm pass, the
|
|
17
|
+
* MARGINS are part of the same contract: the editor states this file's block
|
|
18
|
+
* gaps (1rem between siblings, per-level rem heading margins, the 1.5rem /
|
|
19
|
+
* 0.125rem list geometry) per element on its side. If one side of that pair
|
|
20
|
+
* moves, move the other in the same change.
|
|
21
|
+
*
|
|
22
|
+
* `--surf-reading-scale` is the reader's own text-size setting and stays on
|
|
23
|
+
* the base alone; everything under it is expressed in `em`, so one multiply
|
|
24
|
+
* carries the whole document.
|
|
25
|
+
*/
|
|
11
26
|
[data-ncm-document].ncm-theme-nuu {
|
|
12
27
|
font-family: var(--font-sans);
|
|
13
|
-
font-size: calc(
|
|
14
|
-
line-height: 1.
|
|
28
|
+
font-size: calc(1rem * var(--surf-reading-scale, 1));
|
|
29
|
+
line-height: 1.65;
|
|
15
30
|
color: var(--foreground);
|
|
16
31
|
}
|
|
17
32
|
|
|
@@ -19,7 +34,7 @@
|
|
|
19
34
|
margin-top: 1rem;
|
|
20
35
|
}
|
|
21
36
|
|
|
22
|
-
/* Headings —
|
|
37
|
+
/* Headings — the editor ladder: one 1.12 ratio, h5 a clear step above body */
|
|
23
38
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"] {
|
|
24
39
|
font-family: var(--font-heading);
|
|
25
40
|
color: var(--foreground);
|
|
@@ -28,10 +43,10 @@
|
|
|
28
43
|
}
|
|
29
44
|
|
|
30
45
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"][data-ncm-level="1"] {
|
|
31
|
-
font-size:
|
|
32
|
-
line-height:
|
|
33
|
-
letter-spacing: -0.
|
|
34
|
-
font-weight:
|
|
46
|
+
font-size: 1.75em;
|
|
47
|
+
line-height: 1.3;
|
|
48
|
+
letter-spacing: -0.01em;
|
|
49
|
+
font-weight: 700;
|
|
35
50
|
margin-top: 1.5rem;
|
|
36
51
|
}
|
|
37
52
|
|
|
@@ -40,41 +55,105 @@
|
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"][data-ncm-level="2"] {
|
|
43
|
-
font-size:
|
|
44
|
-
line-height:
|
|
45
|
-
letter-spacing: -0.
|
|
46
|
-
font-weight:
|
|
58
|
+
font-size: 1.56em;
|
|
59
|
+
line-height: 1.3;
|
|
60
|
+
letter-spacing: -0.01em;
|
|
61
|
+
font-weight: 660;
|
|
47
62
|
margin-top: 1.25rem;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"][data-ncm-level="3"] {
|
|
51
|
-
font-size:
|
|
52
|
-
line-height: 1.
|
|
53
|
-
|
|
54
|
-
font-weight: 400;
|
|
66
|
+
font-size: 1.39em;
|
|
67
|
+
line-height: 1.3;
|
|
68
|
+
font-weight: 620;
|
|
55
69
|
margin-top: 1rem;
|
|
56
70
|
}
|
|
57
71
|
|
|
72
|
+
/* h4/h5 open at 1.25rem, above the 1rem gap that follows them: a heading must
|
|
73
|
+
sit closer to the section it introduces than to the text it ends. At the
|
|
74
|
+
old 0.75rem the binding was inverted. */
|
|
58
75
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"][data-ncm-level="4"] {
|
|
59
|
-
font-size:
|
|
60
|
-
line-height: 1.
|
|
61
|
-
font-weight:
|
|
62
|
-
margin-top:
|
|
76
|
+
font-size: 1.24em;
|
|
77
|
+
line-height: 1.3;
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
margin-top: 1.25rem;
|
|
63
80
|
}
|
|
64
81
|
|
|
65
82
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="header"][data-ncm-level="5"] {
|
|
66
|
-
font-size:
|
|
67
|
-
line-height:
|
|
68
|
-
font-weight:
|
|
69
|
-
|
|
70
|
-
text-transform: uppercase;
|
|
71
|
-
margin-top: 0.75rem;
|
|
83
|
+
font-size: 1.1em;
|
|
84
|
+
line-height: 1.3;
|
|
85
|
+
font-weight: 600;
|
|
86
|
+
margin-top: 1.25rem;
|
|
72
87
|
}
|
|
73
88
|
|
|
74
89
|
/* Paragraph */
|
|
75
90
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="paragraph"] {
|
|
76
91
|
color: var(--foreground);
|
|
77
|
-
line-height: 1.
|
|
92
|
+
line-height: 1.65;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* Callout content keeps its line breaks. NCM parses a callout's quoted lines
|
|
97
|
+
* into paragraph content WITH the newlines preserved ("line one\nline two"),
|
|
98
|
+
* and default HTML whitespace collapsing was rendering them as one
|
|
99
|
+
* space-joined line — an author who wrote three lines in a callout saw one.
|
|
100
|
+
* Scoped to admonitions: everywhere else soft-wrapped source keeps its
|
|
101
|
+
* CommonMark space-join.
|
|
102
|
+
*/
|
|
103
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-admonition] [data-ncm-type="paragraph"] {
|
|
104
|
+
white-space: pre-wrap;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Callout (admonition) — a quiet card: rounded `md` corners (the NUU chrome
|
|
109
|
+
* step, stated as radius × 0.8 so a host's `--radius` carries through), 1px
|
|
110
|
+
* hairline border, a 2px colored left edge (the blockquote's own weight),
|
|
111
|
+
* tight padding. Rounded since (Task) 581, superseding the sharp-corner line
|
|
112
|
+
* of the minimalist pass — everything else from that pass stands. The type
|
|
113
|
+
* supplies only colors, through the `--ncm-callout-*` hooks; a host assigns
|
|
114
|
+
* them per `data-ncm-admonition-type` (Onyx does, from its palette
|
|
115
|
+
* families). Unset, every hook falls back to the neutral hairline card, so
|
|
116
|
+
* a host with no callout stylesheet — and any type a host does not cover —
|
|
117
|
+
* renders the same quiet shell with no color.
|
|
118
|
+
*
|
|
119
|
+
* These rules override the component's own rounded-card utilities
|
|
120
|
+
* (`rounded-lg bg-card p-4`): this file is unlayered and Tailwind utilities
|
|
121
|
+
* are layered, so the unlayered declarations win regardless of specificity.
|
|
122
|
+
* The hooks are set by hosts at ANY specificity — this file deliberately
|
|
123
|
+
* never assigns them, only reads them with fallbacks.
|
|
124
|
+
*/
|
|
125
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-admonition] {
|
|
126
|
+
border: 1px solid var(--ncm-callout-border, var(--border));
|
|
127
|
+
border-left: 2px solid var(--ncm-callout-edge, var(--border));
|
|
128
|
+
border-radius: calc(var(--radius, 0.625rem) * 0.8);
|
|
129
|
+
padding: 0.625rem 0.875rem;
|
|
130
|
+
background-color: var(--ncm-callout-tint, transparent);
|
|
131
|
+
/*
|
|
132
|
+
* An unbroken word must stay inside the card. Hosts lay the title out as a
|
|
133
|
+
* flex row (glyph + text), and a flex item's min-content size is the whole
|
|
134
|
+
* unbreakable word — the text ran past the card edge. `anywhere`, not
|
|
135
|
+
* `break-word`: only `anywhere` lets the break point count toward the
|
|
136
|
+
* min-content size, which is what the flex layout measures. Inherited, so
|
|
137
|
+
* the title and every content paragraph get it. ((Task) 581)
|
|
138
|
+
*/
|
|
139
|
+
overflow-wrap: anywhere;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* One gap for both title shapes. The static `<p>` title ships `mb-2` and the
|
|
144
|
+
* collapsible variant instead puts `mt-2` on the content that follows the
|
|
145
|
+
* `<summary>` — two different gaps for one anatomy. Zero the title's own
|
|
146
|
+
* margin and state the gap once on whatever follows the title; a collapsed
|
|
147
|
+
* `<details>` renders no content and so gets no stray bottom space.
|
|
148
|
+
*/
|
|
149
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-admonition] > [data-ncm-admonition-title] {
|
|
150
|
+
margin-bottom: 0;
|
|
151
|
+
color: var(--ncm-callout-title, var(--foreground));
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-admonition] > [data-ncm-admonition-title] + * {
|
|
156
|
+
margin-top: 0.375rem;
|
|
78
157
|
}
|
|
79
158
|
|
|
80
159
|
/* Blockquote */
|
|
@@ -82,7 +161,7 @@
|
|
|
82
161
|
border-left: 2px solid var(--border);
|
|
83
162
|
padding-left: 0.875rem;
|
|
84
163
|
color: color-mix(in srgb, var(--foreground) 80%, transparent);
|
|
85
|
-
line-height: 1.
|
|
164
|
+
line-height: 1.65;
|
|
86
165
|
}
|
|
87
166
|
|
|
88
167
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="blockquote"] p + p {
|
|
@@ -90,11 +169,16 @@
|
|
|
90
169
|
}
|
|
91
170
|
|
|
92
171
|
/* Lists */
|
|
172
|
+
/*
|
|
173
|
+
* 1.5rem is the ONE marker-slot width all three list kinds share — disc,
|
|
174
|
+
* decimal, and the task checkbox (1em box + 0.5rem gap) — so the text column
|
|
175
|
+
* is identical across them at every depth.
|
|
176
|
+
*/
|
|
93
177
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_ordered"],
|
|
94
178
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_unordered"] {
|
|
95
|
-
padding-left: 1.
|
|
179
|
+
padding-left: 1.5rem;
|
|
96
180
|
color: var(--foreground);
|
|
97
|
-
line-height: 1.
|
|
181
|
+
line-height: 1.65;
|
|
98
182
|
}
|
|
99
183
|
|
|
100
184
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_ordered"] {
|
|
@@ -115,7 +199,7 @@
|
|
|
115
199
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_unordered"] ol,
|
|
116
200
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_unordered"] ul {
|
|
117
201
|
margin-top: 0.125rem;
|
|
118
|
-
padding-left: 1.
|
|
202
|
+
padding-left: 1.5rem;
|
|
119
203
|
}
|
|
120
204
|
|
|
121
205
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="list_ordered"] li::marker,
|
|
@@ -136,6 +220,90 @@
|
|
|
136
220
|
list-style-type: decimal;
|
|
137
221
|
}
|
|
138
222
|
|
|
223
|
+
/*
|
|
224
|
+
* Task list — one spec with the editor's `ul[data-type="taskList"]` block in
|
|
225
|
+
* `@nuucognition/nuu-editor` (`src/nuu-editor/nuu-editor.scss`): flush-left
|
|
226
|
+
* rows 0.125rem apart, a 1em checkbox rounded 0.25rem (the nuu-ui Checkbox
|
|
227
|
+
* radius) drawn from theme tokens (border-token box, foreground fill when
|
|
228
|
+
* checked, background-coloured check), 0.5rem to the text — 1em + 0.5rem =
|
|
229
|
+
* the shared 1.5rem marker slot that lines task text up with disc and
|
|
230
|
+
* decimal text. Checked text dims to the muted tone with NO strike-through.
|
|
231
|
+
* A nested task list carries NO indent of its own: the checkbox slot IS the
|
|
232
|
+
* indent, the same 1.5rem step the other list kinds get from padding. If one
|
|
233
|
+
* side of that pair moves, move the other in the same change.
|
|
234
|
+
*
|
|
235
|
+
* The checkbox is drawn with `appearance: none` because the native control
|
|
236
|
+
* neither themes nor matches the editor's; the input stays a real (disabled)
|
|
237
|
+
* checkbox for the accessibility tree. The `> li` rule neutralizes the
|
|
238
|
+
* component's own Tailwind row gap so the 0.125rem list rhythm is the one
|
|
239
|
+
* answer.
|
|
240
|
+
*/
|
|
241
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-list] {
|
|
242
|
+
padding-left: 0;
|
|
243
|
+
color: var(--foreground);
|
|
244
|
+
line-height: 1.65;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-list] > li:not(:last-child) {
|
|
248
|
+
margin-bottom: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-list] li + li {
|
|
252
|
+
margin-top: 0.125rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-list] [data-ncm-list-nested] {
|
|
256
|
+
/* No margin: the nested row's own checkbox slot (1em + 0.5rem) is the
|
|
257
|
+
1.5rem indent, the same step disc and decimal get from padding. */
|
|
258
|
+
margin-left: 0;
|
|
259
|
+
margin-top: 0.125rem;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* Top-aligned like the editor (whose checkbox sits 0.375rem into the row):
|
|
263
|
+
on a wrapped item the box stays on the first line instead of centring
|
|
264
|
+
across the whole item. */
|
|
265
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-item] > span {
|
|
266
|
+
gap: 0.5rem;
|
|
267
|
+
align-items: flex-start;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-item] input[type="checkbox"] {
|
|
271
|
+
appearance: none;
|
|
272
|
+
-webkit-appearance: none;
|
|
273
|
+
width: 1em;
|
|
274
|
+
height: 1em;
|
|
275
|
+
margin: 0.375rem 0 0;
|
|
276
|
+
border: 1px solid var(--border);
|
|
277
|
+
/* nuu-ui's Checkbox radius (rounded-[4px]). */
|
|
278
|
+
border-radius: 0.25rem;
|
|
279
|
+
background-color: transparent;
|
|
280
|
+
position: relative;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-item] input[type="checkbox"]:checked {
|
|
284
|
+
background-color: var(--foreground);
|
|
285
|
+
border-color: var(--foreground);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-item] input[type="checkbox"]:checked::before {
|
|
289
|
+
content: "";
|
|
290
|
+
position: absolute;
|
|
291
|
+
left: 50%;
|
|
292
|
+
top: 50%;
|
|
293
|
+
transform: translate(-50%, -50%);
|
|
294
|
+
width: 0.75em;
|
|
295
|
+
height: 0.75em;
|
|
296
|
+
background-color: var(--background);
|
|
297
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22currentColor%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.4142%204.58579C22.1953%205.36683%2022.1953%206.63317%2021.4142%207.41421L10.4142%2018.4142C9.63317%2019.1953%208.36684%2019.1953%207.58579%2018.4142L2.58579%2013.4142C1.80474%2012.6332%201.80474%2011.3668%202.58579%2010.5858C3.36683%209.80474%204.63317%209.80474%205.41421%2010.5858L9%2014.1716L18.5858%204.58579C19.3668%203.80474%2020.6332%203.80474%2021.4142%204.58579Z%22%20fill%3D%22currentColor%22%2F%3E%3C%2Fsvg%3E")
|
|
298
|
+
center/contain no-repeat;
|
|
299
|
+
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22currentColor%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.4142%204.58579C22.1953%205.36683%2022.1953%206.63317%2021.4142%207.41421L10.4142%2018.4142C9.63317%2019.1953%208.36684%2019.1953%207.58579%2018.4142L2.58579%2013.4142C1.80474%2012.6332%201.80474%2011.3668%202.58579%2010.5858C3.36683%209.80474%204.63317%209.80474%205.41421%2010.5858L9%2014.1716L18.5858%204.58579C19.3668%203.80474%2020.6332%203.80474%2021.4142%204.58579Z%22%20fill%3D%22currentColor%22%2F%3E%3C%2Fsvg%3E")
|
|
300
|
+
center/contain no-repeat;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-task-item][data-ncm-checked="true"] > span > span {
|
|
304
|
+
color: var(--muted-foreground);
|
|
305
|
+
}
|
|
306
|
+
|
|
139
307
|
/* Tables */
|
|
140
308
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="table"] {
|
|
141
309
|
width: 100%;
|
|
@@ -145,7 +313,7 @@
|
|
|
145
313
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="table"] table {
|
|
146
314
|
width: 100%;
|
|
147
315
|
border-collapse: collapse;
|
|
148
|
-
font-size:
|
|
316
|
+
font-size: 0.857em;
|
|
149
317
|
}
|
|
150
318
|
|
|
151
319
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="table"] th {
|
|
@@ -168,27 +336,50 @@
|
|
|
168
336
|
background-color: color-mix(in srgb, var(--muted) 50%, transparent);
|
|
169
337
|
}
|
|
170
338
|
|
|
339
|
+
/* An empty cell keeps its line box, so an entirely blank row renders at full
|
|
340
|
+
height instead of collapsing to its padding. */
|
|
341
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-type="table"] th:empty::after,
|
|
342
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-type="table"] td:empty::after {
|
|
343
|
+
content: "\00a0";
|
|
344
|
+
}
|
|
345
|
+
|
|
171
346
|
/* Code (block) */
|
|
172
347
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="code"] {
|
|
173
348
|
position: relative;
|
|
174
349
|
}
|
|
175
350
|
|
|
351
|
+
/* Minimalist, matching the editor's code block at rest: bare text — no fill,
|
|
352
|
+
no visible box. The border keeps its 1px width as transparent so the text
|
|
353
|
+
sits at exactly the editor's inset (its border reveals on hover/caret). The
|
|
354
|
+
editor's `pre` rule mirrors this — move both together. */
|
|
176
355
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="code"] pre {
|
|
177
356
|
overflow-x: auto;
|
|
178
|
-
border: 1px solid
|
|
179
|
-
border-radius:
|
|
357
|
+
border: 1px solid transparent;
|
|
358
|
+
border-radius: 0;
|
|
180
359
|
padding: 0.75rem;
|
|
181
|
-
background-color:
|
|
360
|
+
background-color: transparent;
|
|
182
361
|
color: var(--foreground);
|
|
183
362
|
font-family: var(--font-mono);
|
|
184
|
-
font-size:
|
|
185
|
-
line-height: 1.
|
|
363
|
+
font-size: 0.875em;
|
|
364
|
+
line-height: 1.55;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* Parse warning (NcmBlockPreview) — the reader-mode display for a block
|
|
368
|
+
source that cannot be parsed as its block type. Minimalist: muted text,
|
|
369
|
+
hairline border, sharp corners. */
|
|
370
|
+
[data-ncm-parse-warning] {
|
|
371
|
+
border: 1px solid var(--border);
|
|
372
|
+
padding: 0.5rem 0.75rem;
|
|
373
|
+
color: var(--muted-foreground);
|
|
374
|
+
font-family: var(--font-sans);
|
|
375
|
+
font-size: 0.857em;
|
|
376
|
+
line-height: 1.5;
|
|
186
377
|
}
|
|
187
378
|
|
|
188
379
|
/* Inline code */
|
|
189
380
|
[data-ncm-document].ncm-theme-nuu [data-ncm-token="code"] {
|
|
190
381
|
font-family: var(--font-mono);
|
|
191
|
-
font-size:
|
|
382
|
+
font-size: 0.857em;
|
|
192
383
|
padding: 0.125rem 0.25rem;
|
|
193
384
|
border-radius: 0.25rem;
|
|
194
385
|
background-color: var(--muted);
|
|
@@ -212,17 +403,111 @@
|
|
|
212
403
|
text-underline-offset: 4px;
|
|
213
404
|
}
|
|
214
405
|
|
|
406
|
+
/*
|
|
407
|
+
* AMBIGUOUS IS A WARNING, NOT A FAILURE — and this rule used to say otherwise.
|
|
408
|
+
*
|
|
409
|
+
* It painted `--fire-text`/`--destructive`, i.e. RED, while the EDIT surface
|
|
410
|
+
* paints red for a MISSING link and amber for an ambiguous one. The same hue
|
|
411
|
+
* therefore carried two different facts depending on which mode the reader was
|
|
412
|
+
* in, which is worse than either surface being wrong on its own: a reader who
|
|
413
|
+
* learns what red means in one mode is actively misled by the other.
|
|
414
|
+
*
|
|
415
|
+
* The vocabulary this settles on, ruled in room `onyx-uiux` on 2026-07-31 and
|
|
416
|
+
* applied across both surfaces:
|
|
417
|
+
*
|
|
418
|
+
* missing pending — muted foreground, dashed. A link to a document that
|
|
419
|
+
* is not in this mesh is very often a PLAN, not a mistake; that is
|
|
420
|
+
* also the Obsidian benchmark, where an unresolved link is the
|
|
421
|
+
* link colour faded and never red.
|
|
422
|
+
* ambiguous warning — amber, dotted. Several targets match; the author has
|
|
423
|
+
* something to decide, but nothing has failed.
|
|
424
|
+
* red reserved for GENUINE FAILURE — in this package, an embed whose
|
|
425
|
+
* bytes did not arrive (see `renderImageError`).
|
|
426
|
+
*
|
|
427
|
+
* A DELIBERATE VISUAL CHANGE FOR EVERY EMBEDDER, not just for Onyx: an
|
|
428
|
+
* ambiguous reference stops being drawn as an error. Recorded in the README.
|
|
429
|
+
*/
|
|
215
430
|
[data-ncm-document].ncm-theme-nuu [data-ncm-token="wiki_link"][data-ncm-wikilink-status="ambiguous"],
|
|
216
431
|
[data-ncm-document].ncm-theme-nuu [data-ncm-token="wiki_embed"][data-ncm-wikiembed-status="ambiguous"] {
|
|
217
|
-
color: var(--
|
|
432
|
+
color: var(--sun-text, var(--warning, #b45309));
|
|
433
|
+
text-decoration: underline dotted;
|
|
434
|
+
text-underline-offset: 4px;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/*
|
|
438
|
+
* Wikilink focus ring.
|
|
439
|
+
*
|
|
440
|
+
* `renderer.tsx` already emits a real <a> or <button> for an actionable
|
|
441
|
+
* wikilink, so read-mode links have ALWAYS been in the tab order — a keyboard
|
|
442
|
+
* user could reach them and had no way to see that they had. Measured on the
|
|
443
|
+
* Onyx read surface in both themes: outline-style none, box-shadow none, while
|
|
444
|
+
* the surrounding chrome buttons showed a ring. That is the whole of
|
|
445
|
+
* known-adopted issue 095#5, and it belongs here rather than in a host: an
|
|
446
|
+
* embedder gets no focus affordance for these elements from anywhere else.
|
|
447
|
+
*
|
|
448
|
+
* A NEW rule, touching no existing selector. It paints only when a host has
|
|
449
|
+
* made the link actionable AND the browser is in keyboard-focus mode, so no
|
|
450
|
+
* rendering that exists today changes.
|
|
451
|
+
*
|
|
452
|
+
* (Landed as the negotiated ncm-ui freeze exception for Task 507, approved in
|
|
453
|
+
* room `onyx-uiux` on 2026-07-31. The TSX half of the original proposal was
|
|
454
|
+
* withdrawn: the button is focusable by construction and needed nothing.)
|
|
455
|
+
*/
|
|
456
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-token="wiki_link"]:focus-visible {
|
|
457
|
+
outline: 2px solid var(--ring, currentColor);
|
|
458
|
+
outline-offset: 2px;
|
|
459
|
+
border-radius: 0.1875rem;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/*
|
|
463
|
+
* Pointer cursor for the ACTIONABLE wikilink elements — the <a> a host's
|
|
464
|
+
* `resolveWikiLinkHref` produces and the <button> a bare `onWikiLinkClick`
|
|
465
|
+
* produces. The anchor has the pointer from the user agent already; the button
|
|
466
|
+
* does not — Tailwind v4's preflight leaves buttons on the default arrow, so in
|
|
467
|
+
* Onyx a clickable wikilink did not read as clickable. The element selectors
|
|
468
|
+
* exclude the inert <span> a host with neither config gets, which stays on the
|
|
469
|
+
* text cursor on purpose. (Task 558.)
|
|
470
|
+
*/
|
|
471
|
+
[data-ncm-document].ncm-theme-nuu a[data-ncm-token="wiki_link"],
|
|
472
|
+
[data-ncm-document].ncm-theme-nuu button[data-ncm-token="wiki_link"] {
|
|
473
|
+
cursor: pointer;
|
|
218
474
|
}
|
|
219
475
|
|
|
220
|
-
/*
|
|
476
|
+
/*
|
|
477
|
+
* The embed BUTTON — the element `EmbeddingsConfig.onEmbedClick` produces.
|
|
478
|
+
*
|
|
479
|
+
* Both rules below can only ever match an element that does not exist unless a
|
|
480
|
+
* host opted in, so neither can change a rendering that ships today.
|
|
481
|
+
*
|
|
482
|
+
* The reset first: a `<button>` in the middle of a sentence arrives wearing the
|
|
483
|
+
* user agent's chrome — its own background, border, padding and font — and an
|
|
484
|
+
* embedded document is a piece of the prose, not a form control. Onyx never saw
|
|
485
|
+
* this because Tailwind's preflight resets buttons app-wide; an embedder
|
|
486
|
+
* without one would have. Then the ring, the sibling of the wikilink rule
|
|
487
|
+
* directly above: the button is a tab stop by construction, so it needs to be
|
|
488
|
+
* able to say when it has been reached.
|
|
489
|
+
*/
|
|
490
|
+
[data-ncm-document].ncm-theme-nuu button[data-ncm-token="wiki_embed"] {
|
|
491
|
+
appearance: none;
|
|
492
|
+
padding: 0;
|
|
493
|
+
border: 0;
|
|
494
|
+
background: none;
|
|
495
|
+
font: inherit;
|
|
496
|
+
cursor: pointer;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
[data-ncm-document].ncm-theme-nuu [data-ncm-token="wiki_embed"]:focus-visible {
|
|
500
|
+
outline: 2px solid var(--ring, currentColor);
|
|
501
|
+
outline-offset: 2px;
|
|
502
|
+
border-radius: 0.1875rem;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* Horizontal rule — 1em on both sides, matching the editor's hr rule. */
|
|
221
506
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="horizontal_rule"] {
|
|
222
507
|
border: 0;
|
|
223
508
|
border-top: 1px solid var(--border);
|
|
224
|
-
margin-top:
|
|
225
|
-
margin-bottom:
|
|
509
|
+
margin-top: 1em;
|
|
510
|
+
margin-bottom: 1em;
|
|
226
511
|
}
|
|
227
512
|
|
|
228
513
|
/* Embeddings */
|
|
@@ -235,7 +520,7 @@
|
|
|
235
520
|
[data-ncm-document].ncm-theme-nuu [data-ncm-type="embedding"] figcaption {
|
|
236
521
|
margin-top: 0.5rem;
|
|
237
522
|
text-align: left;
|
|
238
|
-
font-size: 0.
|
|
523
|
+
font-size: 0.857em;
|
|
239
524
|
color: var(--muted-foreground);
|
|
240
525
|
}
|
|
241
526
|
|
|
@@ -253,7 +538,7 @@
|
|
|
253
538
|
background-color: var(--muted);
|
|
254
539
|
color: var(--foreground);
|
|
255
540
|
font-family: var(--font-mono);
|
|
256
|
-
font-size:
|
|
541
|
+
font-size: 1em;
|
|
257
542
|
}
|
|
258
543
|
|
|
259
544
|
/* OpenDyslexic3 — newest, refined letterforms of the OpenDyslexic family
|
|
@@ -344,7 +629,7 @@
|
|
|
344
629
|
background: var(--popover, var(--background, var(--muted)));
|
|
345
630
|
color: var(--popover-foreground, var(--foreground));
|
|
346
631
|
box-shadow: 0 4px 12px rgb(0 0 0 / 0.12);
|
|
347
|
-
font-size:
|
|
632
|
+
font-size: 0.929em;
|
|
348
633
|
font-weight: 400;
|
|
349
634
|
line-height: 1.5;
|
|
350
635
|
white-space: normal;
|
package/dist/styles/paper.css
CHANGED
|
@@ -172,6 +172,13 @@
|
|
|
172
172
|
color: var(--muted-foreground);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
/* An empty cell keeps its line box, so an entirely blank row renders at full
|
|
176
|
+
height instead of collapsing to its padding. */
|
|
177
|
+
[data-ncm-document].ncm-theme-paper [data-ncm-type="table"] th:empty::after,
|
|
178
|
+
[data-ncm-document].ncm-theme-paper [data-ncm-type="table"] td:empty::after {
|
|
179
|
+
content: "\00a0";
|
|
180
|
+
}
|
|
181
|
+
|
|
175
182
|
/* Code (block) */
|
|
176
183
|
[data-ncm-document].ncm-theme-paper [data-ncm-type="code"] {
|
|
177
184
|
position: relative;
|
|
@@ -218,9 +225,63 @@
|
|
|
218
225
|
text-underline-offset: 3px;
|
|
219
226
|
}
|
|
220
227
|
|
|
228
|
+
/*
|
|
229
|
+
* Ambiguous is a warning, not a failure — the paper sibling of the rule in
|
|
230
|
+
* `nuu.css`, where the whole vocabulary argument is written down. Same change,
|
|
231
|
+
* same reason, kept in step so the two themes cannot disagree about what a
|
|
232
|
+
* colour means. Paper's dotted underline is 1px-thin and offset 3px like every
|
|
233
|
+
* other decoration in this sheet.
|
|
234
|
+
*/
|
|
221
235
|
[data-ncm-document].ncm-theme-paper [data-ncm-token="wiki_link"][data-ncm-wikilink-status="ambiguous"],
|
|
222
236
|
[data-ncm-document].ncm-theme-paper [data-ncm-token="wiki_embed"][data-ncm-wikiembed-status="ambiguous"] {
|
|
223
|
-
color: var(--
|
|
237
|
+
color: var(--sun-text, var(--warning, #b45309));
|
|
238
|
+
text-decoration: underline dotted;
|
|
239
|
+
text-decoration-thickness: 1px;
|
|
240
|
+
text-underline-offset: 3px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/*
|
|
244
|
+
* Wikilink focus ring — the paper sibling of the rule in `nuu.css`; see that
|
|
245
|
+
* file for the full reasoning. Kept in step deliberately: a focus affordance
|
|
246
|
+
* that exists in one theme and not the other is a keyboard user's experience
|
|
247
|
+
* changing with a setting that is supposed to be about typography.
|
|
248
|
+
*
|
|
249
|
+
* `--ring` with a `currentColor` fallback, so a paper host that defines no ring
|
|
250
|
+
* token still gets a visible ring in the link's own ink rather than nothing.
|
|
251
|
+
*/
|
|
252
|
+
[data-ncm-document].ncm-theme-paper [data-ncm-token="wiki_link"]:focus-visible {
|
|
253
|
+
outline: 2px solid var(--ring, currentColor);
|
|
254
|
+
outline-offset: 2px;
|
|
255
|
+
border-radius: 0.1875rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*
|
|
259
|
+
* Pointer cursor for the actionable wikilink elements — the paper sibling of
|
|
260
|
+
* the rule in `nuu.css`; that file carries the reasoning. (Task 558.)
|
|
261
|
+
*/
|
|
262
|
+
[data-ncm-document].ncm-theme-paper a[data-ncm-token="wiki_link"],
|
|
263
|
+
[data-ncm-document].ncm-theme-paper button[data-ncm-token="wiki_link"] {
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/*
|
|
268
|
+
* The embed button — paper siblings of the two rules in `nuu.css`; that file
|
|
269
|
+
* carries the reasoning. Both can only match an element a host opted into, so
|
|
270
|
+
* neither changes anything that renders today.
|
|
271
|
+
*/
|
|
272
|
+
[data-ncm-document].ncm-theme-paper button[data-ncm-token="wiki_embed"] {
|
|
273
|
+
appearance: none;
|
|
274
|
+
padding: 0;
|
|
275
|
+
border: 0;
|
|
276
|
+
background: none;
|
|
277
|
+
font: inherit;
|
|
278
|
+
cursor: pointer;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
[data-ncm-document].ncm-theme-paper [data-ncm-token="wiki_embed"]:focus-visible {
|
|
282
|
+
outline: 2px solid var(--ring, currentColor);
|
|
283
|
+
outline-offset: 2px;
|
|
284
|
+
border-radius: 0.1875rem;
|
|
224
285
|
}
|
|
225
286
|
|
|
226
287
|
/* Horizontal rule */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
import { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import { MeshResolveLinkResult, MeshHydrationContext } from '@nuucognition/mesh-core';
|
|
3
|
+
import { MeshResolveEmbedResult, MeshResolveLinkResult, MeshHydrationContext } from '@nuucognition/mesh-core';
|
|
4
4
|
import { EmbedType } from '@nuucognition/ncm';
|
|
5
5
|
import { c as EmbeddingRendererRegistry, b as BlockRendererRegistry } from './renderers-C5f41FCy.js';
|
|
6
6
|
|
|
@@ -23,6 +23,28 @@ interface InlineConfig {
|
|
|
23
23
|
*/
|
|
24
24
|
referencePopover?: boolean;
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* What a host draws in place of an image whose bytes never arrived.
|
|
28
|
+
*
|
|
29
|
+
* The renderer cannot answer this itself. Whether an `<img src>` actually
|
|
30
|
+
* loads is only learned by trying, and what to SAY about the failure is the
|
|
31
|
+
* host's vocabulary — a mesh embedder can offer a retry against its own blob
|
|
32
|
+
* cache, a static-site embedder has nothing to retry and should say so.
|
|
33
|
+
*/
|
|
34
|
+
interface ImageErrorProps {
|
|
35
|
+
/** The embed target exactly as the author wrote it (`logo.png`, a URL). */
|
|
36
|
+
target: string;
|
|
37
|
+
/** The URL that was handed to `<img src>` and did not load. */
|
|
38
|
+
src: string;
|
|
39
|
+
/** The alt text from the source, if the author wrote one. */
|
|
40
|
+
alt?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Re-attempt the load. The `<img>` is re-keyed, so this is a real second
|
|
43
|
+
* fetch rather than the browser's cached failure. A host that owns the URL
|
|
44
|
+
* (a blob cache) should refresh it first and then call this.
|
|
45
|
+
*/
|
|
46
|
+
retry: () => void;
|
|
47
|
+
}
|
|
26
48
|
/**
|
|
27
49
|
* Configuration for embedding rendering
|
|
28
50
|
*/
|
|
@@ -32,6 +54,34 @@ interface EmbeddingsConfig {
|
|
|
32
54
|
imageClassName?: string;
|
|
33
55
|
videoClassName?: string;
|
|
34
56
|
audioClassName?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Render a failed image instead of leaving the browser's broken-image box.
|
|
59
|
+
*
|
|
60
|
+
* OPT-IN, and strictly so: with no renderer supplied the `<img>` carries no
|
|
61
|
+
* `onError` handler at all, so the emitted DOM is identical to what every
|
|
62
|
+
* consumer gets today — not merely visually identical. Supplying one is what
|
|
63
|
+
* turns an unloadable image into a state with a name and a way out.
|
|
64
|
+
*
|
|
65
|
+
* Applies to both spellings of an inline image — `` and an
|
|
66
|
+
* `![[target]]` that resolves to one.
|
|
67
|
+
*/
|
|
68
|
+
renderImageError?: ComponentType<ImageErrorProps>;
|
|
69
|
+
/**
|
|
70
|
+
* Handle a click on a non-media embed — an embedded DOCUMENT, or any target
|
|
71
|
+
* whose type has no player.
|
|
72
|
+
*
|
|
73
|
+
* WITHOUT THIS the renderer emits `<a href={resolveUrl(...)}>`, which is only
|
|
74
|
+
* honest when the target really has a URL. A document in a title-addressed
|
|
75
|
+
* mesh does not: the host navigates in its own state, so the href ends up
|
|
76
|
+
* being the raw target, a relative URL that leads nowhere and copies as
|
|
77
|
+
* nonsense from the context menu.
|
|
78
|
+
*
|
|
79
|
+
* Supplying this renders the same content as a `<button>` instead, which
|
|
80
|
+
* claims nothing about URLs and is a real control — exactly the shape
|
|
81
|
+
* {@link InlineConfig.onWikiLinkClick} already produces for a wikilink with
|
|
82
|
+
* no href. Absent, nothing changes.
|
|
83
|
+
*/
|
|
84
|
+
onEmbedClick?: (target: string, result: MeshResolveEmbedResult | null, event: React.MouseEvent) => void;
|
|
35
85
|
}
|
|
36
86
|
/**
|
|
37
87
|
* Code rendering configuration
|
|
@@ -43,6 +93,7 @@ interface CodeConfig {
|
|
|
43
93
|
className?: string;
|
|
44
94
|
}>;
|
|
45
95
|
lineNumbers?: boolean;
|
|
96
|
+
/** Opt-in since the minimalist block pass: the button renders only on `true`. */
|
|
46
97
|
copyButton?: boolean;
|
|
47
98
|
}
|
|
48
99
|
/**
|
|
@@ -109,6 +160,6 @@ interface NcmProviderProps {
|
|
|
109
160
|
* </NcmProvider>
|
|
110
161
|
* ```
|
|
111
162
|
*/
|
|
112
|
-
declare function NcmProvider({ config, children }: NcmProviderProps):
|
|
163
|
+
declare function NcmProvider({ config, children }: NcmProviderProps): react.JSX.Element;
|
|
113
164
|
|
|
114
|
-
export { type CodeConfig as C, type EmbeddingsConfig as E, type
|
|
165
|
+
export { type CodeConfig as C, type EmbeddingsConfig as E, type ImageErrorProps as I, type NcmConfig as N, type InlineConfig as a, NcmProvider as b, type NcmProviderProps as c, useNcmConfig as u };
|