@gjermundgaraba-designs/simple-rat 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +5 -5
- package/dist/highlight/highlight.d.ts.map +1 -1
- package/dist/highlight/highlight.js +66 -115
- package/dist/highlight/vite.d.ts +2 -1
- package/dist/highlight/vite.d.ts.map +1 -1
- package/dist/highlight/vite.js +5 -6
- package/dist/src/code/code.d.ts +4 -4
- package/dist/src/code/code.d.ts.map +1 -1
- package/dist/src/code/code.js +10 -7
- package/dist/src/code/index.d.ts.map +1 -1
- package/dist/src/{codeBlock/codeBlock.d.ts → code-block/code-block.d.ts} +2 -3
- package/dist/src/code-block/code-block.d.ts.map +1 -0
- package/dist/src/{codeBlock/codeBlock.js → code-block/code-block.js} +13 -7
- package/dist/src/code-block/index.d.ts +3 -0
- package/dist/src/code-block/index.d.ts.map +1 -0
- package/dist/src/code-block/index.js +1 -0
- package/dist/src/copy/copy.d.ts.map +1 -1
- package/dist/src/copy/copy.js +1 -7
- package/dist/src/{copyTab/copyTab.d.ts → copy-tab/copy-tab.d.ts} +3 -2
- package/dist/src/copy-tab/copy-tab.d.ts.map +1 -0
- package/dist/src/{copyTab/copyTab.js → copy-tab/copy-tab.js} +13 -13
- package/dist/src/copy-tab/index.d.ts +3 -0
- package/dist/src/copy-tab/index.d.ts.map +1 -0
- package/dist/src/{copyTab → copy-tab}/index.js +1 -1
- package/dist/src/diagram/diagram.d.ts.map +1 -1
- package/dist/src/diagram/index.d.ts.map +1 -1
- package/dist/src/footer/footer.d.ts.map +1 -1
- package/dist/src/footer/index.d.ts.map +1 -1
- package/dist/src/footnotes/footnotes.d.ts.map +1 -1
- package/dist/src/footnotes/footnotes.js +7 -2
- package/dist/src/footnotes/index.d.ts.map +1 -1
- package/dist/src/header/header.d.ts +1 -1
- package/dist/src/header/header.d.ts.map +1 -1
- package/dist/src/header/index.d.ts.map +1 -1
- package/dist/src/heading/heading.d.ts.map +1 -1
- package/dist/src/heading/index.d.ts.map +1 -1
- package/dist/src/index.d.ts +6 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -8
- package/dist/src/nav-link/index.d.ts +3 -0
- package/dist/src/nav-link/index.d.ts.map +1 -0
- package/dist/src/nav-link/index.js +1 -0
- package/dist/src/{navLink/navLink.d.ts → nav-link/nav-link.d.ts} +1 -1
- package/dist/src/nav-link/nav-link.d.ts.map +1 -0
- package/dist/src/{navLink/navLink.js → nav-link/nav-link.js} +1 -1
- package/dist/src/note/index.d.ts.map +1 -1
- package/dist/src/note/note.d.ts.map +1 -1
- package/dist/src/pager/index.d.ts.map +1 -1
- package/dist/src/pager/pager.d.ts.map +1 -1
- package/dist/src/post-list/index.d.ts +3 -0
- package/dist/src/post-list/index.d.ts.map +1 -0
- package/dist/src/post-list/index.js +1 -0
- package/dist/src/{postList/postList.d.ts → post-list/post-list.d.ts} +3 -2
- package/dist/src/post-list/post-list.d.ts.map +1 -0
- package/dist/src/post-list/post-list.js +6 -0
- package/dist/src/post-meta/index.d.ts +3 -0
- package/dist/src/post-meta/index.d.ts.map +1 -0
- package/dist/src/post-meta/index.js +1 -0
- package/dist/src/{postMeta/postMeta.d.ts → post-meta/post-meta.d.ts} +1 -1
- package/dist/src/post-meta/post-meta.d.ts.map +1 -0
- package/dist/src/{postMeta/postMeta.js → post-meta/post-meta.js} +3 -3
- package/dist/src/scheme/index.d.ts +1 -1
- package/dist/src/scheme/index.d.ts.map +1 -1
- package/dist/src/scheme/index.js +1 -1
- package/dist/src/scheme/{schemeSwitch.d.ts → scheme-switch.d.ts} +3 -2
- package/dist/src/scheme/scheme-switch.d.ts.map +1 -0
- package/dist/src/scheme/{schemeSwitch.js → scheme-switch.js} +7 -5
- package/dist/src/scheme/scheme.d.ts +0 -2
- package/dist/src/scheme/scheme.d.ts.map +1 -1
- package/dist/src/scheme/scheme.js +0 -2
- package/dist/src/scheme/switch.d.ts.map +1 -1
- package/dist/src/scheme/switch.js +12 -17
- package/dist/src/scrolls/scrolls.d.ts.map +1 -1
- package/dist/src/scrolls/scrolls.js +7 -9
- package/dist/src/skip-link/index.d.ts +2 -0
- package/dist/src/skip-link/index.d.ts.map +1 -0
- package/dist/src/skip-link/index.js +1 -0
- package/dist/src/{skipLink/skipLink.d.ts → skip-link/skip-link.d.ts} +1 -1
- package/dist/src/skip-link/skip-link.d.ts.map +1 -0
- package/dist/src/{skipLink/skipLink.js → skip-link/skip-link.js} +1 -1
- package/dist/src/table/index.d.ts.map +1 -1
- package/dist/src/table/table.d.ts +1 -1
- package/dist/src/table/table.d.ts.map +1 -1
- package/dist/src/table/table.js +3 -1
- package/highlight/highlight.ts +88 -118
- package/highlight/vite.ts +20 -10
- package/package.json +15 -16
- package/src/code/code.ts +18 -11
- package/src/code/index.ts +1 -0
- package/src/code/lines.d.ts +0 -5
- package/src/{codeBlock/codeBlock.ts → code-block/code-block.ts} +32 -14
- package/src/code-block/index.ts +3 -0
- package/src/copy/copy.ts +8 -17
- package/src/{copyTab/copyTab.ts → copy-tab/copy-tab.ts} +24 -8
- package/src/copy-tab/index.ts +12 -0
- package/src/diagram/diagram.ts +8 -4
- package/src/diagram/index.ts +1 -0
- package/src/footer/footer.ts +4 -2
- package/src/footer/index.ts +1 -0
- package/src/footnotes/footnotes.ts +26 -8
- package/src/footnotes/index.ts +1 -0
- package/src/header/header.ts +8 -5
- package/src/header/index.ts +1 -0
- package/src/heading/heading.ts +10 -2
- package/src/heading/index.ts +1 -0
- package/src/index.ts +23 -8
- package/src/nav-link/index.ts +3 -0
- package/src/{navLink/navLink.ts → nav-link/nav-link.ts} +14 -4
- package/src/note/index.ts +1 -0
- package/src/note/note.ts +6 -2
- package/src/pager/index.ts +1 -0
- package/src/pager/pager.ts +6 -2
- package/src/post-list/index.ts +3 -0
- package/src/post-list/post-list.ts +30 -0
- package/src/post-meta/index.ts +3 -0
- package/src/{postMeta/postMeta.ts → post-meta/post-meta.ts} +5 -2
- package/src/scheme/index.ts +3 -1
- package/src/scheme/{schemeSwitch.ts → scheme-switch.ts} +20 -8
- package/src/scheme/scheme.ts +3 -4
- package/src/scheme/switch.ts +9 -20
- package/src/scrolls/scrolls.ts +19 -13
- package/src/simple-rat.css +0 -47
- package/src/skip-link/index.ts +1 -0
- package/src/table/index.ts +1 -0
- package/src/table/table.ts +18 -9
- package/src/tokens.css +23 -32
- package/dist/src/codeBlock/codeBlock.d.ts.map +0 -1
- package/dist/src/codeBlock/index.d.ts +0 -3
- package/dist/src/codeBlock/index.d.ts.map +0 -1
- package/dist/src/codeBlock/index.js +0 -1
- package/dist/src/copyTab/copyTab.d.ts.map +0 -1
- package/dist/src/copyTab/index.d.ts +0 -3
- package/dist/src/copyTab/index.d.ts.map +0 -1
- package/dist/src/navLink/index.d.ts +0 -3
- package/dist/src/navLink/index.d.ts.map +0 -1
- package/dist/src/navLink/index.js +0 -1
- package/dist/src/navLink/navLink.d.ts.map +0 -1
- package/dist/src/postList/index.d.ts +0 -3
- package/dist/src/postList/index.d.ts.map +0 -1
- package/dist/src/postList/index.js +0 -1
- package/dist/src/postList/postList.d.ts.map +0 -1
- package/dist/src/postList/postList.js +0 -3
- package/dist/src/postMeta/index.d.ts +0 -3
- package/dist/src/postMeta/index.d.ts.map +0 -1
- package/dist/src/postMeta/index.js +0 -1
- package/dist/src/postMeta/postMeta.d.ts.map +0 -1
- package/dist/src/scheme/schemeSwitch.d.ts.map +0 -1
- package/dist/src/skipLink/index.d.ts +0 -2
- package/dist/src/skipLink/index.d.ts.map +0 -1
- package/dist/src/skipLink/index.js +0 -1
- package/dist/src/skipLink/skipLink.d.ts.map +0 -1
- package/src/codeBlock/index.ts +0 -2
- package/src/copyTab/index.ts +0 -2
- package/src/navLink/index.ts +0 -2
- package/src/postList/index.ts +0 -2
- package/src/postList/postList.ts +0 -19
- package/src/postMeta/index.ts +0 -2
- package/src/skipLink/index.ts +0 -1
- /package/src/{skipLink/skipLink.ts → skip-link/skip-link.ts} +0 -0
package/src/footer/index.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { Html, HtmlBuilder } from "foldkit/html";
|
|
2
2
|
|
|
3
3
|
/** A superscript number that jumps to the note numbered `noteNumber`; the note links back. */
|
|
4
|
-
export const refView = <Message>(
|
|
5
|
-
|
|
4
|
+
export const refView = <Message>(
|
|
5
|
+
noteNumber: number,
|
|
6
|
+
h: HtmlBuilder<Message>
|
|
7
|
+
): Html =>
|
|
8
|
+
h.sup(
|
|
9
|
+
[],
|
|
10
|
+
[
|
|
11
|
+
h.a(
|
|
12
|
+
[h.Href(`#fn-${noteNumber}`), h.Id(`ref-${noteNumber}`)],
|
|
13
|
+
[`${noteNumber}`]
|
|
14
|
+
),
|
|
15
|
+
]
|
|
16
|
+
);
|
|
6
17
|
|
|
7
18
|
/** Configuration for rendering the notes with `view`. */
|
|
8
19
|
export type ViewConfig = Readonly<{
|
|
@@ -12,7 +23,10 @@ export type ViewConfig = Readonly<{
|
|
|
12
23
|
|
|
13
24
|
/** The notes, numbered from 1, at the end of the page under a rule. Each ends in a `Back`
|
|
14
25
|
link named for the reference it returns to. */
|
|
15
|
-
export const view = <Message>(
|
|
26
|
+
export const view = <Message>(
|
|
27
|
+
config: ViewConfig,
|
|
28
|
+
h: HtmlBuilder<Message>
|
|
29
|
+
): Html =>
|
|
16
30
|
h.section(
|
|
17
31
|
[h.Class("footnotes"), h.AriaLabel("Footnotes")],
|
|
18
32
|
[
|
|
@@ -21,18 +35,22 @@ export const view = <Message>(config: ViewConfig, h: HtmlBuilder<Message>): Html
|
|
|
21
35
|
[],
|
|
22
36
|
config.notes.map((note, index) => {
|
|
23
37
|
const noteNumber = index + 1;
|
|
38
|
+
|
|
24
39
|
return h.li(
|
|
25
40
|
[h.Id(`fn-${noteNumber}`)],
|
|
26
41
|
[
|
|
27
42
|
...note,
|
|
28
43
|
" ",
|
|
29
44
|
h.a(
|
|
30
|
-
[
|
|
31
|
-
|
|
45
|
+
[
|
|
46
|
+
h.Href(`#ref-${noteNumber}`),
|
|
47
|
+
h.AriaLabel(`Back to reference ${noteNumber}`),
|
|
48
|
+
],
|
|
49
|
+
["Back"]
|
|
32
50
|
),
|
|
33
|
-
]
|
|
51
|
+
]
|
|
34
52
|
);
|
|
35
|
-
})
|
|
53
|
+
})
|
|
36
54
|
),
|
|
37
|
-
]
|
|
55
|
+
]
|
|
38
56
|
);
|
package/src/footnotes/index.ts
CHANGED
package/src/header/header.ts
CHANGED
|
@@ -3,22 +3,25 @@ import type { Html, HtmlBuilder } from "foldkit/html";
|
|
|
3
3
|
/** Configuration for rendering the header with `view`. */
|
|
4
4
|
export type ViewConfig = Readonly<{
|
|
5
5
|
/** `NavLink`s, and optionally a `SchemeSwitch` last. */
|
|
6
|
-
items:
|
|
6
|
+
items: readonly Html[];
|
|
7
7
|
}>;
|
|
8
8
|
|
|
9
9
|
/** The page's header: a nav named "Primary navigation", a line of lowercase links separated
|
|
10
10
|
by middots, then a rule. Each item after the first sits in a `span` with its middot, so a
|
|
11
11
|
wrapped line starts with the middot instead of ending on one. */
|
|
12
|
-
export const view = <Message>(
|
|
12
|
+
export const view = <Message>(
|
|
13
|
+
config: ViewConfig,
|
|
14
|
+
h: HtmlBuilder<Message>
|
|
15
|
+
): Html =>
|
|
13
16
|
h.header(
|
|
14
17
|
[],
|
|
15
18
|
[
|
|
16
19
|
h.nav(
|
|
17
20
|
[h.AriaLabel("Primary navigation")],
|
|
18
21
|
config.items.flatMap((item, index) =>
|
|
19
|
-
index === 0 ? [item] : [" ", h.span([], ["· ", item])]
|
|
20
|
-
)
|
|
22
|
+
index === 0 ? [item] : [" ", h.span([], ["· ", item])]
|
|
23
|
+
)
|
|
21
24
|
),
|
|
22
25
|
h.hr([]),
|
|
23
|
-
]
|
|
26
|
+
]
|
|
24
27
|
);
|
package/src/header/index.ts
CHANGED
package/src/heading/heading.ts
CHANGED
|
@@ -10,12 +10,20 @@ export type ViewConfig = Readonly<{
|
|
|
10
10
|
|
|
11
11
|
/** A section heading with a `#` link to itself, shown on hover and focus. The page title is
|
|
12
12
|
a plain `h1`. */
|
|
13
|
-
export const view = <Message>(
|
|
13
|
+
export const view = <Message>(
|
|
14
|
+
config: ViewConfig,
|
|
15
|
+
h: HtmlBuilder<Message>
|
|
16
|
+
): Html => {
|
|
14
17
|
const { level, id, text } = config;
|
|
18
|
+
|
|
15
19
|
const children: ReadonlyArray<Html | string> = [
|
|
16
20
|
text,
|
|
17
21
|
" ",
|
|
18
|
-
h.a(
|
|
22
|
+
h.a(
|
|
23
|
+
[h.Class("self"), h.Href(`#${id}`), h.AriaLabel(`Link to ${text}`)],
|
|
24
|
+
["#"]
|
|
25
|
+
),
|
|
19
26
|
];
|
|
27
|
+
|
|
20
28
|
return level === 2 ? h.h2([h.Id(id)], children) : h.h3([h.Id(id)], children);
|
|
21
29
|
};
|
package/src/heading/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
|
-
// simple rat's Foldkit components. Each renders the markup simple-rat.css styles; plain
|
|
2
|
-
// elements (paragraphs, lists, quotes, kbd, mark, details) need no component.
|
|
3
1
|
export * as Code from "./code/index.ts";
|
|
4
|
-
|
|
5
|
-
export * as
|
|
2
|
+
|
|
3
|
+
export * as CodeBlock from "./code-block/index.ts";
|
|
4
|
+
|
|
5
|
+
export * as CopyTab from "./copy-tab/index.ts";
|
|
6
|
+
|
|
6
7
|
export * as Diagram from "./diagram/index.ts";
|
|
8
|
+
|
|
7
9
|
export * as Footer from "./footer/index.ts";
|
|
10
|
+
|
|
8
11
|
export * as Footnotes from "./footnotes/index.ts";
|
|
12
|
+
|
|
9
13
|
export * as Header from "./header/index.ts";
|
|
14
|
+
|
|
10
15
|
export * as Heading from "./heading/index.ts";
|
|
11
|
-
|
|
16
|
+
|
|
17
|
+
export * as NavLink from "./nav-link/index.ts";
|
|
18
|
+
|
|
12
19
|
export * as Note from "./note/index.ts";
|
|
20
|
+
|
|
13
21
|
export * as Pager from "./pager/index.ts";
|
|
14
|
-
|
|
15
|
-
export * as
|
|
22
|
+
|
|
23
|
+
export * as PostList from "./post-list/index.ts";
|
|
24
|
+
|
|
25
|
+
export * as PostMeta from "./post-meta/index.ts";
|
|
26
|
+
|
|
16
27
|
export * as Scheme from "./scheme/index.ts";
|
|
28
|
+
|
|
17
29
|
export * as Scrolls from "./scrolls/index.ts";
|
|
18
|
-
|
|
30
|
+
|
|
31
|
+
export * as SkipLink from "./skip-link/index.ts";
|
|
32
|
+
|
|
19
33
|
export * as Swatch from "./swatch/index.ts";
|
|
34
|
+
|
|
20
35
|
export * as Table from "./table/index.ts";
|
|
@@ -11,8 +11,18 @@ export type ViewConfig = Readonly<{
|
|
|
11
11
|
}>;
|
|
12
12
|
|
|
13
13
|
/** A link in the header nav. Nav links never turn visited purple. */
|
|
14
|
-
export const view = <Message>(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
export const view = <Message>(
|
|
15
|
+
config: ViewConfig,
|
|
16
|
+
h: HtmlBuilder<Message>
|
|
17
|
+
): Html => {
|
|
18
|
+
const pageAttributes =
|
|
19
|
+
config.current === "Page" ? [h.AriaCurrent("page")] : [];
|
|
20
|
+
|
|
21
|
+
const sectionAttributes =
|
|
22
|
+
config.current === "Section" ? [h.AriaCurrent("true")] : [];
|
|
23
|
+
|
|
24
|
+
return h.a(
|
|
25
|
+
[h.Href(config.href), ...pageAttributes, ...sectionAttributes],
|
|
26
|
+
[config.label]
|
|
27
|
+
);
|
|
18
28
|
};
|
package/src/note/index.ts
CHANGED
package/src/note/note.ts
CHANGED
|
@@ -10,10 +10,14 @@ export type ViewConfig = Readonly<{
|
|
|
10
10
|
|
|
11
11
|
/** A ruled box for the thing a reader must not miss, its first word "Note." (or "Warning.")
|
|
12
12
|
in bold; at most one per screen. */
|
|
13
|
-
export const view = <Message>(
|
|
13
|
+
export const view = <Message>(
|
|
14
|
+
config: ViewConfig,
|
|
15
|
+
h: HtmlBuilder<Message>
|
|
16
|
+
): Html => {
|
|
14
17
|
const { isWarn = false, body } = config;
|
|
18
|
+
|
|
15
19
|
return h.aside(
|
|
16
20
|
[h.Class(isWarn ? "note warn" : "note")],
|
|
17
|
-
[h.p([], [h.strong([], [isWarn ? "Warning." : "Note."]), " ", ...body])]
|
|
21
|
+
[h.p([], [h.strong([], [isWarn ? "Warning." : "Note."]), " ", ...body])]
|
|
18
22
|
);
|
|
19
23
|
};
|
package/src/pager/index.ts
CHANGED
package/src/pager/pager.ts
CHANGED
|
@@ -13,8 +13,12 @@ export type ViewConfig = Readonly<{
|
|
|
13
13
|
|
|
14
14
|
/** Older and newer links at the end of a post, then the way back to all posts. A missing
|
|
15
15
|
neighbour becomes a muted line saying so. */
|
|
16
|
-
export const view = <Message>(
|
|
16
|
+
export const view = <Message>(
|
|
17
|
+
config: ViewConfig,
|
|
18
|
+
h: HtmlBuilder<Message>
|
|
19
|
+
): Html => {
|
|
17
20
|
const { newer, older, all } = config;
|
|
21
|
+
|
|
18
22
|
return h.nav(
|
|
19
23
|
[h.Class("pager"), h.AriaLabel("Older and newer posts")],
|
|
20
24
|
[
|
|
@@ -25,6 +29,6 @@ export const view = <Message>(config: ViewConfig, h: HtmlBuilder<Message>): Html
|
|
|
25
29
|
? h.p([h.Class("muted")], ["This is the oldest post."])
|
|
26
30
|
: h.p([], ["Older: ", h.a([h.Href(older.href)], [older.label])]),
|
|
27
31
|
h.p([], [h.a([h.Href(all.href)], [all.label])]),
|
|
28
|
-
]
|
|
32
|
+
]
|
|
29
33
|
);
|
|
30
34
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Html, HtmlBuilder } from "foldkit/html";
|
|
2
|
+
|
|
3
|
+
export type Entry = Readonly<{
|
|
4
|
+
/** ISO date. */
|
|
5
|
+
date: string;
|
|
6
|
+
title: string;
|
|
7
|
+
href: string;
|
|
8
|
+
}>;
|
|
9
|
+
|
|
10
|
+
/** Configuration for rendering a post list with `view`. */
|
|
11
|
+
export type ViewConfig = Readonly<{ posts: readonly Entry[] }>;
|
|
12
|
+
|
|
13
|
+
/** A list of posts: date, then title, in two columns. */
|
|
14
|
+
export const view = <Message>(
|
|
15
|
+
config: ViewConfig,
|
|
16
|
+
h: HtmlBuilder<Message>
|
|
17
|
+
): Html =>
|
|
18
|
+
h.ul(
|
|
19
|
+
[h.Class("posts")],
|
|
20
|
+
config.posts.map((post) =>
|
|
21
|
+
h.keyed("li")(
|
|
22
|
+
post.href,
|
|
23
|
+
[],
|
|
24
|
+
[
|
|
25
|
+
h.time([h.Datetime(post.date)], [post.date]),
|
|
26
|
+
h.a([h.Href(post.href)], [post.title]),
|
|
27
|
+
]
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
);
|
|
@@ -10,7 +10,10 @@ export type ViewConfig = Readonly<{
|
|
|
10
10
|
}>;
|
|
11
11
|
|
|
12
12
|
/** Everything about a post, on one muted line under its title: the date, then the rest. */
|
|
13
|
-
export const view = <Message>(
|
|
13
|
+
export const view = <Message>(
|
|
14
|
+
config: ViewConfig,
|
|
15
|
+
h: HtmlBuilder<Message>
|
|
16
|
+
): Html =>
|
|
14
17
|
h.p(
|
|
15
18
|
[h.Class("meta")],
|
|
16
19
|
[
|
|
@@ -19,5 +22,5 @@ export const view = <Message>(config: ViewConfig, h: HtmlBuilder<Message>): Html
|
|
|
19
22
|
onEmpty: () => [],
|
|
20
23
|
onNonEmpty: (body) => [" · ", ...body],
|
|
21
24
|
}),
|
|
22
|
-
]
|
|
25
|
+
]
|
|
23
26
|
);
|
package/src/scheme/index.ts
CHANGED
|
@@ -3,11 +3,20 @@ import type { Html } from "foldkit/html";
|
|
|
3
3
|
import { defineView } from "foldkit/submodel";
|
|
4
4
|
|
|
5
5
|
import type { Scheme } from "./scheme.ts";
|
|
6
|
-
import { Message
|
|
6
|
+
import { Message } from "./switch.ts";
|
|
7
|
+
import type { Model } from "./switch.ts";
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
+
export {
|
|
10
|
+
Message,
|
|
11
|
+
Model,
|
|
12
|
+
PinScheme,
|
|
13
|
+
ReadScheme,
|
|
14
|
+
id,
|
|
15
|
+
init,
|
|
16
|
+
update,
|
|
17
|
+
} from "./switch.ts";
|
|
9
18
|
|
|
10
|
-
|
|
19
|
+
export type { InitConfig } from "./switch.ts";
|
|
11
20
|
|
|
12
21
|
const CHOICES: ReadonlyArray<Readonly<{ scheme: Scheme; label: string }>> = [
|
|
13
22
|
{ scheme: "System", label: "system" },
|
|
@@ -31,13 +40,16 @@ export const view = defineView<Model, Message>((model, h): Html =>
|
|
|
31
40
|
onClick: Message.SelectedScheme({ scheme: choice }),
|
|
32
41
|
toView: ({ button }) =>
|
|
33
42
|
h.button(
|
|
34
|
-
[
|
|
35
|
-
|
|
43
|
+
[
|
|
44
|
+
...button,
|
|
45
|
+
h.AriaPressed(choice === model.scheme ? "true" : "false"),
|
|
46
|
+
],
|
|
47
|
+
[label]
|
|
36
48
|
),
|
|
37
49
|
},
|
|
38
|
-
h
|
|
50
|
+
h
|
|
39
51
|
),
|
|
40
52
|
]),
|
|
41
|
-
]
|
|
42
|
-
)
|
|
53
|
+
]
|
|
54
|
+
)
|
|
43
55
|
);
|
package/src/scheme/scheme.ts
CHANGED
|
@@ -3,23 +3,22 @@ import { Match, Option, Schema } from "effect";
|
|
|
3
3
|
/** The colour scheme: `Light` or `Dark` pinned on `<html data-scheme>`, or `System`, which
|
|
4
4
|
follows the reader's system in CSS alone. */
|
|
5
5
|
export const Scheme = Schema.Literals(["System", "Light", "Dark"]);
|
|
6
|
+
|
|
6
7
|
export type Scheme = typeof Scheme.Type;
|
|
7
8
|
|
|
8
|
-
/** The `data-scheme` value a scheme pins, or none for `System`. */
|
|
9
9
|
export const toPinnedValue = (scheme: Scheme): Option.Option<string> =>
|
|
10
10
|
Match.value(scheme).pipe(
|
|
11
11
|
Match.withReturnType<Option.Option<string>>(),
|
|
12
12
|
Match.when("System", () => Option.none()),
|
|
13
13
|
Match.when("Light", () => Option.some("light")),
|
|
14
14
|
Match.when("Dark", () => Option.some("dark")),
|
|
15
|
-
Match.exhaustive
|
|
15
|
+
Match.exhaustive
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
/** The scheme a `data-scheme` value pins. Anything else, or nothing, is `System`. */
|
|
19
18
|
export const fromPinnedValue = (value: string | null | undefined): Scheme =>
|
|
20
19
|
Match.value(value).pipe(
|
|
21
20
|
Match.withReturnType<Scheme>(),
|
|
22
21
|
Match.when("light", () => "Light"),
|
|
23
22
|
Match.when("dark", () => "Dark"),
|
|
24
|
-
Match.orElse(() => "System")
|
|
23
|
+
Match.orElse(() => "System")
|
|
25
24
|
);
|
package/src/scheme/switch.ts
CHANGED
|
@@ -7,20 +7,14 @@ import type * as Update from "foldkit/update";
|
|
|
7
7
|
import { Scheme, fromPinnedValue, toPinnedValue } from "./scheme.ts";
|
|
8
8
|
import { SCHEME_ATTRIBUTE, SCHEME_STORAGE_KEY } from "./script.ts";
|
|
9
9
|
|
|
10
|
-
// The scheme switch without its view, the same file in every system that has it; the view
|
|
11
|
-
// is the system's own, in schemeSwitch.ts, which also passes all of this on.
|
|
12
|
-
|
|
13
|
-
// MODEL
|
|
14
|
-
|
|
15
10
|
/** Schema for the scheme switch: its id, and the scheme in force as far as the page has
|
|
16
11
|
seen. */
|
|
17
12
|
export const Model = Schema.Struct({
|
|
18
13
|
id: Schema.String,
|
|
19
14
|
scheme: Scheme,
|
|
20
15
|
});
|
|
21
|
-
export type Model = typeof Model.Type;
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
export type Model = typeof Model.Type;
|
|
24
18
|
|
|
25
19
|
/** Union of all Messages the scheme switch can produce. */
|
|
26
20
|
export const Message = defineMessageUnion({
|
|
@@ -28,9 +22,8 @@ export const Message = defineMessageUnion({
|
|
|
28
22
|
CompletedPinScheme: {},
|
|
29
23
|
CompletedReadScheme: { scheme: Scheme },
|
|
30
24
|
});
|
|
31
|
-
export type Message = typeof Message.Type;
|
|
32
25
|
|
|
33
|
-
|
|
26
|
+
export type Message = typeof Message.Type;
|
|
34
27
|
|
|
35
28
|
/** Pins a scheme on `<html data-scheme>` and remembers it on this device in `localStorage`
|
|
36
29
|
under the key `schemeScript` reads; `System` removes both. The attribute is written first,
|
|
@@ -40,7 +33,7 @@ export const PinScheme = Command.define("PinScheme", {
|
|
|
40
33
|
args: { scheme: Scheme },
|
|
41
34
|
messages: [Message.CompletedPinScheme],
|
|
42
35
|
execute: ({ scheme }) =>
|
|
43
|
-
Effect.try(() =>
|
|
36
|
+
Effect.try(() => {
|
|
44
37
|
Option.match(toPinnedValue(scheme), {
|
|
45
38
|
onNone: () => {
|
|
46
39
|
document.documentElement.removeAttribute(SCHEME_ATTRIBUTE);
|
|
@@ -50,8 +43,8 @@ export const PinScheme = Command.define("PinScheme", {
|
|
|
50
43
|
document.documentElement.setAttribute(SCHEME_ATTRIBUTE, value);
|
|
51
44
|
localStorage.setItem(SCHEME_STORAGE_KEY, value);
|
|
52
45
|
},
|
|
53
|
-
})
|
|
54
|
-
).pipe(Effect.ignore, Effect.as(Message.CompletedPinScheme())),
|
|
46
|
+
});
|
|
47
|
+
}).pipe(Effect.ignore, Effect.as(Message.CompletedPinScheme())),
|
|
55
48
|
});
|
|
56
49
|
|
|
57
50
|
/** Reads the scheme in force from `<html data-scheme>`: what `schemeScript` pinned before
|
|
@@ -60,13 +53,13 @@ export const ReadScheme = Command.define("ReadScheme", {
|
|
|
60
53
|
messages: [Message.CompletedReadScheme],
|
|
61
54
|
execute: Effect.sync(() =>
|
|
62
55
|
Message.CompletedReadScheme({
|
|
63
|
-
scheme: fromPinnedValue(
|
|
64
|
-
|
|
56
|
+
scheme: fromPinnedValue(
|
|
57
|
+
document.documentElement.getAttribute(SCHEME_ATTRIBUTE)
|
|
58
|
+
),
|
|
59
|
+
})
|
|
65
60
|
),
|
|
66
61
|
});
|
|
67
62
|
|
|
68
|
-
// INIT
|
|
69
|
-
|
|
70
63
|
/** Configuration for creating a switch with `init`: its id, unique in the document. */
|
|
71
64
|
export type InitConfig = Readonly<{ id: string }>;
|
|
72
65
|
|
|
@@ -78,13 +71,9 @@ export const init = (config: InitConfig): Update.Return<Model, Message> => ({
|
|
|
78
71
|
commands: [ReadScheme()],
|
|
79
72
|
});
|
|
80
73
|
|
|
81
|
-
// ACCESSORS
|
|
82
|
-
|
|
83
74
|
/** The switch's id. */
|
|
84
75
|
export const id = (model: Model): string => model.id;
|
|
85
76
|
|
|
86
|
-
// UPDATE
|
|
87
|
-
|
|
88
77
|
/** Processes a scheme switch Message and returns the next Model and Commands. */
|
|
89
78
|
export const update = (model: Model, message: Message) =>
|
|
90
79
|
Message.match<Update.Return<Model, Message>>(message, {
|
package/src/scrolls/scrolls.ts
CHANGED
|
@@ -2,13 +2,10 @@ import { Effect, Option, Schema } from "effect";
|
|
|
2
2
|
import { defineMessageUnion } from "foldkit/message";
|
|
3
3
|
import * as Mount from "foldkit/mount";
|
|
4
4
|
|
|
5
|
-
// MESSAGE
|
|
6
|
-
|
|
7
5
|
/** What the Mount reports: it is watching. Nothing in a Model follows it. */
|
|
8
6
|
export const Message = defineMessageUnion({ CompletedWatchOverflow: {} });
|
|
9
|
-
export type Message = typeof Message.Type;
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
export type Message = typeof Message.Type;
|
|
12
9
|
|
|
13
10
|
/** Whether a block is wider than its box and scrolls sideways, checked when it mounts and
|
|
14
11
|
whenever its own box changes size, as when the window resizes. A font arriving that
|
|
@@ -23,34 +20,43 @@ export const WatchOverflow = Mount.define("WatchOverflow", {
|
|
|
23
20
|
Effect.gen(function* () {
|
|
24
21
|
yield* Effect.acquireRelease(
|
|
25
22
|
Effect.sync(() => {
|
|
23
|
+
const clear = () => {
|
|
24
|
+
element.removeAttribute("tabindex");
|
|
25
|
+
|
|
26
|
+
if (Option.isSome(maybeName)) {
|
|
27
|
+
element.removeAttribute("role");
|
|
28
|
+
element.removeAttribute("aria-label");
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
26
32
|
const check = () => {
|
|
27
33
|
if (element.scrollWidth > element.clientWidth) {
|
|
28
34
|
element.setAttribute("tabindex", "0");
|
|
35
|
+
|
|
29
36
|
if (Option.isSome(maybeName)) {
|
|
30
37
|
element.setAttribute("role", "region");
|
|
31
|
-
element.setAttribute(
|
|
38
|
+
element.setAttribute(
|
|
39
|
+
"aria-label",
|
|
40
|
+
`Code: ${maybeName.value}, scrolls sideways`
|
|
41
|
+
);
|
|
32
42
|
}
|
|
33
43
|
} else {
|
|
34
44
|
clear();
|
|
35
45
|
}
|
|
36
46
|
};
|
|
37
|
-
|
|
38
|
-
element.removeAttribute("tabindex");
|
|
39
|
-
if (Option.isSome(maybeName)) {
|
|
40
|
-
element.removeAttribute("role");
|
|
41
|
-
element.removeAttribute("aria-label");
|
|
42
|
-
}
|
|
43
|
-
};
|
|
47
|
+
|
|
44
48
|
const resized = new ResizeObserver(check);
|
|
45
49
|
resized.observe(element);
|
|
46
50
|
check();
|
|
51
|
+
|
|
47
52
|
return () => {
|
|
48
53
|
resized.disconnect();
|
|
49
54
|
clear();
|
|
50
55
|
};
|
|
51
56
|
}),
|
|
52
|
-
(stop) => Effect.sync(stop)
|
|
57
|
+
(stop) => Effect.sync(stop)
|
|
53
58
|
);
|
|
59
|
+
|
|
54
60
|
return Message.CompletedWatchOverflow();
|
|
55
61
|
}),
|
|
56
62
|
});
|