@heyramzi/ui 3.3.1 → 3.4.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.
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
* A surface supplies a title and a body, and never lays a document out itself.
|
|
4
4
|
*/
|
|
5
5
|
export { default as DocPage } from "../../../src/components/docs/doc-page.svelte";
|
|
6
|
+
export { default as DocumentView } from "../../../src/components/docs/document-view.svelte";
|
|
6
7
|
export { default as OnThisPage } from "../../../src/components/docs/on-this-page.svelte";
|
|
7
8
|
export { ScrollSpy, READ_LINE } from "./scroll-spy.svelte.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heyramzi/ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Svelte 5 UI for apps: primitives, effects and animations, plus work (tasks and docs), charts, slides, an editor, onboarding and a canvas as subpaths.",
|
|
5
5
|
"homepage": "https://ui.heyramzi.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,25 +82,28 @@
|
|
|
82
82
|
{#if count > 0}
|
|
83
83
|
<p class="hr-sr-only" aria-live="polite">{announce}</p>
|
|
84
84
|
{/if}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
{#each table.columns as column, j (j)}
|
|
91
|
-
<th scope="col">{column}</th>
|
|
92
|
-
{/each}
|
|
93
|
-
</tr>
|
|
94
|
-
</thead>
|
|
95
|
-
<tbody>
|
|
96
|
-
{#each table.rows as row, i (i)}
|
|
85
|
+
<!-- A table ignores width: 1px and spills past the page, so the clipping box is a div. -->
|
|
86
|
+
<div class="hr-sr-only">
|
|
87
|
+
<table>
|
|
88
|
+
<caption>{label}</caption>
|
|
89
|
+
<thead>
|
|
97
90
|
<tr>
|
|
98
|
-
<th scope="
|
|
99
|
-
{#each
|
|
100
|
-
<
|
|
91
|
+
<th scope="col">{table.xLabel}</th>
|
|
92
|
+
{#each table.columns as column, j (j)}
|
|
93
|
+
<th scope="col">{column}</th>
|
|
101
94
|
{/each}
|
|
102
95
|
</tr>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
</thead>
|
|
97
|
+
<tbody>
|
|
98
|
+
{#each table.rows as row, i (i)}
|
|
99
|
+
<tr>
|
|
100
|
+
<th scope="row">{row.x}</th>
|
|
101
|
+
{#each row.cells as cell, j (j)}
|
|
102
|
+
<td>{cell}</td>
|
|
103
|
+
{/each}
|
|
104
|
+
</tr>
|
|
105
|
+
{/each}
|
|
106
|
+
</tbody>
|
|
107
|
+
</table>
|
|
108
|
+
</div>
|
|
106
109
|
{/if}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// =========================
|
|
3
|
+
// IMPORTS
|
|
4
|
+
// =========================
|
|
5
|
+
import type { Component, Snippet } from "svelte";
|
|
6
|
+
import { untrack } from "svelte";
|
|
7
|
+
import DocPage from "./doc-page.svelte";
|
|
8
|
+
import type { DocHeading } from "./scroll-spy.svelte.js";
|
|
9
|
+
|
|
10
|
+
// =========================
|
|
11
|
+
// TYPES
|
|
12
|
+
// =========================
|
|
13
|
+
interface Props {
|
|
14
|
+
title: string;
|
|
15
|
+
/** Breadcrumb, as a reader would say it: "Marketing / Reports". */
|
|
16
|
+
section?: string;
|
|
17
|
+
/** Already worded and localised: "Updated 30 Jul 2026". */
|
|
18
|
+
updated?: string;
|
|
19
|
+
icon?: Component<{
|
|
20
|
+
class?: string;
|
|
21
|
+
weight?: "bold";
|
|
22
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
23
|
+
}>;
|
|
24
|
+
actions?: Snippet;
|
|
25
|
+
/** The body's h2s, anchored by id, for the "On this page" rail. */
|
|
26
|
+
headings?: DocHeading[];
|
|
27
|
+
contentsLabel: string;
|
|
28
|
+
/** The rendered body. Trusted HTML from the consumer's own parser, never user input. */
|
|
29
|
+
html: string;
|
|
30
|
+
/** Changes when another document is shown: the pane returns to the top and the body re-enters. */
|
|
31
|
+
resetKey: string;
|
|
32
|
+
measure?: "prose" | "wide";
|
|
33
|
+
/** Runs on the body after every swap (icons, diagrams). Returns its cleanup. */
|
|
34
|
+
enhance?: (root: HTMLElement) => void | (() => void);
|
|
35
|
+
class?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// =========================
|
|
39
|
+
// PROPS
|
|
40
|
+
// =========================
|
|
41
|
+
let {
|
|
42
|
+
title,
|
|
43
|
+
section,
|
|
44
|
+
updated,
|
|
45
|
+
icon,
|
|
46
|
+
actions,
|
|
47
|
+
headings = [],
|
|
48
|
+
contentsLabel,
|
|
49
|
+
html,
|
|
50
|
+
resetKey,
|
|
51
|
+
measure = "prose",
|
|
52
|
+
enhance,
|
|
53
|
+
class: className = "",
|
|
54
|
+
}: Props = $props();
|
|
55
|
+
|
|
56
|
+
// =========================
|
|
57
|
+
// STATE
|
|
58
|
+
// =========================
|
|
59
|
+
let body = $state<HTMLElement | null>(null);
|
|
60
|
+
|
|
61
|
+
// =========================
|
|
62
|
+
// EFFECTS
|
|
63
|
+
// =========================
|
|
64
|
+
$effect(() => {
|
|
65
|
+
void html;
|
|
66
|
+
const root = body;
|
|
67
|
+
if (!root || !enhance) return;
|
|
68
|
+
return untrack(() => enhance(root)) ?? undefined;
|
|
69
|
+
});
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<!-- =========================== -->
|
|
73
|
+
<!-- MARKUP -->
|
|
74
|
+
<!-- =========================== -->
|
|
75
|
+
<!-- Inline, not framed: a link is an ordinary anchor, so the router swaps only this body. -->
|
|
76
|
+
<DocPage
|
|
77
|
+
{title}
|
|
78
|
+
{section}
|
|
79
|
+
{updated}
|
|
80
|
+
{icon}
|
|
81
|
+
{actions}
|
|
82
|
+
{headings}
|
|
83
|
+
{contentsLabel}
|
|
84
|
+
{resetKey}
|
|
85
|
+
{measure}
|
|
86
|
+
>
|
|
87
|
+
{#key resetKey}
|
|
88
|
+
<div bind:this={body} class="document-view t-enter {className}">
|
|
89
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -- trusted, parsed server-side -->
|
|
90
|
+
{@html html}
|
|
91
|
+
</div>
|
|
92
|
+
{/key}
|
|
93
|
+
</DocPage>
|
|
94
|
+
|
|
95
|
+
<!-- =========================== -->
|
|
96
|
+
<!-- STYLES -->
|
|
97
|
+
<!-- =========================== -->
|
|
98
|
+
<!-- In the components layer at zero specificity, so a consumer's own document stylesheet wins without !important. -->
|
|
99
|
+
<style>
|
|
100
|
+
@layer theme, base, components, utilities;
|
|
101
|
+
|
|
102
|
+
@layer components {
|
|
103
|
+
:global {
|
|
104
|
+
:where(.document-view) {
|
|
105
|
+
color: var(--color-foreground);
|
|
106
|
+
font-size: 0.9375rem;
|
|
107
|
+
line-height: 1.65;
|
|
108
|
+
overflow-wrap: anywhere;
|
|
109
|
+
}
|
|
110
|
+
:where(.document-view) :where(h1, h2, h3, h4) {
|
|
111
|
+
font-family: var(--font-heading);
|
|
112
|
+
color: var(--color-foreground);
|
|
113
|
+
line-height: 1.25;
|
|
114
|
+
text-wrap: balance;
|
|
115
|
+
scroll-margin-top: 6rem;
|
|
116
|
+
}
|
|
117
|
+
:where(.document-view) :where(h1:first-child) {
|
|
118
|
+
display: none;
|
|
119
|
+
}
|
|
120
|
+
:where(.document-view) :where(h2) {
|
|
121
|
+
margin: 2.5rem 0 0.75rem;
|
|
122
|
+
font-size: 1.25rem;
|
|
123
|
+
font-weight: 700;
|
|
124
|
+
letter-spacing: -0.01em;
|
|
125
|
+
}
|
|
126
|
+
:where(.document-view) :where(h3) {
|
|
127
|
+
margin: 1.75rem 0 0.5rem;
|
|
128
|
+
font-size: 1rem;
|
|
129
|
+
font-weight: 600;
|
|
130
|
+
}
|
|
131
|
+
:where(.document-view) > :where(:first-child, h1:first-child + *) {
|
|
132
|
+
margin-top: 0;
|
|
133
|
+
}
|
|
134
|
+
:where(.document-view) :where(p, ul, ol, blockquote, pre, table) {
|
|
135
|
+
margin: 0 0 1rem;
|
|
136
|
+
}
|
|
137
|
+
:where(.document-view) :where(ul, ol) {
|
|
138
|
+
padding-left: 1.25rem;
|
|
139
|
+
}
|
|
140
|
+
:where(.document-view) :where(li + li) {
|
|
141
|
+
margin-top: 0.25rem;
|
|
142
|
+
}
|
|
143
|
+
:where(.document-view) :where(a) {
|
|
144
|
+
color: var(--color-brand);
|
|
145
|
+
text-decoration: underline;
|
|
146
|
+
text-decoration-color: color-mix(in oklch, currentColor 35%, transparent);
|
|
147
|
+
text-underline-offset: 0.16em;
|
|
148
|
+
transition: text-decoration-color var(--duration-fast) ease-out;
|
|
149
|
+
}
|
|
150
|
+
@media (hover: hover) and (pointer: fine) {
|
|
151
|
+
:where(.document-view) :where(a:hover) {
|
|
152
|
+
text-decoration-color: currentColor;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/* A wikilink to a page that does not exist yet reads as text, not as a dead link. */
|
|
156
|
+
:where(.document-view) :where(.wikilink.missing, a.missing) {
|
|
157
|
+
color: var(--color-muted-foreground);
|
|
158
|
+
text-decoration-style: dashed;
|
|
159
|
+
}
|
|
160
|
+
:where(.document-view) :where(code) {
|
|
161
|
+
font-family: var(--font-mono);
|
|
162
|
+
font-size: 0.85em;
|
|
163
|
+
padding: 0.1em 0.35em;
|
|
164
|
+
border-radius: var(--radius-sm, 0.375rem);
|
|
165
|
+
background: var(--color-muted);
|
|
166
|
+
}
|
|
167
|
+
:where(.document-view) :where(pre) {
|
|
168
|
+
overflow-x: auto;
|
|
169
|
+
padding: 0.875rem 1rem;
|
|
170
|
+
border: 1px solid var(--color-border);
|
|
171
|
+
border-radius: var(--radius-lg);
|
|
172
|
+
background: var(--color-muted);
|
|
173
|
+
font-size: 0.8125rem;
|
|
174
|
+
line-height: 1.55;
|
|
175
|
+
}
|
|
176
|
+
:where(.document-view) :where(pre code) {
|
|
177
|
+
padding: 0;
|
|
178
|
+
background: none;
|
|
179
|
+
font-size: inherit;
|
|
180
|
+
}
|
|
181
|
+
:where(.document-view) :where(blockquote) {
|
|
182
|
+
padding: 0.75rem 1rem;
|
|
183
|
+
border-radius: var(--radius-md);
|
|
184
|
+
background: var(--color-muted);
|
|
185
|
+
color: var(--color-muted-foreground);
|
|
186
|
+
}
|
|
187
|
+
:where(.document-view) :where(blockquote > :last-child) {
|
|
188
|
+
margin-bottom: 0;
|
|
189
|
+
}
|
|
190
|
+
:where(.document-view) :where(.callout) {
|
|
191
|
+
margin: 0 0 1rem;
|
|
192
|
+
padding: 0.75rem 1rem;
|
|
193
|
+
border: 1px solid var(--color-border);
|
|
194
|
+
border-radius: var(--radius-lg);
|
|
195
|
+
background: var(--color-card);
|
|
196
|
+
}
|
|
197
|
+
:where(.document-view) :where(table) {
|
|
198
|
+
display: block;
|
|
199
|
+
max-width: 100%;
|
|
200
|
+
overflow-x: auto;
|
|
201
|
+
border-collapse: collapse;
|
|
202
|
+
font-size: 0.875rem;
|
|
203
|
+
font-variant-numeric: tabular-nums;
|
|
204
|
+
}
|
|
205
|
+
:where(.document-view) :where(th, td) {
|
|
206
|
+
padding: 0.5rem 0.75rem;
|
|
207
|
+
border-bottom: 1px solid var(--color-border);
|
|
208
|
+
text-align: left;
|
|
209
|
+
vertical-align: top;
|
|
210
|
+
}
|
|
211
|
+
:where(.document-view) :where(th) {
|
|
212
|
+
font-weight: 600;
|
|
213
|
+
color: var(--color-muted-foreground);
|
|
214
|
+
}
|
|
215
|
+
:where(.document-view) :where(hr) {
|
|
216
|
+
margin: 2rem 0;
|
|
217
|
+
border: 0;
|
|
218
|
+
border-top: 1px solid var(--color-border);
|
|
219
|
+
}
|
|
220
|
+
:where(.document-view) :where(img) {
|
|
221
|
+
max-width: 100%;
|
|
222
|
+
height: auto;
|
|
223
|
+
border-radius: var(--radius-md);
|
|
224
|
+
}
|
|
225
|
+
@media (prefers-reduced-motion: reduce) {
|
|
226
|
+
:where(.document-view) :where(a) {
|
|
227
|
+
transition: none;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Component, Snippet } from "svelte";
|
|
2
|
+
import type { DocHeading } from "./scroll-spy.svelte.js";
|
|
3
|
+
interface Props {
|
|
4
|
+
title: string;
|
|
5
|
+
/** Breadcrumb, as a reader would say it: "Marketing / Reports". */
|
|
6
|
+
section?: string;
|
|
7
|
+
/** Already worded and localised: "Updated 30 Jul 2026". */
|
|
8
|
+
updated?: string;
|
|
9
|
+
icon?: Component<{
|
|
10
|
+
class?: string;
|
|
11
|
+
weight?: "bold";
|
|
12
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
13
|
+
}>;
|
|
14
|
+
actions?: Snippet;
|
|
15
|
+
/** The body's h2s, anchored by id, for the "On this page" rail. */
|
|
16
|
+
headings?: DocHeading[];
|
|
17
|
+
contentsLabel: string;
|
|
18
|
+
/** The rendered body. Trusted HTML from the consumer's own parser, never user input. */
|
|
19
|
+
html: string;
|
|
20
|
+
/** Changes when another document is shown: the pane returns to the top and the body re-enters. */
|
|
21
|
+
resetKey: string;
|
|
22
|
+
measure?: "prose" | "wide";
|
|
23
|
+
/** Runs on the body after every swap (icons, diagrams). Returns its cleanup. */
|
|
24
|
+
enhance?: (root: HTMLElement) => void | (() => void);
|
|
25
|
+
class?: string;
|
|
26
|
+
}
|
|
27
|
+
declare const $$Component: Component<Props, {}, "">;
|
|
28
|
+
type $$Component = ReturnType<typeof $$Component>;
|
|
29
|
+
export default $$Component;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* A surface supplies a title and a body, and never lays a document out itself.
|
|
4
4
|
*/
|
|
5
5
|
export { default as DocPage } from "./doc-page.svelte";
|
|
6
|
+
export { default as DocumentView } from "./document-view.svelte";
|
|
6
7
|
export { default as OnThisPage } from "./on-this-page.svelte";
|
|
7
8
|
export {
|
|
8
9
|
ScrollSpy,
|