@fuzdev/fuz_ui 0.192.0 โ 0.193.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/dist/ApiIndex.svelte +3 -3
- package/dist/ApiModule.svelte +2 -2
- package/dist/Docs.svelte +4 -4
- package/dist/DocsMenu.svelte +3 -3
- package/dist/DocsMenu.svelte.d.ts.map +1 -1
- package/dist/DocsTertiaryNav.svelte +7 -7
- package/dist/DocsTertiaryNav.svelte.d.ts +1 -1
- package/dist/TomeContent.svelte +2 -2
- package/dist/TomeHeader.svelte +12 -11
- package/dist/TomeHeader.svelte.d.ts.map +1 -1
- package/dist/TomeLink.svelte +13 -6
- package/dist/TomeLink.svelte.d.ts +1 -1
- package/dist/TomeLink.svelte.d.ts.map +1 -1
- package/dist/contextmenu_state.svelte.js +1 -2
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +1 -6
- package/dist/tome.d.ts +8 -3
- package/dist/tome.d.ts.map +1 -1
- package/dist/tome.js +24 -8
- package/package.json +4 -4
- package/src/lib/contextmenu_state.svelte.ts +2 -2
- package/src/lib/csp.ts +2 -6
- package/src/lib/tome.ts +25 -8
package/dist/ApiIndex.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {library_context, type Library} from './library.svelte.js';
|
|
3
|
-
import {
|
|
3
|
+
import {tome_get_by_slug, type Tome} from './tome.js';
|
|
4
4
|
import TomeContent from './TomeContent.svelte';
|
|
5
5
|
import TomeLink from './TomeLink.svelte';
|
|
6
6
|
import DocsSearch from './DocsSearch.svelte';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
const {
|
|
12
12
|
library = library_context.get(),
|
|
13
|
-
tome =
|
|
13
|
+
tome = tome_get_by_slug('api'),
|
|
14
14
|
minimal = false,
|
|
15
15
|
}: {
|
|
16
16
|
/**
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<TomeContent {tome}>
|
|
41
41
|
{#if minimal}
|
|
42
42
|
<section>
|
|
43
|
-
<p>Browse the full <TomeLink
|
|
43
|
+
<p>Browse the full <TomeLink slug="api" /> docs.</p>
|
|
44
44
|
</section>
|
|
45
45
|
{:else}
|
|
46
46
|
<section>
|
package/dist/ApiModule.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {library_context, type Library} from './library.svelte.js';
|
|
3
|
-
import {
|
|
3
|
+
import {tome_get_by_slug, type Tome} from './tome.js';
|
|
4
4
|
import TomeContent from './TomeContent.svelte';
|
|
5
5
|
import TomeSection from './TomeSection.svelte';
|
|
6
6
|
import TomeSectionHeader from './TomeSectionHeader.svelte';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
const {
|
|
14
14
|
module_path: module_path_param,
|
|
15
15
|
library = library_context.get(),
|
|
16
|
-
tome =
|
|
16
|
+
tome = tome_get_by_slug('api'),
|
|
17
17
|
}: {
|
|
18
18
|
/**
|
|
19
19
|
* The module path parameter from the route (e.g., "lib/Button.svelte").
|
package/dist/Docs.svelte
CHANGED
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
} = $props();
|
|
28
28
|
|
|
29
29
|
// TODO this API is messy, inconsistent usage of props/context
|
|
30
|
-
const
|
|
31
|
-
tomes_context.set(() =>
|
|
30
|
+
const tomes_by_slug = $derived(new Map(tomes.map((t) => [t.slug, t])));
|
|
31
|
+
tomes_context.set(() => tomes_by_slug);
|
|
32
32
|
|
|
33
33
|
// TODO @many dialog navs - this is messy to satisfy SSR with the current design that puts the secondary nav in a dialog
|
|
34
34
|
const TERTIARY_NAV_BREAKPOINT = 1000;
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
{/key}
|
|
70
70
|
<!-- TODO @many dialog navs -->
|
|
71
71
|
{#if !innerWidth.current || innerWidth.current > TERTIARY_NAV_BREAKPOINT}
|
|
72
|
-
<DocsTertiaryNav {tomes} {
|
|
72
|
+
<DocsTertiaryNav {tomes} {tomes_by_slug} />
|
|
73
73
|
{/if}
|
|
74
74
|
<section class="box">
|
|
75
75
|
<DocsFooter {library} root_url="https://www.fuz.dev/">
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
</div>
|
|
103
103
|
<div class="px_lg pb_xl">
|
|
104
104
|
<DocsSecondaryNav {tomes} sidebar={false} />
|
|
105
|
-
<DocsTertiaryNav {tomes} {
|
|
105
|
+
<DocsTertiaryNav {tomes} {tomes_by_slug} sidebar={false} />
|
|
106
106
|
</div>
|
|
107
107
|
</div>
|
|
108
108
|
</Dialog>
|
package/dist/DocsMenu.svelte
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import type {SvelteHTMLElements} from 'svelte/elements';
|
|
6
6
|
|
|
7
7
|
import DocsList from './DocsList.svelte';
|
|
8
|
-
import {
|
|
8
|
+
import {tome_to_pathname, tome_to_title, type Tome} from './tome.js';
|
|
9
9
|
import DocsMenuHeader from './DocsMenuHeader.svelte';
|
|
10
10
|
|
|
11
11
|
const {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
>{/if}
|
|
38
38
|
<ul class="unstyled">
|
|
39
39
|
{#each tomes as item (item)}
|
|
40
|
-
{@const pathname =
|
|
40
|
+
{@const pathname = tome_to_pathname(item)}
|
|
41
41
|
<li role="none" transition:slide>
|
|
42
42
|
<a class="menuitem" href={pathname} class:selected={pathname === page.url.pathname}
|
|
43
|
-
><div class="ellipsis">{item
|
|
43
|
+
><div class="ellipsis">{tome_to_title(item)}</div></a
|
|
44
44
|
>
|
|
45
45
|
</li>
|
|
46
46
|
{/each}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocsMenu.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsMenu.svelte"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAGxD,OAAO,
|
|
1
|
+
{"version":3,"file":"DocsMenu.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/DocsMenu.svelte"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAkC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAGpE,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,KAAK,CAAC,GAAG;IACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAkDH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type {SvelteHTMLElements} from 'svelte/elements';
|
|
4
4
|
|
|
5
5
|
import DocsPageLinks from './DocsPageLinks.svelte';
|
|
6
|
-
import {
|
|
6
|
+
import {tome_to_pathname, Tome} from './tome.js';
|
|
7
7
|
import {docs_links_context} from './docs_helpers.svelte.js';
|
|
8
8
|
import {library_context} from './library.svelte.js';
|
|
9
9
|
import TomeLink from './TomeLink.svelte';
|
|
@@ -12,20 +12,20 @@
|
|
|
12
12
|
|
|
13
13
|
const {
|
|
14
14
|
tomes,
|
|
15
|
-
|
|
15
|
+
tomes_by_slug,
|
|
16
16
|
sidebar = true,
|
|
17
17
|
...rest
|
|
18
18
|
}: SvelteHTMLElements['aside'] & {
|
|
19
19
|
tomes: Array<Tome>;
|
|
20
|
-
|
|
20
|
+
tomes_by_slug: Map<string, Tome>;
|
|
21
21
|
sidebar?: boolean; // TODO @many dialog navs (this shouldn't exist)
|
|
22
22
|
} = $props();
|
|
23
23
|
|
|
24
|
-
const selected_tome = $derived(tomes.find((t) =>
|
|
24
|
+
const selected_tome = $derived(tomes.find((t) => tome_to_pathname(t) === page.url.pathname));
|
|
25
25
|
|
|
26
26
|
const tomes_related_to_selected = $derived(
|
|
27
27
|
selected_tome?.related_tomes
|
|
28
|
-
.map((
|
|
28
|
+
.map((slug) => tomes_by_slug.get(slug))
|
|
29
29
|
.filter((t) => t !== undefined) ?? [],
|
|
30
30
|
);
|
|
31
31
|
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
<section class="related-section">
|
|
58
58
|
<h4 class="mb_sm">related tomes</h4>
|
|
59
59
|
<ul class="unstyled">
|
|
60
|
-
{#each tomes_related_to_selected as tome (tome.
|
|
61
|
-
<li><TomeLink
|
|
60
|
+
{#each tomes_related_to_selected as tome (tome.slug)}
|
|
61
|
+
<li><TomeLink slug={tome.slug} class="menuitem" /></li>
|
|
62
62
|
{/each}
|
|
63
63
|
</ul>
|
|
64
64
|
</section>
|
|
@@ -2,7 +2,7 @@ import type { SvelteHTMLElements } from 'svelte/elements';
|
|
|
2
2
|
import { Tome } from './tome.js';
|
|
3
3
|
type $$ComponentProps = SvelteHTMLElements['aside'] & {
|
|
4
4
|
tomes: Array<Tome>;
|
|
5
|
-
|
|
5
|
+
tomes_by_slug: Map<string, Tome>;
|
|
6
6
|
sidebar?: boolean;
|
|
7
7
|
};
|
|
8
8
|
declare const DocsTertiaryNav: import("svelte").Component<$$ComponentProps, {}, "">;
|
package/dist/TomeContent.svelte
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import TomeHeader from './TomeHeader.svelte';
|
|
7
7
|
import {tome_context, type Tome} from './tome.js';
|
|
8
|
-
import {DOCS_PATH_DEFAULT, docs_links_context
|
|
8
|
+
import {DOCS_PATH_DEFAULT, docs_links_context} from './docs_helpers.svelte.js';
|
|
9
9
|
import {intersect} from './intersect.svelte.js';
|
|
10
10
|
|
|
11
11
|
const {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
tome_context.set(() => tome);
|
|
26
26
|
|
|
27
|
-
const fragment = $derived(
|
|
27
|
+
const fragment = $derived(tome.slug);
|
|
28
28
|
|
|
29
29
|
const at_root = $derived(page.url.pathname === resolve(docs_path as any));
|
|
30
30
|
</script>
|
package/dist/TomeHeader.svelte
CHANGED
|
@@ -3,41 +3,42 @@
|
|
|
3
3
|
import {DEV} from 'esm-env';
|
|
4
4
|
import type {SvelteHTMLElements} from 'svelte/elements';
|
|
5
5
|
|
|
6
|
-
import {tome_context} from './tome.js';
|
|
6
|
+
import {tome_context, tome_to_title} from './tome.js';
|
|
7
7
|
import Hashlink from './Hashlink.svelte';
|
|
8
|
-
import {docs_links_context,
|
|
8
|
+
import {docs_links_context, to_docs_path_info} from './docs_helpers.svelte.js';
|
|
9
9
|
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
|
|
11
11
|
const props: SvelteHTMLElements['h1'] | SvelteHTMLElements['h2'] = $props();
|
|
12
12
|
|
|
13
13
|
const get_tome = tome_context.get();
|
|
14
|
-
if (DEV && !get_tome) throw Error('TomeHeader expects a tome in context');
|
|
14
|
+
if (DEV && !get_tome) throw Error('TomeHeader expects a tome in context');
|
|
15
15
|
const tome = $derived(get_tome());
|
|
16
16
|
|
|
17
17
|
const docs_links = docs_links_context.get();
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
const
|
|
19
|
+
// The slug is the route segment + anchor fragment; only the visible label uses `title`.
|
|
20
|
+
const fragment = $derived(tome.slug);
|
|
21
|
+
const title = $derived(tome_to_title(tome));
|
|
21
22
|
$effect(() => {
|
|
22
|
-
const id = docs_links.add(fragment,
|
|
23
|
+
const id = docs_links.add(fragment, title, page.url.pathname);
|
|
23
24
|
return () => docs_links.remove(id);
|
|
24
25
|
});
|
|
25
26
|
|
|
26
|
-
const {path, path_is_selected} = $derived(to_docs_path_info(
|
|
27
|
+
const {path, path_is_selected} = $derived(to_docs_path_info(fragment, page.url.pathname));
|
|
27
28
|
</script>
|
|
28
29
|
|
|
29
30
|
<svelte:element this={path_is_selected ? 'h1' : 'h2'} {...props} class="tome-header">
|
|
30
31
|
{#if path_is_selected}
|
|
31
|
-
{@render content(
|
|
32
|
+
{@render content(title)}
|
|
32
33
|
{:else}
|
|
33
34
|
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
|
|
34
|
-
<a href={path}>{@render content(
|
|
35
|
+
<a href={path}>{@render content(title)}</a>
|
|
35
36
|
{/if}
|
|
36
37
|
<Hashlink {fragment} />
|
|
37
38
|
</svelte:element>
|
|
38
39
|
|
|
39
|
-
{#snippet content(
|
|
40
|
-
{
|
|
40
|
+
{#snippet content(text: string)}
|
|
41
|
+
{text}
|
|
41
42
|
{/snippet}
|
|
42
43
|
|
|
43
44
|
<style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TomeHeader.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TomeHeader.svelte"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TomeHeader.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TomeHeader.svelte"],"names":[],"mappings":"AA2DA,QAAA,MAAM,UAAU,kGAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
package/dist/TomeLink.svelte
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
import {DEV} from 'esm-env';
|
|
3
3
|
import type {SvelteHTMLElements} from 'svelte/elements';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {tome_get_by_slug, tome_to_pathname, tome_to_title, tomes_context} from './tome.js';
|
|
6
6
|
import {DOCS_PATH_DEFAULT} from './docs_helpers.svelte.js';
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
-
|
|
9
|
+
slug,
|
|
10
10
|
docs_path = DOCS_PATH_DEFAULT,
|
|
11
11
|
hash,
|
|
12
12
|
children,
|
|
13
13
|
class: class_prop = 'chip',
|
|
14
14
|
...rest
|
|
15
15
|
}: SvelteHTMLElements['a'] & {
|
|
16
|
-
|
|
16
|
+
slug: string; // TODO type, generate from `tomes`?
|
|
17
17
|
docs_path?: string;
|
|
18
18
|
/** URL fragment to append, with or without the `#`. */
|
|
19
19
|
hash?: string;
|
|
@@ -21,14 +21,21 @@
|
|
|
21
21
|
|
|
22
22
|
if (DEV) {
|
|
23
23
|
$effect(() => {
|
|
24
|
-
|
|
24
|
+
tome_get_by_slug(slug); // throws if not found
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
// Default link text is the tome's display title, falling back to its `slug`.
|
|
29
|
+
const get_tomes = tomes_context.get_maybe();
|
|
30
|
+
const label = $derived.by(() => {
|
|
31
|
+
const tome = get_tomes?.().get(slug);
|
|
32
|
+
return tome ? tome_to_title(tome) : slug;
|
|
33
|
+
});
|
|
34
|
+
|
|
28
35
|
// TODO add contextmenu behavior
|
|
29
36
|
</script>
|
|
30
37
|
|
|
31
38
|
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
|
|
32
|
-
<a {...rest} class="tome-link {class_prop}" href={
|
|
33
|
-
>{#if children}{@render children()}{:else}{
|
|
39
|
+
<a {...rest} class="tome-link {class_prop}" href={tome_to_pathname(slug, docs_path, hash)}
|
|
40
|
+
>{#if children}{@render children()}{:else}{label}{/if}</a
|
|
34
41
|
>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TomeLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TomeLink.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAKvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;
|
|
1
|
+
{"version":3,"file":"TomeLink.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/TomeLink.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAKvD,KAAK,gBAAgB,GAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAsCH,QAAA,MAAM,QAAQ,sDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|
|
@@ -213,7 +213,7 @@ export class ContextmenuState {
|
|
|
213
213
|
do {
|
|
214
214
|
i.selected = true;
|
|
215
215
|
new_selections.unshift(i);
|
|
216
|
-
} while ((i = i.menu) && i.menu);
|
|
216
|
+
} while ((i = i.menu) && i.menu);
|
|
217
217
|
this.selections = new_selections;
|
|
218
218
|
}
|
|
219
219
|
collapse_selected() {
|
|
@@ -341,7 +341,6 @@ export const contextmenu_open = (target, x, y, contextmenu, options) => {
|
|
|
341
341
|
// `navigator.vibrate()` works with `ContextmenuRoot` but gets blocked by some browsers
|
|
342
342
|
// when used with `ContextmenuRootForSafariCompatibility` because its longpress
|
|
343
343
|
// workaround triggers from a timeout rather than a direct user interaction.
|
|
344
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
345
344
|
if (BROWSER && vibrate && navigator.vibrate) {
|
|
346
345
|
navigator.vibrate(CONTEXTMENU_OPEN_VIBRATE_DURATION);
|
|
347
346
|
}
|
package/dist/csp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csp.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AAIvD;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG;KACnC,CAAC,IAAI,YAAY,IAAI,aAAa,CAAC,CAAC,CAAC,SAAS,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;CACjG,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,4BAA4B,CAAC,CAAC;IAEhE;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAE/C;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE;SACV,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI;KACjD,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAS,0BAA+B,KAAG,
|
|
1
|
+
{"version":3,"file":"csp.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp.ts"],"names":[],"mappings":"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"}
|
package/dist/csp.js
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
*/
|
|
23
23
|
export const create_csp_directives = (options = {}) => {
|
|
24
24
|
const { replace_defaults = csp_directive_value_defaults, extend, overrides } = options;
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
26
25
|
if (replace_defaults === null) {
|
|
27
26
|
throw new Error(`Invalid value 'null' for options.replace_defaults. ` +
|
|
28
27
|
`Omit the option to use library defaults, or pass {} to start with no directives.`);
|
|
@@ -40,12 +39,10 @@ export const create_csp_directives = (options = {}) => {
|
|
|
40
39
|
// Stage 1: starting state from `replace_defaults`.
|
|
41
40
|
// `{}` starts blank โ every directive must come from `extend`/`overrides`.
|
|
42
41
|
for_each_directive(replace_defaults, 'replace_defaults', (directive, value) => {
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
44
42
|
if (value === null) {
|
|
45
43
|
throw new Error(`Invalid value 'null' for directive '${directive}' in options.replace_defaults. ` +
|
|
46
44
|
`Omit the key instead, or use \`overrides: { '${directive}': null }\` to remove.`);
|
|
47
45
|
}
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
49
46
|
if (value === undefined)
|
|
50
47
|
return;
|
|
51
48
|
assign(directive, value);
|
|
@@ -95,7 +92,6 @@ export const create_csp_directives = (options = {}) => {
|
|
|
95
92
|
for_each_directive(overrides, 'overrides', (directive, value) => {
|
|
96
93
|
if (value === null) {
|
|
97
94
|
delete directives[directive]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
|
|
98
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
99
95
|
}
|
|
100
96
|
else if (value !== undefined) {
|
|
101
97
|
assign(directive, value);
|
|
@@ -144,9 +140,8 @@ const is_none = (value) => Array.isArray(value) && value.length === 1 && value[0
|
|
|
144
140
|
* `Object.entries`.
|
|
145
141
|
*/
|
|
146
142
|
const for_each_directive = (source, source_label, fn) => {
|
|
147
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
148
143
|
if (source === null || typeof source !== 'object') {
|
|
149
|
-
const got = source === null ? 'null' : typeof source;
|
|
144
|
+
const got = source === null ? 'null' : typeof source;
|
|
150
145
|
throw new Error(`Invalid entry in options.${source_label}: expected an object, got ${got}.`);
|
|
151
146
|
}
|
|
152
147
|
for (const [key, value] of Object.entries(source)) {
|
package/dist/tome.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
export declare const Tome: z.ZodObject<{
|
|
4
|
-
|
|
4
|
+
slug: z.ZodString;
|
|
5
|
+
title: z.ZodOptional<z.ZodString>;
|
|
5
6
|
category: z.ZodString;
|
|
6
7
|
Component: z.ZodCustom<Component<any, any, string>, Component<any, any, string>>;
|
|
7
8
|
related_tomes: z.ZodArray<z.ZodString>;
|
|
@@ -12,13 +13,17 @@ export type Tome = z.infer<typeof Tome>;
|
|
|
12
13
|
/**
|
|
13
14
|
* @param hash - URL fragment to append, with or without the `#`
|
|
14
15
|
*/
|
|
15
|
-
export declare const
|
|
16
|
+
export declare const tome_to_pathname: (item: Tome | string, docs_path?: string, hash?: string) => string;
|
|
17
|
+
/**
|
|
18
|
+
* The display label for a tome โ its `title` if set, else its `slug`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const tome_to_title: (tome: Tome) => string;
|
|
16
21
|
export declare const tomes_context: {
|
|
17
22
|
get: (error_message?: string) => () => Map<string, Tome>;
|
|
18
23
|
get_maybe: () => (() => Map<string, Tome>) | undefined;
|
|
19
24
|
set: (value: () => Map<string, Tome>) => () => Map<string, Tome>;
|
|
20
25
|
};
|
|
21
|
-
export declare const
|
|
26
|
+
export declare const tome_get_by_slug: (slug: string) => Tome;
|
|
22
27
|
export declare const tome_context: {
|
|
23
28
|
get: (error_message?: string) => () => Tome;
|
|
24
29
|
get_maybe: () => (() => Tome) | undefined;
|
package/dist/tome.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tome.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,eAAO,MAAM,IAAI
|
|
1
|
+
{"version":3,"file":"tome.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,eAAO,MAAM,IAAI;;;;;;;;iBAoBf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC5B,MAAM,IAAI,GAAG,MAAM,EACnB,kBAA6B,EAC7B,OAAO,MAAM,KACX,MAIF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,KAAG,MAAiC,CAAC;AAE7E,eAAO,MAAM,aAAa;2CAAwB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;4BAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;uBAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,WAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;CAAG,CAAC;AAEvE,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,IAK/C,CAAC;AAEF,eAAO,MAAM,YAAY;2CAAwB,IAAI;4BAAJ,IAAI;uBAAJ,IAAI,WAAJ,IAAI;CAAG,CAAC"}
|
package/dist/tome.js
CHANGED
|
@@ -2,9 +2,21 @@ import { resolve } from '$app/paths';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { ensure_start } from '@fuzdev/fuz_util/string.js';
|
|
4
4
|
import { create_context } from './context_helpers.js';
|
|
5
|
-
import { DOCS_PATH_DEFAULT
|
|
5
|
+
import { DOCS_PATH_DEFAULT } from './docs_helpers.svelte.js';
|
|
6
6
|
export const Tome = z.object({
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Stable identifier and URL path segment โ must be a URL-safe slug
|
|
9
|
+
* (used directly as the route segment, the lookup key, and in
|
|
10
|
+
* `related_tomes` cross-references). Set `title` for the display label.
|
|
11
|
+
*/
|
|
12
|
+
slug: z.string(),
|
|
13
|
+
/**
|
|
14
|
+
* Human-readable display label shown in menus, headings, and links.
|
|
15
|
+
* Falls back to `slug` when omitted, so set `title` to give multi-word or
|
|
16
|
+
* specially cased tomes a readable label (e.g. `slug: 'vite-plugin'` โ
|
|
17
|
+
* `title: 'vite plugin'`).
|
|
18
|
+
*/
|
|
19
|
+
title: z.string().optional(),
|
|
8
20
|
// TODO maybe now this makes sense with mdz? summary: z.string(),
|
|
9
21
|
category: z.string(),
|
|
10
22
|
Component: z.custom(),
|
|
@@ -15,17 +27,21 @@ export const Tome = z.object({
|
|
|
15
27
|
/**
|
|
16
28
|
* @param hash - URL fragment to append, with or without the `#`
|
|
17
29
|
*/
|
|
18
|
-
export const
|
|
19
|
-
const
|
|
20
|
-
const path = docs_path + '/' +
|
|
30
|
+
export const tome_to_pathname = (item, docs_path = DOCS_PATH_DEFAULT, hash) => {
|
|
31
|
+
const slug = typeof item === 'string' ? item : item.slug;
|
|
32
|
+
const path = docs_path + '/' + slug;
|
|
21
33
|
return resolve((hash ? path + ensure_start(hash, '#') : path));
|
|
22
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* The display label for a tome โ its `title` if set, else its `slug`.
|
|
37
|
+
*/
|
|
38
|
+
export const tome_to_title = (tome) => tome.title ?? tome.slug;
|
|
23
39
|
export const tomes_context = create_context();
|
|
24
|
-
export const
|
|
40
|
+
export const tome_get_by_slug = (slug) => {
|
|
25
41
|
const get_tomes = tomes_context.get();
|
|
26
|
-
const tome = get_tomes().get(
|
|
42
|
+
const tome = get_tomes().get(slug);
|
|
27
43
|
if (!tome)
|
|
28
|
-
throw Error(`unable to find tome "${
|
|
44
|
+
throw Error(`unable to find tome "${slug}"`);
|
|
29
45
|
return tome;
|
|
30
46
|
};
|
|
31
47
|
export const tome_context = create_context();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.193.0",
|
|
4
4
|
"description": "Svelte UI library",
|
|
5
5
|
"tagline": "friendly user zystem",
|
|
6
6
|
"glyph": "๐งถ",
|
|
@@ -82,10 +82,10 @@
|
|
|
82
82
|
"@changesets/changelog-git": "^0.2.1",
|
|
83
83
|
"@fuzdev/fuz_code": "^0.45.1",
|
|
84
84
|
"@fuzdev/fuz_css": "^0.59.0",
|
|
85
|
-
"@fuzdev/fuz_util": "^0.
|
|
86
|
-
"@fuzdev/gro": "^0.
|
|
85
|
+
"@fuzdev/fuz_util": "^0.61.1",
|
|
86
|
+
"@fuzdev/gro": "^0.199.1",
|
|
87
87
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
88
|
-
"@ryanatkn/eslint-config": "^0.
|
|
88
|
+
"@ryanatkn/eslint-config": "^0.12.1",
|
|
89
89
|
"@sveltejs/acorn-typescript": "^1.0.9",
|
|
90
90
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
91
91
|
"@sveltejs/kit": "^2.55.0",
|
|
@@ -253,7 +253,7 @@ export class ContextmenuState {
|
|
|
253
253
|
do {
|
|
254
254
|
i.selected = true;
|
|
255
255
|
new_selections.unshift(i);
|
|
256
|
-
} while ((i = i.menu) && i.menu);
|
|
256
|
+
} while ((i = i.menu) && i.menu);
|
|
257
257
|
this.selections = new_selections;
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -418,7 +418,7 @@ export const contextmenu_open = (
|
|
|
418
418
|
// `navigator.vibrate()` works with `ContextmenuRoot` but gets blocked by some browsers
|
|
419
419
|
// when used with `ContextmenuRootForSafariCompatibility` because its longpress
|
|
420
420
|
// workaround triggers from a timeout rather than a direct user interaction.
|
|
421
|
-
|
|
421
|
+
|
|
422
422
|
if (BROWSER && vibrate && navigator.vibrate) {
|
|
423
423
|
navigator.vibrate(CONTEXTMENU_OPEN_VIBRATE_DURATION);
|
|
424
424
|
}
|
package/src/lib/csp.ts
CHANGED
|
@@ -89,7 +89,6 @@ export interface CreateCspDirectivesOptions {
|
|
|
89
89
|
export const create_csp_directives = (options: CreateCspDirectivesOptions = {}): CspDirectives => {
|
|
90
90
|
const {replace_defaults = csp_directive_value_defaults, extend, overrides} = options;
|
|
91
91
|
|
|
92
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
93
92
|
if (replace_defaults === null) {
|
|
94
93
|
throw new Error(
|
|
95
94
|
`Invalid value 'null' for options.replace_defaults. ` +
|
|
@@ -112,14 +111,13 @@ export const create_csp_directives = (options: CreateCspDirectivesOptions = {}):
|
|
|
112
111
|
// Stage 1: starting state from `replace_defaults`.
|
|
113
112
|
// `{}` starts blank โ every directive must come from `extend`/`overrides`.
|
|
114
113
|
for_each_directive(replace_defaults, 'replace_defaults', (directive, value) => {
|
|
115
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
116
114
|
if (value === null) {
|
|
117
115
|
throw new Error(
|
|
118
116
|
`Invalid value 'null' for directive '${directive}' in options.replace_defaults. ` +
|
|
119
117
|
`Omit the key instead, or use \`overrides: { '${directive}': null }\` to remove.`,
|
|
120
118
|
);
|
|
121
119
|
}
|
|
122
|
-
|
|
120
|
+
|
|
123
121
|
if (value === undefined) return;
|
|
124
122
|
assign(directive, value);
|
|
125
123
|
});
|
|
@@ -172,7 +170,6 @@ export const create_csp_directives = (options: CreateCspDirectivesOptions = {}):
|
|
|
172
170
|
for_each_directive(overrides, 'overrides', (directive, value) => {
|
|
173
171
|
if (value === null) {
|
|
174
172
|
delete directives[directive]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
|
|
175
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
176
173
|
} else if (value !== undefined) {
|
|
177
174
|
assign(directive, value);
|
|
178
175
|
}
|
|
@@ -242,9 +239,8 @@ const for_each_directive = <V>(
|
|
|
242
239
|
source_label: 'replace_defaults' | 'extend' | 'overrides',
|
|
243
240
|
fn: (directive: CspDirective, value: V) => void,
|
|
244
241
|
): void => {
|
|
245
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
246
242
|
if (source === null || typeof source !== 'object') {
|
|
247
|
-
const got = source === null ? 'null' : typeof source;
|
|
243
|
+
const got = source === null ? 'null' : typeof source;
|
|
248
244
|
throw new Error(`Invalid entry in options.${source_label}: expected an object, got ${got}.`);
|
|
249
245
|
}
|
|
250
246
|
for (const [key, value] of Object.entries(source)) {
|
package/src/lib/tome.ts
CHANGED
|
@@ -4,10 +4,22 @@ import {z} from 'zod';
|
|
|
4
4
|
import {ensure_start} from '@fuzdev/fuz_util/string.js';
|
|
5
5
|
|
|
6
6
|
import {create_context} from './context_helpers.js';
|
|
7
|
-
import {DOCS_PATH_DEFAULT
|
|
7
|
+
import {DOCS_PATH_DEFAULT} from './docs_helpers.svelte.js';
|
|
8
8
|
|
|
9
9
|
export const Tome = z.object({
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Stable identifier and URL path segment โ must be a URL-safe slug
|
|
12
|
+
* (used directly as the route segment, the lookup key, and in
|
|
13
|
+
* `related_tomes` cross-references). Set `title` for the display label.
|
|
14
|
+
*/
|
|
15
|
+
slug: z.string(),
|
|
16
|
+
/**
|
|
17
|
+
* Human-readable display label shown in menus, headings, and links.
|
|
18
|
+
* Falls back to `slug` when omitted, so set `title` to give multi-word or
|
|
19
|
+
* specially cased tomes a readable label (e.g. `slug: 'vite-plugin'` โ
|
|
20
|
+
* `title: 'vite plugin'`).
|
|
21
|
+
*/
|
|
22
|
+
title: z.string().optional(),
|
|
11
23
|
// TODO maybe now this makes sense with mdz? summary: z.string(),
|
|
12
24
|
category: z.string(),
|
|
13
25
|
Component: z.custom<Component<any, any>>(),
|
|
@@ -20,22 +32,27 @@ export type Tome = z.infer<typeof Tome>;
|
|
|
20
32
|
/**
|
|
21
33
|
* @param hash - URL fragment to append, with or without the `#`
|
|
22
34
|
*/
|
|
23
|
-
export const
|
|
35
|
+
export const tome_to_pathname = (
|
|
24
36
|
item: Tome | string,
|
|
25
37
|
docs_path = DOCS_PATH_DEFAULT,
|
|
26
38
|
hash?: string,
|
|
27
39
|
): string => {
|
|
28
|
-
const
|
|
29
|
-
const path = docs_path + '/' +
|
|
40
|
+
const slug = typeof item === 'string' ? item : item.slug;
|
|
41
|
+
const path = docs_path + '/' + slug;
|
|
30
42
|
return resolve((hash ? path + ensure_start(hash, '#') : path) as any);
|
|
31
43
|
};
|
|
32
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The display label for a tome โ its `title` if set, else its `slug`.
|
|
47
|
+
*/
|
|
48
|
+
export const tome_to_title = (tome: Tome): string => tome.title ?? tome.slug;
|
|
49
|
+
|
|
33
50
|
export const tomes_context = create_context<() => Map<string, Tome>>();
|
|
34
51
|
|
|
35
|
-
export const
|
|
52
|
+
export const tome_get_by_slug = (slug: string): Tome => {
|
|
36
53
|
const get_tomes = tomes_context.get();
|
|
37
|
-
const tome = get_tomes().get(
|
|
38
|
-
if (!tome) throw Error(`unable to find tome "${
|
|
54
|
+
const tome = get_tomes().get(slug);
|
|
55
|
+
if (!tome) throw Error(`unable to find tome "${slug}"`);
|
|
39
56
|
return tome;
|
|
40
57
|
};
|
|
41
58
|
|