@graview/primitives 0.1.15 → 0.1.16
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 +13 -4
- package/dist/app-bar.d.ts +87 -0
- package/dist/app-bar.d.ts.map +1 -0
- package/dist/app-bar.js +261 -0
- package/dist/app-bar.js.map +1 -0
- package/dist/app-title.d.ts +28 -0
- package/dist/app-title.d.ts.map +1 -0
- package/dist/app-title.js +76 -0
- package/dist/app-title.js.map +1 -0
- package/dist/arrange-bar.d.ts +1 -1
- package/dist/arrange-bar.js +3 -3
- package/dist/arrange-bar.js.map +1 -1
- package/dist/bar-panes.d.ts +26 -0
- package/dist/bar-panes.d.ts.map +1 -0
- package/dist/bar-panes.js +119 -0
- package/dist/bar-panes.js.map +1 -0
- package/dist/companion.d.ts.map +1 -1
- package/dist/companion.js +8 -6
- package/dist/companion.js.map +1 -1
- package/dist/connections.d.ts +1 -1
- package/dist/connections.js +4 -4
- package/dist/connections.js.map +1 -1
- package/dist/default-views.js +9 -9
- package/dist/default-views.js.map +1 -1
- package/dist/editable.d.ts +3 -3
- package/dist/editable.js +4 -4
- package/dist/find.d.ts.map +1 -1
- package/dist/find.js +25 -6
- package/dist/find.js.map +1 -1
- package/dist/frame.d.ts +5 -1
- package/dist/frame.d.ts.map +1 -1
- package/dist/frame.js +4 -1
- package/dist/frame.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/installation.d.ts +1 -1
- package/dist/installation.js +1 -1
- package/dist/lens/board.js +3 -3
- package/dist/lens/calendar-view.js +1 -1
- package/dist/lens/coverage.d.ts +2 -2
- package/dist/lens/coverage.js +7 -7
- package/dist/lens/coverage.js.map +1 -1
- package/dist/lens/plan-state.d.ts +2 -2
- package/dist/lens/plan-state.js +1 -1
- package/dist/lens/plan-view.js +4 -4
- package/dist/lens/plan.d.ts +1 -1
- package/dist/lens/plan.js +1 -1
- package/dist/lens/timeline.d.ts +2 -2
- package/dist/lens/timeline.js +7 -7
- package/dist/lens/timeline.js.map +1 -1
- package/dist/markup.d.ts +1 -1
- package/dist/markup.js +1 -1
- package/dist/notice-place.d.ts +30 -0
- package/dist/notice-place.d.ts.map +1 -0
- package/dist/notice-place.js +91 -0
- package/dist/notice-place.js.map +1 -0
- package/dist/notices.d.ts +5 -3
- package/dist/notices.d.ts.map +1 -1
- package/dist/notices.js +11 -12
- package/dist/notices.js.map +1 -1
- package/dist/pages.d.ts +8 -1
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +8 -1
- package/dist/pages.js.map +1 -1
- package/dist/primitives/index.d.ts +7 -7
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +6 -6
- package/dist/primitives/index.js.map +1 -1
- package/dist/profile.d.ts +2 -4
- package/dist/profile.d.ts.map +1 -1
- package/dist/profile.js +38 -103
- package/dist/profile.js.map +1 -1
- package/dist/quick-relations.js +1 -1
- package/dist/relation-key.d.ts +2 -2
- package/dist/relation-key.js +3 -3
- package/dist/scene-css.d.ts.map +1 -1
- package/dist/scene-css.js +12 -11
- package/dist/scene-css.js.map +1 -1
- package/dist/scene.d.ts +2 -0
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +2 -0
- package/dist/scene.js.map +1 -1
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +13 -8
- package/dist/shell.js.map +1 -1
- package/dist/spec-views.d.ts +7 -0
- package/dist/spec-views.d.ts.map +1 -1
- package/dist/spec-views.js +9 -1
- package/dist/spec-views.js.map +1 -1
- package/dist/theme.d.ts +3 -3
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +21 -21
- package/dist/theme.js.map +1 -1
- package/dist/views-css.d.ts +9 -0
- package/dist/views-css.d.ts.map +1 -0
- package/dist/views-css.js +12 -0
- package/dist/views-css.js.map +1 -0
- package/dist/wordmark.d.ts +1 -1
- package/dist/wordmark.d.ts.map +1 -1
- package/dist/wordmark.js +5 -10
- package/dist/wordmark.js.map +1 -1
- package/dist/workbench/activity.js +3 -3
- package/dist/workbench/activity.js.map +1 -1
- package/dist/workbench/answer-args.js +4 -4
- package/dist/workbench/back-out.d.ts +1 -1
- package/dist/workbench/back-out.js +2 -2
- package/dist/workbench/inspector.d.ts +2 -2
- package/dist/workbench/inspector.js +6 -6
- package/dist/workbench/inspector.js.map +1 -1
- package/dist/workbench/standing.d.ts +8 -4
- package/dist/workbench/standing.d.ts.map +1 -1
- package/dist/workbench/standing.js +26 -41
- package/dist/workbench/standing.js.map +1 -1
- package/dist/workbench/trail.d.ts +1 -1
- package/dist/workbench/trail.js +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -38,10 +38,19 @@ is selected and what can be done with it, whether the rules hold, what just
|
|
|
38
38
|
happened and how to take it back, how to back out of a view. All derived from
|
|
39
39
|
the schema, the invariants and the op log.
|
|
40
40
|
|
|
41
|
+
**The app, said once** — `AppBar`: one bar over every face (FR-131) — the
|
|
42
|
+
brand's mark (`AppMark`, drawn as given, never an SVG that could act) and
|
|
43
|
+
the app's name as the page's heading, the app's places as tabs (`barPlaces`,
|
|
44
|
+
the overview among them, FR-132), and three tools of one size: the Find a
|
|
45
|
+
face puts in it (`useBarFind`), `Standing` and `Profile`. `AppTitle` draws
|
|
46
|
+
the mark, the name and the line under it elsewhere; `useFavicon` is for a
|
|
47
|
+
face that owns the page.
|
|
48
|
+
|
|
41
49
|
**Visual system** — `themeCss(scheme, brand)`. Two schemes that are not
|
|
42
50
|
inversions of each other: dark loses luminance, light loses contrast and gains
|
|
43
51
|
haze. A brand supplies its own and `graview check` measures it. The sheet is
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
three parts: `themeBaseCss`, what every face draws on; `viewsCss`, the blocks
|
|
53
|
+
a view spec is drawn with, which each face that draws a view draws beside it;
|
|
54
|
+
and `sceneCss`, the rules only the scene draws (the districts from altitude,
|
|
55
|
+
the plots, the village, the billboards), which an embed's scene face draws
|
|
56
|
+
beside it so a page on the pages face carries none of them.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type AnySchema, type Brand, type PagesArrangement, type Place, type Principal, type Store } from "@graview/core";
|
|
2
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
3
|
+
/** One of the app's places on the bar: what it is called, and where it is on the routed face. */
|
|
4
|
+
export interface BarPlace {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly label: string;
|
|
7
|
+
/** Its path on the routed face — `/places/overview` for the scene. */
|
|
8
|
+
readonly path: string;
|
|
9
|
+
}
|
|
10
|
+
/** The key the scene's place has on the bar. */
|
|
11
|
+
export declare const OVERVIEW_KEY = "overview";
|
|
12
|
+
/**
|
|
13
|
+
* THE APP'S PLACES, IN THE BAR'S ORDER: the overview (when the face can draw
|
|
14
|
+
* the scene), each named picture, each kind's list in the declaration's
|
|
15
|
+
* order, and how the kinds connect, when they do. What a seat may not see
|
|
16
|
+
* is not offered: a kind kept from it, a disabled module's kind, a picture
|
|
17
|
+
* over either.
|
|
18
|
+
*/
|
|
19
|
+
export declare function barPlaces(input: {
|
|
20
|
+
readonly store: Store<AnySchema>;
|
|
21
|
+
readonly principal?: Principal | undefined;
|
|
22
|
+
readonly views?: {
|
|
23
|
+
places(): readonly Place[];
|
|
24
|
+
arrangement?(): PagesArrangement | undefined;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/** Whether the scene is one of the places here. */
|
|
27
|
+
readonly overview: boolean;
|
|
28
|
+
}): readonly BarPlace[];
|
|
29
|
+
/** Which of the places a path on the routed face is: its own, a record's kind's, or none (the home, Find, the problems). */
|
|
30
|
+
export declare function barPlaceAt(places: readonly BarPlace[], path: string): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* WHERE A FACE PUTS ITS FIND BOX (FR-131). The bar draws the place; the
|
|
33
|
+
* face drawn under it — the scene's Find, or the routed face's — puts its
|
|
34
|
+
* own box there, so Find is one box in one place whichever face is drawn.
|
|
35
|
+
*/
|
|
36
|
+
export interface BarFind {
|
|
37
|
+
readonly slot: HTMLElement;
|
|
38
|
+
/** A phone's bar: the box opens over the bar's first row when it is asked for. */
|
|
39
|
+
readonly compact: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare const BarFindContext: import("react").Context<BarFind | null>;
|
|
42
|
+
/** The bar's place for a Find box, when a bar above this face has one. */
|
|
43
|
+
export declare const useBarFind: () => BarFind | null;
|
|
44
|
+
/** How a place is reached: a link when it has an address, a press when the bar decides. */
|
|
45
|
+
export interface BarGo {
|
|
46
|
+
/** The address a place's link carries; none, and the tab is a button. */
|
|
47
|
+
readonly href?: (path: string) => string | undefined;
|
|
48
|
+
/** Goes to a place; a link's ordinary press is handed here rather than followed. */
|
|
49
|
+
readonly go?: (place: BarPlace) => void;
|
|
50
|
+
}
|
|
51
|
+
/** One size for every tool on the bar (FR-131). */
|
|
52
|
+
export declare const TOOL = 30;
|
|
53
|
+
/** A tool's own box: one size, square, its name in words for whoever cannot see the mark. */
|
|
54
|
+
export declare const toolStyle: CSSProperties;
|
|
55
|
+
/**
|
|
56
|
+
* THE BAR. The app at the left — its mark, its name as the page's heading,
|
|
57
|
+
* the way home — its places in the middle, and the tools at the right: the
|
|
58
|
+
* Find a face puts in it, then `tools` (the standing and the person). One
|
|
59
|
+
* row at a desk; on a phone the places take a second row of their own.
|
|
60
|
+
*/
|
|
61
|
+
export declare function AppBar({ brand, name, heading, home, places, current, reach, tools, find, description, findBox, onFind, }: {
|
|
62
|
+
readonly brand: Brand | undefined;
|
|
63
|
+
readonly name: string;
|
|
64
|
+
/** The level the app's name is said at: 1 when the page is the app's, `false` when the host's own heading already says it. */
|
|
65
|
+
readonly heading?: 1 | 2 | 3 | 4 | 5 | 6 | false;
|
|
66
|
+
/** The way home, and whether the reader is there. */
|
|
67
|
+
readonly home: {
|
|
68
|
+
readonly href?: string | undefined;
|
|
69
|
+
readonly go?: (() => void) | undefined;
|
|
70
|
+
readonly current: boolean;
|
|
71
|
+
};
|
|
72
|
+
readonly places: readonly BarPlace[];
|
|
73
|
+
/** The key of the place the reader is on; null at the home, at Find, at the problems. */
|
|
74
|
+
readonly current: string | null;
|
|
75
|
+
readonly reach: BarGo;
|
|
76
|
+
/** The standing and the person, after Find. */
|
|
77
|
+
readonly tools: ReactNode;
|
|
78
|
+
/** Whether a face puts a Find box in the bar. */
|
|
79
|
+
readonly find?: boolean;
|
|
80
|
+
/** The line under the app's name (the brand's `subtitle`): said on the home, and as the name's hover here. */
|
|
81
|
+
readonly description?: string | undefined;
|
|
82
|
+
/** A Find box the bar is handed to draw in its place, for a face drawn inside the bar's own tree; otherwise the face puts its own there. */
|
|
83
|
+
readonly findBox?: ReactNode;
|
|
84
|
+
/** Told where the bar keeps the Find box, for the face under it (`BarFindContext`). */
|
|
85
|
+
readonly onFind?: (find: BarFind | null) => void;
|
|
86
|
+
}): import("react").JSX.Element;
|
|
87
|
+
//# sourceMappingURL=app-bar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-bar.d.ts","sourceRoot":"","sources":["../src/app-bar.tsx"],"names":[],"mappings":"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"}
|
package/dist/app-bar.js
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { OVERVIEW_PATH, OVERVIEW_SLUG, orderKinds, overviewTitle, placeSlug } from "@graview/core";
|
|
3
|
+
import { POPOVER_STYLE, usePopover } from "@graview/react/provider";
|
|
4
|
+
import { createContext, useCallback, useContext, useLayoutEffect, useRef, useState } from "react";
|
|
5
|
+
import { AppMark } from "./app-title.js";
|
|
6
|
+
/** The key the scene's place has on the bar. */
|
|
7
|
+
export const OVERVIEW_KEY = OVERVIEW_SLUG;
|
|
8
|
+
const upper = (word) => word.charAt(0).toUpperCase() + word.slice(1);
|
|
9
|
+
/**
|
|
10
|
+
* THE APP'S PLACES, IN THE BAR'S ORDER: the overview (when the face can draw
|
|
11
|
+
* the scene), each named picture, each kind's list in the declaration's
|
|
12
|
+
* order, and how the kinds connect, when they do. What a seat may not see
|
|
13
|
+
* is not offered: a kind kept from it, a disabled module's kind, a picture
|
|
14
|
+
* over either.
|
|
15
|
+
*/
|
|
16
|
+
export function barPlaces(input) {
|
|
17
|
+
const { store, principal, views } = input;
|
|
18
|
+
const kept = store.kindsKeptFrom(principal);
|
|
19
|
+
const live = store.schema.kinds.filter((kind) => !store.modules.disabledKinds.has(kind) && !kept.has(kind));
|
|
20
|
+
const arrangement = views?.arrangement?.();
|
|
21
|
+
const plural = (kind) => store.schema.tryDefinition(kind)?.plural ?? `${kind}s`;
|
|
22
|
+
const out = [];
|
|
23
|
+
if (input.overview)
|
|
24
|
+
out.push({ key: OVERVIEW_KEY, label: overviewTitle(arrangement), path: OVERVIEW_PATH });
|
|
25
|
+
const all = views?.places() ?? [];
|
|
26
|
+
for (const place of all) {
|
|
27
|
+
if (!live.includes(place.kind) || place.as === OVERVIEW_SLUG)
|
|
28
|
+
continue;
|
|
29
|
+
// Two kinds' pictures of one name say whose with `?of=` (as the routed face addresses them).
|
|
30
|
+
const shared = all.some((other) => other.as === place.as && other.kind !== place.kind);
|
|
31
|
+
const path = `/places/${encodeURIComponent(place.as)}${shared ? `?of=${placeSlug(plural(place.kind))}` : ""}`;
|
|
32
|
+
if (!out.some((held) => held.path === path))
|
|
33
|
+
out.push({ key: `place:${place.kind}:${place.as}`, label: place.title, path });
|
|
34
|
+
}
|
|
35
|
+
for (const kind of orderKinds(live, arrangement?.order))
|
|
36
|
+
out.push({ key: `kind:${kind}`, label: upper(plural(kind)), path: `/${placeSlug(plural(kind))}` });
|
|
37
|
+
const connects = live.some((kind) => Object.keys((store.schema.tryDefinition(kind)?.edges ?? {})).length > 0);
|
|
38
|
+
if (connects)
|
|
39
|
+
out.push({ key: "connections", label: "Connections", path: "/map" });
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
/** Which of the places a path on the routed face is: its own, a record's kind's, or none (the home, Find, the problems). */
|
|
43
|
+
export function barPlaceAt(places, path) {
|
|
44
|
+
const [pathname = "/", search = ""] = path.split("?");
|
|
45
|
+
const exact = places.find((place) => place.path === (search ? `${pathname}?${search}` : pathname)) ?? places.find((place) => place.path === pathname);
|
|
46
|
+
if (exact)
|
|
47
|
+
return exact.key;
|
|
48
|
+
const first = `/${pathname.split("/").filter(Boolean)[0] ?? ""}`;
|
|
49
|
+
// A record's page is under its kind's list.
|
|
50
|
+
return places.find((place) => place.key.startsWith("kind:") && place.path === first)?.key ?? null;
|
|
51
|
+
}
|
|
52
|
+
export const BarFindContext = createContext(null);
|
|
53
|
+
/** The bar's place for a Find box, when a bar above this face has one. */
|
|
54
|
+
export const useBarFind = () => useContext(BarFindContext);
|
|
55
|
+
/** One size for every tool on the bar (FR-131). */
|
|
56
|
+
export const TOOL = 30;
|
|
57
|
+
const BAR_CSS = `
|
|
58
|
+
.graview-bar{container-type:inline-size;flex:0 0 auto;position:relative;background:var(--graview-bar);border-bottom:1px solid var(--graview-edge);color:var(--graview-ink);font-family:var(--graview-font-body,system-ui)}
|
|
59
|
+
.graview-bar-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"app places tools";align-items:stretch;column-gap:20px;padding:0 16px;min-height:48px}
|
|
60
|
+
.graview-bar-app{grid-area:app;display:flex;align-items:center;min-width:0}
|
|
61
|
+
.graview-bar-name{margin:0;min-width:0;display:flex;font-family:var(--graview-font-display,var(--graview-font-body,system-ui));font-size:.9375rem;font-weight:600;line-height:1.3;letter-spacing:-.005em}
|
|
62
|
+
.graview-bar-home{display:inline-flex;align-items:center;gap:8px;min-width:0;min-height:30px;color:var(--graview-ink);text-decoration:none;font:inherit;letter-spacing:inherit;overflow-wrap:anywhere;margin:0;padding:0;border:0;background:none;box-shadow:none;cursor:pointer;text-align:left}
|
|
63
|
+
.graview-bar-more{display:grid;min-width:200px;max-width:calc(100vw - 32px);margin:0;padding:4px;list-style:none;border-radius:10px;border:1px solid var(--graview-edge);background:var(--graview-float);box-shadow:var(--graview-lift-high)}
|
|
64
|
+
.graview-bar-more[hidden]{display:none}
|
|
65
|
+
.graview-bar-item{display:flex;align-items:center;width:100%;min-height:32px;padding:0 10px;border:0;border-left:2px solid transparent;border-radius:7px;background:none;box-shadow:none;font:inherit;font-size:.875rem;text-align:left;text-decoration:none;color:var(--graview-ink);cursor:pointer}
|
|
66
|
+
.graview-bar-item[aria-current="page"]{font-weight:600;border-left-color:var(--graview-accent)}
|
|
67
|
+
.graview-bar-places{grid-area:places;display:flex;align-items:stretch;min-width:0}
|
|
68
|
+
.graview-bar-tools{grid-area:tools;display:flex;align-items:center;gap:8px;min-width:0}
|
|
69
|
+
.graview-bar-find{display:flex;align-items:center;width:15rem;min-width:0}
|
|
70
|
+
.graview-bar-find-open{display:none;align-items:center;justify-content:center}
|
|
71
|
+
.graview-bar-tab{display:inline-flex;align-items:center;gap:4px;padding:0 10px;margin:0;border:0;border-bottom:2px solid transparent;border-radius:0;background:none;box-shadow:none;font:inherit;font-size:.875rem;line-height:1.2;white-space:nowrap;color:var(--graview-ink-muted);text-decoration:none;cursor:pointer;flex:0 0 auto}
|
|
72
|
+
.graview-bar-tab:hover{color:var(--graview-ink)}
|
|
73
|
+
.graview-bar-tab[aria-current="page"]{color:var(--graview-ink);border-bottom-color:var(--graview-accent);font-weight:600}
|
|
74
|
+
.graview-bar-tab:focus-visible{outline:2px solid var(--graview-accent);outline-offset:-4px}
|
|
75
|
+
.graview-bar-measure{position:absolute;visibility:hidden;pointer-events:none;display:flex;white-space:nowrap;height:0;overflow:hidden}
|
|
76
|
+
@container (max-width: 639px){
|
|
77
|
+
.graview-bar-row{grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"app tools" "places places";padding:0 12px;min-height:0;column-gap:12px}
|
|
78
|
+
.graview-bar-app,.graview-bar-tools{min-height:48px}
|
|
79
|
+
.graview-bar-places{border-top:1px solid var(--graview-edge);margin:0 -12px;padding:0 2px;min-height:40px}
|
|
80
|
+
.graview-bar-find{display:none;width:auto;flex:1 1 auto}
|
|
81
|
+
.graview-bar-find-open{display:inline-flex}
|
|
82
|
+
.graview-bar[data-finding] .graview-bar-app{display:none}
|
|
83
|
+
.graview-bar[data-finding] .graview-bar-row{grid-template-areas:"tools tools" "places places"}
|
|
84
|
+
.graview-bar[data-finding] .graview-bar-tools{flex:1 1 auto}
|
|
85
|
+
.graview-bar[data-finding] .graview-bar-find{display:flex}
|
|
86
|
+
.graview-bar[data-finding] .graview-bar-find-open{display:none}
|
|
87
|
+
}`;
|
|
88
|
+
/** A tool's own box: one size, square, its name in words for whoever cannot see the mark. */
|
|
89
|
+
export const toolStyle = {
|
|
90
|
+
display: "inline-flex",
|
|
91
|
+
alignItems: "center",
|
|
92
|
+
justifyContent: "center",
|
|
93
|
+
gap: 6,
|
|
94
|
+
minWidth: TOOL,
|
|
95
|
+
height: TOOL,
|
|
96
|
+
padding: 0,
|
|
97
|
+
borderRadius: 8,
|
|
98
|
+
border: "1px solid transparent",
|
|
99
|
+
background: "none",
|
|
100
|
+
boxShadow: "none",
|
|
101
|
+
color: "var(--graview-ink-muted)",
|
|
102
|
+
font: "inherit",
|
|
103
|
+
fontSize: "0.875rem",
|
|
104
|
+
cursor: "pointer",
|
|
105
|
+
flex: "0 0 auto",
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* THE BAR. The app at the left — its mark, its name as the page's heading,
|
|
109
|
+
* the way home — its places in the middle, and the tools at the right: the
|
|
110
|
+
* Find a face puts in it, then `tools` (the standing and the person). One
|
|
111
|
+
* row at a desk; on a phone the places take a second row of their own.
|
|
112
|
+
*/
|
|
113
|
+
export function AppBar({ brand, name, heading = 1, home, places, current, reach, tools, find = true, description, findBox, onFind, }) {
|
|
114
|
+
const bar = useRef(null);
|
|
115
|
+
const [slot, setSlot] = useState(null);
|
|
116
|
+
const [compact, setCompact] = useState(false);
|
|
117
|
+
const [finding, setFinding] = useState(false);
|
|
118
|
+
useLayoutEffect(() => {
|
|
119
|
+
const element = bar.current;
|
|
120
|
+
if (!element)
|
|
121
|
+
return;
|
|
122
|
+
const read = () => setCompact(element.getBoundingClientRect().width < 640);
|
|
123
|
+
read();
|
|
124
|
+
if (typeof ResizeObserver === "undefined")
|
|
125
|
+
return;
|
|
126
|
+
const watch = new ResizeObserver(read);
|
|
127
|
+
watch.observe(element);
|
|
128
|
+
return () => watch.disconnect();
|
|
129
|
+
}, []);
|
|
130
|
+
const told = useRef(onFind);
|
|
131
|
+
told.current = onFind;
|
|
132
|
+
useLayoutEffect(() => {
|
|
133
|
+
told.current?.(find && slot ? { slot, compact } : null);
|
|
134
|
+
}, [find, slot, compact]);
|
|
135
|
+
useLayoutEffect(() => () => told.current?.(null), []);
|
|
136
|
+
const openFind = useCallback(() => {
|
|
137
|
+
setFinding(true);
|
|
138
|
+
requestAnimationFrame(() => slot?.querySelector("input")?.focus());
|
|
139
|
+
}, [slot]);
|
|
140
|
+
/*
|
|
141
|
+
* Put away on a phone by Escape, the box gives the keyboard back to the
|
|
142
|
+
* magnifier that opened it — never to the page's body.
|
|
143
|
+
*/
|
|
144
|
+
const opener = useRef(null);
|
|
145
|
+
const escaping = useRef(false);
|
|
146
|
+
const putAway = useCallback(() => {
|
|
147
|
+
setFinding(false);
|
|
148
|
+
if (!escaping.current)
|
|
149
|
+
return;
|
|
150
|
+
escaping.current = false;
|
|
151
|
+
requestAnimationFrame(() => opener.current?.focus());
|
|
152
|
+
}, []);
|
|
153
|
+
const Heading = heading === false ? "span" : `h${heading}`;
|
|
154
|
+
const press = (go) => (event) => {
|
|
155
|
+
if (!go || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
156
|
+
return;
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
go();
|
|
159
|
+
};
|
|
160
|
+
return (_jsxs("header", { ref: bar, className: "graview-bar", "data-testid": "app-bar", "data-graview-app-bar": "", ...(finding && compact ? { "data-finding": "" } : {}), children: [_jsx("style", { children: BAR_CSS }), _jsxs("div", { className: "graview-bar-row", children: [_jsx("div", { className: "graview-bar-app", children: _jsx(Heading, { className: "graview-bar-name", children: home.href !== undefined ? (_jsxs("a", { href: home.href, onClick: press(home.go), "data-testid": "app-home", ...(home.current ? { "aria-current": "page" } : {}), title: description ? `${name} — ${description}` : `${name} — home`, className: "graview-bar-home", children: [_jsx(AppMark, { brand: brand, size: 20 }), _jsx("span", { "data-testid": "app-name", children: name })] })) : (_jsxs("button", { type: "button", onClick: home.go, "data-testid": "app-home", ...(home.current ? { "aria-current": "page" } : {}), title: description ? `${name} — ${description}` : `${name} — home`, className: "graview-bar-home", children: [_jsx(AppMark, { brand: brand, size: 20 }), _jsx("span", { "data-testid": "app-name", children: name })] })) }) }), _jsx(BarPlaces, { places: places, current: current, reach: reach }), _jsxs("div", { className: "graview-bar-tools", children: [find ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "graview-bar-find-open", ref: opener, "data-testid": "app-find-open", "aria-label": "Find", title: "Find", onClick: openFind, style: { ...toolStyle, display: undefined }, children: _jsx(FindMark, {}) }), _jsx("div", { ref: setSlot, className: "graview-bar-find", "data-testid": "app-find", onBlur: (event) => {
|
|
161
|
+
// Put away on a phone when the keyboard leaves it with nothing typed.
|
|
162
|
+
const next = event.relatedTarget;
|
|
163
|
+
if (next instanceof Node && event.currentTarget.contains(next))
|
|
164
|
+
return;
|
|
165
|
+
if (!event.currentTarget.querySelector("input")?.value)
|
|
166
|
+
putAway();
|
|
167
|
+
}, onKeyDownCapture: (event) => {
|
|
168
|
+
if (event.key === "Escape" && compact)
|
|
169
|
+
escaping.current = true;
|
|
170
|
+
}, onKeyDown: (event) => {
|
|
171
|
+
if (event.key !== "Escape" || !compact)
|
|
172
|
+
return;
|
|
173
|
+
// The scene's Find takes Escape for its words first; an empty box is put away.
|
|
174
|
+
if (!event.defaultPrevented || !event.currentTarget.querySelector("input")?.value)
|
|
175
|
+
putAway();
|
|
176
|
+
else
|
|
177
|
+
escaping.current = false;
|
|
178
|
+
}, children: findBox })] })) : null, tools] })] })] }));
|
|
179
|
+
}
|
|
180
|
+
/** The way a menu opens: a chevron drawn, not a glyph a face may draw as a dot. */
|
|
181
|
+
function Chevron() {
|
|
182
|
+
return (_jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", "aria-hidden": "true", focusable: "false", style: { flex: "0 0 auto" }, children: _jsx("path", { d: "M2 3.5 L5 6.5 L8 3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
183
|
+
}
|
|
184
|
+
/** A magnifier: the mark for Find where there is no room for the box. */
|
|
185
|
+
function FindMark() {
|
|
186
|
+
return (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: [_jsx("circle", { cx: "7", cy: "7", r: "4.75", fill: "none", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M10.5 10.5 L14 14", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* THE PLACES AS PLAIN TABS. As many as the row holds, in order; the rest
|
|
190
|
+
* under "More". The tab you are on is marked, and always on the row — in
|
|
191
|
+
* the last tab's room when the row could not otherwise hold it, and alone
|
|
192
|
+
* beside "More" when the row holds none — so where you are is never hidden.
|
|
193
|
+
*/
|
|
194
|
+
function BarPlaces({ places, current, reach }) {
|
|
195
|
+
const row = useRef(null);
|
|
196
|
+
const measure = useRef(null);
|
|
197
|
+
const [fits, setFits] = useState(places.length);
|
|
198
|
+
const popover = usePopover("places");
|
|
199
|
+
const signature = places.map((place) => place.label).join("|");
|
|
200
|
+
const currentAt = places.findIndex((place) => place.key === current);
|
|
201
|
+
useLayoutEffect(() => {
|
|
202
|
+
const element = row.current;
|
|
203
|
+
const ruler = measure.current;
|
|
204
|
+
if (!element || !ruler)
|
|
205
|
+
return;
|
|
206
|
+
const fit = () => {
|
|
207
|
+
const room = element.getBoundingClientRect().width + 0.5;
|
|
208
|
+
const widths = [...ruler.children].map((child) => child.getBoundingClientRect().width);
|
|
209
|
+
const more = widths.pop() ?? 0;
|
|
210
|
+
const sum = (list) => list.reduce((total, width) => total + width, 0);
|
|
211
|
+
let count = widths.length;
|
|
212
|
+
if (sum(widths) > room) {
|
|
213
|
+
// As many as fit beside "More" — the place you are on among them, in the last one's room when it is further along.
|
|
214
|
+
count = widths.length - 1;
|
|
215
|
+
while (count > 0) {
|
|
216
|
+
const seen = currentAt >= count ? [...widths.slice(0, count - 1), widths[currentAt]] : widths.slice(0, count);
|
|
217
|
+
if (sum(seen) + more <= room)
|
|
218
|
+
break;
|
|
219
|
+
count -= 1;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
setFits((was) => (was === count ? was : count));
|
|
223
|
+
};
|
|
224
|
+
fit();
|
|
225
|
+
if (typeof ResizeObserver === "undefined")
|
|
226
|
+
return;
|
|
227
|
+
const watch = new ResizeObserver(fit);
|
|
228
|
+
watch.observe(element);
|
|
229
|
+
// The ruler too: a brand's web font arriving after the first measure widens every tab.
|
|
230
|
+
watch.observe(ruler);
|
|
231
|
+
return () => watch.disconnect();
|
|
232
|
+
}, [signature, currentAt]);
|
|
233
|
+
if (places.length === 0)
|
|
234
|
+
return _jsx("div", { className: "graview-bar-places", "data-testid": "app-places", ref: row });
|
|
235
|
+
// The place you are on is on the row: in the last tab's room when it is one the row could not otherwise hold, alone when it holds none.
|
|
236
|
+
const shown = currentAt >= fits ? [...places.slice(0, Math.max(0, fits - 1)), places[currentAt]] : places.slice(0, fits);
|
|
237
|
+
const rest = places.filter((place) => !shown.includes(place));
|
|
238
|
+
const tab = (place, inMenu) => {
|
|
239
|
+
const here = place.key === current;
|
|
240
|
+
const href = reach.href?.(place.path);
|
|
241
|
+
const common = {
|
|
242
|
+
className: inMenu ? "graview-bar-item" : "graview-bar-tab",
|
|
243
|
+
"data-testid": `app-place-${place.key}`,
|
|
244
|
+
"data-place-path": place.path,
|
|
245
|
+
...(here ? { "aria-current": "page" } : {}),
|
|
246
|
+
onClick: (event) => {
|
|
247
|
+
if (inMenu)
|
|
248
|
+
popover.setOpen(false);
|
|
249
|
+
if (!reach.go)
|
|
250
|
+
return;
|
|
251
|
+
if (href !== undefined && (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey))
|
|
252
|
+
return;
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
reach.go(place);
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
return href !== undefined ? (_jsx("a", { ...common, href: href, children: place.label }, place.key)) : (_jsx("button", { ...common, type: "button", children: place.label }, place.key));
|
|
258
|
+
};
|
|
259
|
+
return (_jsxs("nav", { ref: row, className: "graview-bar-places", "aria-label": "The app\u2019s places", "data-testid": "app-places", style: { position: "relative" }, children: [_jsxs("div", { ref: measure, className: "graview-bar-measure", "aria-hidden": "true", children: [places.map((place) => (_jsx("span", { className: "graview-bar-tab", style: { fontWeight: 600 }, children: place.label }, place.key))), _jsxs("span", { className: "graview-bar-tab", children: ["More", _jsx(Chevron, {})] })] }), shown.map((place) => tab(place, false)), rest.length > 0 ? (_jsxs("span", { style: { position: "relative", display: "inline-flex" }, children: [_jsxs("button", { type: "button", className: "graview-bar-tab", "data-testid": "app-places-more", ...popover.trigger, onClick: popover.toggle, "aria-label": "More places", children: ["More", _jsx(Chevron, {})] }), _jsx("ul", { ...popover.pane, "data-testid": "app-places-more-list", "aria-label": "More places", hidden: !popover.open, className: "graview-bar-more", style: POPOVER_STYLE, children: rest.map((place) => (_jsx("li", { children: tab(place, true) }, place.key))) })] })) : null] }));
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=app-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-bar.js","sourceRoot":"","sources":["../src/app-bar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAA6F,MAAM,eAAe,CAAC;AAC9L,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAuD,MAAM,OAAO,CAAC;AACvJ,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AA4BzC,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;AAE1C,MAAM,KAAK,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAErF;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAMzB;IACC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAI,KAAK,CAAC,MAAM,CAAC,KAA2B,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACnI,MAAM,WAAW,GAAG,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE,CAAE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,MAA6B,IAAI,GAAG,IAAI,GAAG,CAAC;IACxH,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,IAAI,KAAK,CAAC,QAAQ;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IAC5G,MAAM,GAAG,GAAG,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,KAAK,aAAa;YAAE,SAAS;QACvE,6FAA6F;QAC7F,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;QACvF,MAAM,IAAI,GAAG,WAAW,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9G,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9H,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5J,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxH,IAAI,QAAQ;QAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,4HAA4H;AAC5H,MAAM,UAAU,UAAU,CAAC,MAA2B,EAAE,IAAY;IAClE,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACtJ,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IACjE,4CAA4C;IAC5C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC;AACpG,CAAC;AAYD,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAiB,IAAI,CAAC,CAAC;AAClE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG,GAAmB,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AAU3E,mDAAmD;AACnD,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;AAEvB,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8Bd,CAAC;AAEH,6FAA6F;AAC7F,MAAM,CAAC,MAAM,SAAS,GAAkB;IACtC,OAAO,EAAE,aAAa;IACtB,UAAU,EAAE,QAAQ;IACpB,cAAc,EAAE,QAAQ;IACxB,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,CAAC;IACf,MAAM,EAAE,uBAAuB;IAC/B,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,MAAM;IACjB,KAAK,EAAE,0BAA0B;IACjC,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,UAAU;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,EACrB,KAAK,EACL,IAAI,EACJ,OAAO,GAAG,CAAC,EACX,IAAI,EACJ,MAAM,EACN,OAAO,EACP,KAAK,EACL,KAAK,EACL,IAAI,GAAG,IAAI,EACX,WAAW,EACX,OAAO,EACP,MAAM,GAsBP;IACC,MAAM,GAAG,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;QAC3E,IAAI,EAAE,CAAC;QACP,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE,OAAO;QAClD,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;QACvC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACtB,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1B,eAAe,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;QAChC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,CAAmB,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACvF,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACX;;;OAGG;IACH,MAAM,MAAM,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,OAAO;QAC9B,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;QACzB,qBAAqB,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,IAAI,OAAO,EAAY,CAAC;IACtE,MAAM,KAAK,GAAG,CAAC,EAA4B,EAAE,EAAE,CAAC,CAAC,KAAiB,EAAE,EAAE;QACpE,IAAI,CAAC,EAAE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO;QAC1G,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,EAAE,EAAE,CAAC;IACP,CAAC,CAAC;IACF,OAAO,CACL,kBACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAC,aAAa,iBACX,SAAS,0BACA,EAAE,KACnB,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAEtD,0BAAQ,OAAO,GAAS,EACxB,eAAK,SAAS,EAAC,iBAAiB,aAC9B,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,OAAO,IAAC,SAAS,EAAC,kBAAkB,YAElC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACzB,aAAG,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAc,UAAU,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,SAAS,EAAC,kBAAkB,aACjO,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,GAAI,EACnC,8BAAkB,UAAU,YAAE,IAAI,GAAQ,IACxC,CACL,CAAC,CAAC,CAAC,CACF,kBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,iBAAc,UAAU,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,SAAS,EAAC,kBAAkB,aAC5N,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,GAAI,EACnC,8BAAkB,UAAU,YAAE,IAAI,GAAQ,IACnC,CACV,GACO,GACN,EACN,KAAC,SAAS,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAI,EAC7D,eAAK,SAAS,EAAC,mBAAmB,aAC/B,IAAI,CAAC,CAAC,CAAC,CACN,8BACE,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uBAAuB,EACjC,GAAG,EAAE,MAAM,iBACC,eAAe,gBAChB,MAAM,EACjB,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAE3C,KAAC,QAAQ,KAAG,GACL,EACT,cACE,GAAG,EAAE,OAAO,EACZ,SAAS,EAAC,kBAAkB,iBAChB,UAAU,EACtB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;4CAChB,sEAAsE;4CACtE,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC;4CACjC,IAAI,IAAI,YAAY,IAAI,IAAI,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;gDAAE,OAAO;4CACvE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,aAAa,CAAmB,OAAO,CAAC,EAAE,KAAK;gDAAE,OAAO,EAAE,CAAC;wCACtF,CAAC,EACD,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;4CAC1B,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO;gDAAE,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;wCACjE,CAAC,EACD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;4CACnB,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO;gDAAE,OAAO;4CAC/C,+EAA+E;4CAC/E,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,aAAa,CAAmB,OAAO,CAAC,EAAE,KAAK;gDAAE,OAAO,EAAE,CAAC;;gDAC1G,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;wCAChC,CAAC,YAEA,OAAO,GACJ,IACL,CACJ,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,IACF,IACF,IACC,CACV,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAS,OAAO;IACd,OAAO,CACL,cAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,iBAAa,MAAM,EAAC,SAAS,EAAC,OAAO,EAAC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,YAC9G,eAAM,CAAC,EAAC,sBAAsB,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,GAAG,GAC9H,CACP,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ;IACf,OAAO,CACL,eAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,iBAAa,MAAM,EAAC,SAAS,EAAC,OAAO,aAClF,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,MAAM,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,GAAG,EACrF,eAAM,CAAC,EAAC,mBAAmB,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,aAAa,EAAC,OAAO,GAAG,IACxF,CACP,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAoG;IAC7I,MAAM,GAAG,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC;IACrE,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK;YAAE,OAAO;QAC/B,MAAM,GAAG,GAAG,GAAG,EAAE;YACf,MAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC;YACzD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,CAAC;YACvF,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,IAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;YACzF,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;YAC1B,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;gBACvB,mHAAmH;gBACnH,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC1B,OAAO,KAAK,GAAG,CAAC,EAAE,CAAC;oBACjB,MAAM,IAAI,GAAG,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;oBAC/G,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI;wBAAE,MAAM;oBACpC,KAAK,IAAI,CAAC,CAAC;gBACb,CAAC;YACH,CAAC;YACD,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC;QACF,GAAG,EAAE,CAAC;QACN,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE,OAAO;QAClD,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC;QACtC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,uFAAuF;QACvF,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,cAAK,SAAS,EAAC,oBAAoB,iBAAa,YAAY,EAAC,GAAG,EAAE,GAAY,GAAI,CAAC;IACnH,wIAAwI;IACxI,MAAM,KAAK,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1H,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,MAAe,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG;YACb,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,iBAAiB;YAC1D,aAAa,EAAE,aAAa,KAAK,CAAC,GAAG,EAAE;YACvC,iBAAiB,EAAE,KAAK,CAAC,IAAI;YAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;gBAC7B,IAAI,MAAM;oBAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACnC,IAAI,CAAC,KAAK,CAAC,EAAE;oBAAE,OAAO;gBACtB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;oBAAE,OAAO;gBAC3H,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;SACF,CAAC;QACF,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAC1B,eAAuB,MAAM,EAAE,IAAI,EAAE,IAAI,YACtC,KAAK,CAAC,KAAK,IADN,KAAK,CAAC,GAAG,CAEb,CACL,CAAC,CAAC,CAAC,CACF,oBAA4B,MAAM,EAAE,IAAI,EAAC,QAAQ,YAC9C,KAAK,CAAC,KAAK,IADD,KAAK,CAAC,GAAG,CAEb,CACV,CAAC;IACJ,CAAC,CAAC;IACF,OAAO,CACL,eAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAC,oBAAoB,gBAAY,uBAAkB,iBAAa,YAAY,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,aAElI,eAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAC,qBAAqB,iBAAa,MAAM,aAClE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,eAAsB,SAAS,EAAC,iBAAiB,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,YACzE,KAAK,CAAC,KAAK,IADH,KAAK,CAAC,GAAG,CAEb,CACR,CAAC,EACF,gBAAM,SAAS,EAAC,iBAAiB,qBAE/B,KAAC,OAAO,KAAG,IACN,IACH,EACL,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EACvC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACjB,gBAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,aAC3D,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,iBAAiB,iBACf,iBAAiB,KACzB,OAAO,CAAC,OAAO,EACnB,OAAO,EAAE,OAAO,CAAC,MAAM,gBACZ,aAAa,qBAGxB,KAAC,OAAO,KAAG,IACJ,EACT,gBACM,OAAO,CAAC,IAAI,iBACJ,sBAAsB,gBACvB,aAAa,EACxB,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EACrB,SAAS,EAAC,kBAAkB,EAC5B,KAAK,EAAE,aAAa,YAEnB,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACnB,uBAAqB,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,IAA5B,KAAK,CAAC,GAAG,CAAyB,CAC5C,CAAC,GACC,IACA,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Brand } from "@graview/core";
|
|
2
|
+
/** The brand's mark alone, `size` pixels tall; nothing when there is none, or none that may be drawn. */
|
|
3
|
+
export declare function AppMark({ brand, size }: {
|
|
4
|
+
readonly brand: Brand | undefined;
|
|
5
|
+
readonly size?: number;
|
|
6
|
+
}): import("react").JSX.Element | null;
|
|
7
|
+
/**
|
|
8
|
+
* The mark, the name and — where `subtitle` asks and the brand has one —
|
|
9
|
+
* the line under the name. Its type is the container's: the name takes
|
|
10
|
+
* the font, size and case it is drawn in; the line under it is the body's,
|
|
11
|
+
* quiet, and wraps rather than being cut.
|
|
12
|
+
*/
|
|
13
|
+
export declare function AppTitle({ brand, name, subtitle, size }: {
|
|
14
|
+
readonly brand: Brand | undefined;
|
|
15
|
+
readonly name?: string;
|
|
16
|
+
readonly subtitle?: boolean;
|
|
17
|
+
readonly size?: number;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* THE PAGE'S ICON (FR-124), for a face that owns the whole page — the
|
|
21
|
+
* Shell, the routed face on its own, an embed its host told `favicon:
|
|
22
|
+
* true`. Every `<link rel="icon">` the page has points at it while the face
|
|
23
|
+
* is drawn, and back at what it pointed at after; a page with none gets
|
|
24
|
+
* one. `undefined` touches nothing, which is what an embed on somebody
|
|
25
|
+
* else's page passes.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useFavicon(href: string | undefined): void;
|
|
28
|
+
//# sourceMappingURL=app-title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-title.d.ts","sourceRoot":"","sources":["../src/app-title.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAkB9E,yGAAyG;AACzG,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,sCAU1G;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAgB,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,+BAkBnL;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAqBzD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isInlineSvg, markHref, svgProblem } from "@graview/core";
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
import { useMarkup } from "./markup.js";
|
|
5
|
+
/*
|
|
6
|
+
* THE APP, SAID ONCE (FR-124, FR-125): its mark, its name, and the line
|
|
7
|
+
* under the name — the one component every face draws its title with, so
|
|
8
|
+
* the whole-page Shell's wordmark and the one app bar (FR-131, with `AppMark`)
|
|
9
|
+
* say the same app the same way.
|
|
10
|
+
*
|
|
11
|
+
* The mark is drawn as the brand gives it, never redrawn: an SVG written
|
|
12
|
+
* inline is put in the page as it is (so `currentColor` takes the accent,
|
|
13
|
+
* and nothing else is recolored), and only when it could not act — an
|
|
14
|
+
* SVG with a script, a handler or a load in it is not drawn at all. A path
|
|
15
|
+
* is an `<img>`. Beside the name the mark is said only when its alt text
|
|
16
|
+
* says more than the name does.
|
|
17
|
+
*/
|
|
18
|
+
/** The brand's mark alone, `size` pixels tall; nothing when there is none, or none that may be drawn. */
|
|
19
|
+
export function AppMark({ brand, size = 22 }) {
|
|
20
|
+
const logo = brand?.logo;
|
|
21
|
+
const inline = logo !== undefined && isInlineSvg(logo) && svgProblem(logo) === null ? logo : undefined;
|
|
22
|
+
const markup = useMarkup(inline);
|
|
23
|
+
if (!logo || !markHref(logo))
|
|
24
|
+
return null;
|
|
25
|
+
const alt = brand?.logoAlt ?? brand?.name ?? "";
|
|
26
|
+
const said = alt !== "" && alt !== brand?.name;
|
|
27
|
+
const box = { display: "inline-flex", flex: "0 0 auto", height: size, color: "var(--graview-accent)" };
|
|
28
|
+
if (inline)
|
|
29
|
+
return _jsx("span", { className: "graview-logo", "data-testid": "app-mark", style: box, ...(said ? { role: "img", "aria-label": alt } : { "aria-hidden": true }), dangerouslySetInnerHTML: markup });
|
|
30
|
+
return _jsx("img", { className: "graview-logo", "data-testid": "app-mark", src: logo, alt: said ? alt : "", style: { ...box, width: "auto" } });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The mark, the name and — where `subtitle` asks and the brand has one —
|
|
34
|
+
* the line under the name. Its type is the container's: the name takes
|
|
35
|
+
* the font, size and case it is drawn in; the line under it is the body's,
|
|
36
|
+
* quiet, and wraps rather than being cut.
|
|
37
|
+
*/
|
|
38
|
+
export function AppTitle({ brand, name, subtitle = false, size }) {
|
|
39
|
+
const line = subtitle ? brand?.subtitle : undefined;
|
|
40
|
+
return (_jsxs("span", { className: "graview-app-title", style: { display: "inline-flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [_jsx(AppMark, { brand: brand, ...(size !== undefined ? { size } : {}) }), _jsxs("span", { style: { display: "inline-flex", flexDirection: "column", minWidth: 0 }, children: [_jsx("span", { "data-testid": "app-name", children: name ?? brand?.name ?? "Graview" }), line ? (_jsx("span", { "data-testid": "app-subtitle", style: { fontFamily: "var(--graview-font-body)", fontSize: "0.8125rem", fontWeight: 400, letterSpacing: "normal", textTransform: "none", lineHeight: 1.35, color: "var(--graview-ink-muted)", whiteSpace: "normal", overflowWrap: "anywhere" }, children: line })) : null] })] }));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* THE PAGE'S ICON (FR-124), for a face that owns the whole page — the
|
|
44
|
+
* Shell, the routed face on its own, an embed its host told `favicon:
|
|
45
|
+
* true`. Every `<link rel="icon">` the page has points at it while the face
|
|
46
|
+
* is drawn, and back at what it pointed at after; a page with none gets
|
|
47
|
+
* one. `undefined` touches nothing, which is what an embed on somebody
|
|
48
|
+
* else's page passes.
|
|
49
|
+
*/
|
|
50
|
+
export function useFavicon(href) {
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!href || typeof document === "undefined")
|
|
53
|
+
return;
|
|
54
|
+
const links = [...document.querySelectorAll('link[rel~="icon"]')];
|
|
55
|
+
const was = links.map((link) => link.getAttribute("href"));
|
|
56
|
+
let made;
|
|
57
|
+
if (links.length === 0) {
|
|
58
|
+
made = document.createElement("link");
|
|
59
|
+
made.rel = "icon";
|
|
60
|
+
made.setAttribute("data-graview-favicon", "");
|
|
61
|
+
document.head.appendChild(made);
|
|
62
|
+
links.push(made);
|
|
63
|
+
}
|
|
64
|
+
for (const link of links)
|
|
65
|
+
link.href = href;
|
|
66
|
+
return () => {
|
|
67
|
+
if (made)
|
|
68
|
+
made.remove();
|
|
69
|
+
links.forEach((link, i) => {
|
|
70
|
+
if (link !== made && was[i] !== null && was[i] !== undefined)
|
|
71
|
+
link.setAttribute("href", was[i]);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}, [href]);
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=app-title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-title.js","sourceRoot":"","sources":["../src/app-title.tsx"],"names":[],"mappings":"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"}
|
package/dist/arrange-bar.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface ArrangeBarProps {
|
|
|
34
34
|
/** The far ends an edge condition may name, from the graph. */
|
|
35
35
|
/**
|
|
36
36
|
* The far ends a menu offers to narrow by. A menu is for choosing, not for
|
|
37
|
-
* reading a
|
|
37
|
+
* reading a catalog: past FAR_ENDS it holds the most connected (the ones a
|
|
38
38
|
* person most likely means), and the search reaches the rest — a select of
|
|
39
39
|
* 1,177 songs was 1,177 elements in every row that offered it (docs/scale.md).
|
|
40
40
|
*/
|
package/dist/arrange-bar.js
CHANGED
|
@@ -29,7 +29,7 @@ const control = {
|
|
|
29
29
|
* under the 24 a target needs, measured by a check that had only ever run
|
|
30
30
|
* in Chromium (the third walk's lesson, in the fifth). With the native
|
|
31
31
|
* appearance off the floor holds, and the chevron is drawn in the text's
|
|
32
|
-
*
|
|
32
|
+
* color the way the places menu draws it.
|
|
33
33
|
*/
|
|
34
34
|
const choice = {
|
|
35
35
|
...control,
|
|
@@ -66,7 +66,7 @@ const chip = {
|
|
|
66
66
|
/** The far ends an edge condition may name, from the graph. */
|
|
67
67
|
/**
|
|
68
68
|
* The far ends a menu offers to narrow by. A menu is for choosing, not for
|
|
69
|
-
* reading a
|
|
69
|
+
* reading a catalog: past FAR_ENDS it holds the most connected (the ones a
|
|
70
70
|
* person most likely means), and the search reaches the rest — a select of
|
|
71
71
|
* 1,177 songs was 1,177 elements in every row that offered it (docs/scale.md).
|
|
72
72
|
*/
|
|
@@ -242,7 +242,7 @@ function AddCondition({ schema, graph, offers, testId, onAdd, }) {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
else if (offer.type === "text") {
|
|
245
|
-
// A word field by the values it holds — a make, a
|
|
245
|
+
// A word field by the values it holds — a make, a color — when they are few enough to be a list rather than a name each.
|
|
246
246
|
const held = [...new Set(heldValues(graph, offers.kind, offer.key).filter((value) => typeof value === "string" && value.length > 0 && !value.includes(",")))].sort((a, b) => a.localeCompare(b));
|
|
247
247
|
if (held.length >= 2 && held.length <= WORD_VALUES) {
|
|
248
248
|
for (const word of held)
|