@graview/primitives 0.1.65 → 0.1.67
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/app-bar.d.ts +114 -15
- package/dist/app-bar.d.ts.map +1 -1
- package/dist/app-bar.js +192 -130
- package/dist/app-bar.js.map +1 -1
- package/dist/app-menu.d.ts +9 -0
- package/dist/app-menu.d.ts.map +1 -0
- package/dist/app-menu.js +60 -0
- package/dist/app-menu.js.map +1 -0
- package/dist/bar-activity.d.ts +5 -9
- package/dist/bar-activity.d.ts.map +1 -1
- package/dist/bar-activity.js +24 -7
- package/dist/bar-activity.js.map +1 -1
- package/dist/bar-panes.d.ts +5 -5
- package/dist/bar-panes.d.ts.map +1 -1
- package/dist/bar-panes.js +9 -5
- package/dist/bar-panes.js.map +1 -1
- package/dist/bar-suggested.d.ts +9 -1
- package/dist/bar-suggested.d.ts.map +1 -1
- package/dist/bar-suggested.js +11 -17
- package/dist/bar-suggested.js.map +1 -1
- package/dist/better-bar.d.ts +77 -0
- package/dist/better-bar.d.ts.map +1 -0
- package/dist/better-bar.js +312 -0
- package/dist/better-bar.js.map +1 -0
- package/dist/better-panel.d.ts +55 -0
- package/dist/better-panel.d.ts.map +1 -0
- package/dist/better-panel.js +151 -0
- package/dist/better-panel.js.map +1 -0
- package/dist/editable.d.ts +8 -1
- package/dist/editable.d.ts.map +1 -1
- package/dist/editable.js +140 -16
- package/dist/editable.js.map +1 -1
- package/dist/first-look-door.d.ts +2 -2
- package/dist/first-look-door.js +2 -2
- package/dist/first-look.d.ts.map +1 -1
- package/dist/first-look.js +9 -7
- package/dist/first-look.js.map +1 -1
- package/dist/frame.d.ts +2 -2
- package/dist/frame.d.ts.map +1 -1
- package/dist/frame.js +1 -1
- package/dist/frame.js.map +1 -1
- package/dist/inbox-pane.d.ts +31 -0
- package/dist/inbox-pane.d.ts.map +1 -0
- package/dist/inbox-pane.js +89 -0
- package/dist/inbox-pane.js.map +1 -0
- package/dist/inbox.d.ts +17 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +84 -0
- package/dist/inbox.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/lens/calendar-drawing.js +7 -3
- package/dist/lens/calendar-drawing.js.map +1 -1
- package/dist/menu-suggested.d.ts +54 -0
- package/dist/menu-suggested.d.ts.map +1 -0
- package/dist/menu-suggested.js +140 -0
- package/dist/menu-suggested.js.map +1 -0
- package/dist/menu-told-door.js +1 -1
- package/dist/menu-told-door.js.map +1 -1
- package/dist/menu-told.d.ts +7 -0
- package/dist/menu-told.d.ts.map +1 -1
- package/dist/menu-told.js +24 -0
- package/dist/menu-told.js.map +1 -1
- package/dist/notify-sheet.js +2 -2
- package/dist/notify-sheet.js.map +1 -1
- package/dist/page-better.d.ts +27 -0
- package/dist/page-better.d.ts.map +1 -0
- package/dist/page-better.js +747 -0
- package/dist/page-better.js.map +1 -0
- package/dist/page-parts.d.ts +41 -0
- package/dist/page-parts.d.ts.map +1 -0
- package/dist/page-parts.js +101 -0
- package/dist/page-parts.js.map +1 -0
- package/dist/pages.d.ts +2 -3
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +2 -3
- package/dist/pages.js.map +1 -1
- package/dist/profile.d.ts +1 -10
- package/dist/profile.d.ts.map +1 -1
- package/dist/profile.js +2 -3
- package/dist/profile.js.map +1 -1
- package/dist/scene-bar.d.ts +1 -1
- package/dist/scene-bar.d.ts.map +1 -1
- package/dist/scene-bar.js +4 -7
- package/dist/scene-bar.js.map +1 -1
- package/dist/section-better.d.ts +66 -9
- package/dist/section-better.d.ts.map +1 -1
- package/dist/section-better.js +285 -136
- package/dist/section-better.js.map +1 -1
- package/dist/section-door.d.ts +7 -0
- package/dist/section-door.d.ts.map +1 -1
- package/dist/section-door.js +39 -5
- package/dist/section-door.js.map +1 -1
- package/dist/section-menu.d.ts +23 -9
- package/dist/section-menu.d.ts.map +1 -1
- package/dist/section-menu.js +176 -23
- package/dist/section-menu.js.map +1 -1
- package/dist/section-words.d.ts +8 -0
- package/dist/section-words.d.ts.map +1 -1
- package/dist/section-words.js +25 -0
- package/dist/section-words.js.map +1 -1
- package/dist/shell.d.ts +7 -1
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +4 -2
- package/dist/shell.js.map +1 -1
- package/dist/suggested.d.ts +21 -10
- package/dist/suggested.d.ts.map +1 -1
- package/dist/suggested.js +80 -66
- package/dist/suggested.js.map +1 -1
- package/dist/suggestion-sentence.d.ts +50 -0
- package/dist/suggestion-sentence.d.ts.map +1 -0
- package/dist/suggestion-sentence.js +119 -0
- package/dist/suggestion-sentence.js.map +1 -0
- package/dist/told-card.js +1 -1
- package/dist/told-card.js.map +1 -1
- package/dist/told-ui.d.ts +1 -1
- package/dist/told-ui.d.ts.map +1 -1
- package/dist/told-ui.js +1 -1
- package/dist/told-ui.js.map +1 -1
- package/dist/when-words.d.ts +21 -0
- package/dist/when-words.d.ts.map +1 -0
- package/dist/when-words.js +43 -0
- package/dist/when-words.js.map +1 -0
- package/dist/workbench/activity.d.ts +44 -0
- package/dist/workbench/activity.d.ts.map +1 -1
- package/dist/workbench/activity.js +74 -59
- package/dist/workbench/activity.js.map +1 -1
- package/dist/workbench/inspector.d.ts.map +1 -1
- package/dist/workbench/inspector.js +170 -31
- package/dist/workbench/inspector.js.map +1 -1
- package/dist/workbench/standing.d.ts.map +1 -1
- package/dist/workbench/standing.js +1 -1
- package/dist/workbench/standing.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { layer } from "@graview/core";
|
|
3
|
+
import { Fragment, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
|
+
import { VISUALLY_HIDDEN } from "./primitives/measure.js";
|
|
5
|
+
const PHONE = 640;
|
|
6
|
+
const WIDE = 372;
|
|
7
|
+
const DRAWER = 1100;
|
|
8
|
+
const dockOf = () => (typeof innerWidth !== "number" || innerWidth >= DRAWER ? "side" : innerWidth >= PHONE ? "drawer" : "sheet");
|
|
9
|
+
/** The app's bar along the top of the window: the shell's, else a header that spans it. */
|
|
10
|
+
function barOf() {
|
|
11
|
+
const named = document.querySelector('[data-testid="app-bar"]');
|
|
12
|
+
if (named)
|
|
13
|
+
return named;
|
|
14
|
+
return [...document.querySelectorAll("header")].find((one) => {
|
|
15
|
+
const box = one.getBoundingClientRect();
|
|
16
|
+
return box.top <= 1 && box.width >= innerWidth * 0.8 && box.height > 0;
|
|
17
|
+
}) ?? null;
|
|
18
|
+
}
|
|
19
|
+
/** What holds the page under the bar: the widest box around the page's own region that is not around the bar too. */
|
|
20
|
+
function contentOf(bar) {
|
|
21
|
+
let at = document.querySelector("[data-graview-page-main], main");
|
|
22
|
+
while (at?.parentElement && at.parentElement !== document.body && !(bar && at.parentElement.contains(bar)))
|
|
23
|
+
at = at.parentElement;
|
|
24
|
+
return at;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* THE PANEL IS PART OF THE PAGE. Beside it, it is docked flush under the
|
|
28
|
+
* app's bar, at the right, down to the window's foot, and what holds the
|
|
29
|
+
* page gives up its width — the bar spans the window as always, and
|
|
30
|
+
* nothing behind the panel shows. Where the window is narrow it is a
|
|
31
|
+
* drawer over the page's right side, and on a phone a sheet from the
|
|
32
|
+
* bottom with room left below the page. Followed each frame: a bar that
|
|
33
|
+
* scrolls away leaves the panel the window's full height.
|
|
34
|
+
*/
|
|
35
|
+
function useDock(panel) {
|
|
36
|
+
const [dock, setDock] = useState(dockOf);
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
const body = document.body.style;
|
|
39
|
+
const bottom = body.paddingBottom;
|
|
40
|
+
let content = null;
|
|
41
|
+
let right = "";
|
|
42
|
+
let frame = 0;
|
|
43
|
+
const give = (to, wide) => {
|
|
44
|
+
if (content && content !== to)
|
|
45
|
+
content.style.paddingRight = right;
|
|
46
|
+
if (to && to !== content)
|
|
47
|
+
right = to.style.paddingRight;
|
|
48
|
+
content = to;
|
|
49
|
+
if (content)
|
|
50
|
+
content.style.paddingRight = wide ? `${WIDE}px` : right;
|
|
51
|
+
};
|
|
52
|
+
const place = () => {
|
|
53
|
+
const now = dockOf();
|
|
54
|
+
setDock(now);
|
|
55
|
+
const bar = barOf();
|
|
56
|
+
const top = Math.max(0, Math.round(bar?.getBoundingClientRect().bottom ?? 0));
|
|
57
|
+
if (panel.current && now !== "sheet")
|
|
58
|
+
panel.current.style.top = `${top}px`;
|
|
59
|
+
give(contentOf(bar), now === "side");
|
|
60
|
+
body.paddingBottom = now === "sheet" ? `${Math.round((panel.current?.getBoundingClientRect().height ?? 0) + 16)}px` : bottom;
|
|
61
|
+
frame = requestAnimationFrame(place);
|
|
62
|
+
};
|
|
63
|
+
place();
|
|
64
|
+
return () => {
|
|
65
|
+
cancelAnimationFrame(frame);
|
|
66
|
+
give(null, false);
|
|
67
|
+
body.paddingBottom = bottom;
|
|
68
|
+
};
|
|
69
|
+
}, [panel]);
|
|
70
|
+
return dock;
|
|
71
|
+
}
|
|
72
|
+
/** Minutes and seconds: "0:42". */
|
|
73
|
+
const elapsed = (ms) => `${Math.floor(ms / 60_000)}:${String(Math.floor((ms % 60_000) / 1000)).padStart(2, "0")}`;
|
|
74
|
+
export function BetterPanel(props) {
|
|
75
|
+
const panel = useRef(null);
|
|
76
|
+
const list = useRef(null);
|
|
77
|
+
const field = useRef(null);
|
|
78
|
+
const [typed, setTyped] = useState("");
|
|
79
|
+
const [, tick] = useState(0);
|
|
80
|
+
const dock = useDock(panel);
|
|
81
|
+
/* The running time, while it works. */
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!props.working)
|
|
84
|
+
return;
|
|
85
|
+
const timer = setInterval(() => tick((one) => one + 1), 1000);
|
|
86
|
+
return () => clearInterval(timer);
|
|
87
|
+
}, [props.working]);
|
|
88
|
+
/* The newest line in view, and the keyboard in the words field once it is the person's turn. */
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
// Within the conversation only: scrolling the newest line into view must never move the panel, nor hide the first line under its head.
|
|
91
|
+
if (list.current)
|
|
92
|
+
list.current.scrollTop = list.current.scrollHeight;
|
|
93
|
+
}, [props.talk.length, props.steps.length]);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!props.working)
|
|
96
|
+
field.current?.focus({ preventScroll: true });
|
|
97
|
+
}, [props.working, props.phase]);
|
|
98
|
+
const lastAsked = props.talk.map((line) => line.who).lastIndexOf("person");
|
|
99
|
+
const steps = props.steps.length > 0 ? (_jsx("li", { "data-testid": "better-steps", style: STEPS, children: _jsx("ol", { style: { margin: 0, padding: 0, listStyle: "none", display: "grid", gap: 3 }, children: props.steps.map((step, at) => {
|
|
100
|
+
const now = props.working && at === props.steps.length - 1;
|
|
101
|
+
return (_jsxs("li", { "data-testid": "better-step", "data-step-kind": step.kind, style: { display: "flex", gap: 6, alignItems: "baseline", color: now ? "var(--graview-ink)" : "var(--graview-ink-muted)" }, children: [_jsx("span", { "aria-hidden": "true", style: { width: 14, flex: "none", color: step.kind === "check" || step.kind === "stuck" ? "var(--graview-warn)" : "var(--graview-accent)" }, children: now ? "…" : step.kind === "check" || step.kind === "stuck" ? "!" : "✓" }), _jsx("span", { children: step.text })] }, `s${at}`));
|
|
102
|
+
}) }) })) : null;
|
|
103
|
+
const empty = props.talk.length === 0;
|
|
104
|
+
return (_jsxs("aside", { ref: panel, role: "complementary", "aria-label": `Change how “${props.name}” looks`, "data-testid": "better-panel", "data-better-phase": props.phase, "data-better-dock": dock, "data-graview-popover": "", style: dock === "sheet" ? SHEET : dock === "drawer" ? DRAWER_STYLE : SIDE, children: [_jsxs("header", { style: HEAD, children: [_jsxs("p", { style: { margin: 0, fontWeight: 600 }, children: ["Change how \u201C", props.name, "\u201D looks"] }), _jsx("button", { type: "button", "data-testid": "better-close", "aria-label": "Close", onClick: props.close, style: ICON, children: "\u00D7" })] }), _jsx("p", { "data-testid": "better-scope", style: QUIET_LINE, children: props.scope }), props.about ? (_jsxs("p", { "data-testid": "better-about", style: CHIP, children: ["About: ", props.about] })) : null, _jsxs("ol", { ref: list, "data-testid": "better-talk", style: TALK, children: [props.talk.map((line, at) => (_jsxs(Fragment, { children: [_jsx("li", { "data-testid": "better-message", "data-who": line.who, style: line.who === "person" ? MINE : THEIRS, children: line.said }), at === lastAsked ? steps : null] }, `t${at}`))), lastAsked < 0 ? steps : null] }), props.working ? (_jsxs("div", { style: ROW, children: [_jsxs("p", { role: "status", "aria-live": "polite", "data-testid": "better-working", style: { margin: 0, flex: 1, color: "var(--graview-ink-muted)" }, children: ["Graview is working on \u201C", props.name, "\u201D \u00B7 ", _jsx("span", { "data-testid": "better-time", children: elapsed(Date.now() - props.since) })] }), _jsx("button", { type: "button", "data-testid": "better-stop", onClick: props.stop, style: QUIET, children: "Stop" })] })) : null, props.draft && !props.working ? (_jsxs("div", { "data-testid": "better-draft", style: { flexShrink: 0, display: "grid", gap: 6 }, children: [_jsx("p", { "data-testid": "better-changed", style: { margin: 0 }, children: props.draft.said }), _jsxs("div", { style: ROW, children: [_jsx("div", { role: "group", "aria-label": "Compare", style: SWITCH, children: ["Before", "After"].map((side) => {
|
|
105
|
+
const on = side === "Before" ? props.draft.before : !props.draft.before;
|
|
106
|
+
return (_jsx("button", { type: "button", "data-testid": `better-${side.toLowerCase()}`, "aria-pressed": on, onClick: () => props.compare(side === "Before"), style: on ? SWITCH_ON : SWITCH_OFF, children: side }, side));
|
|
107
|
+
}) }), _jsxs("span", { style: { marginLeft: "auto", display: "inline-flex", gap: 6 }, children: [_jsx("button", { type: "button", "data-testid": "better-keep", onClick: props.keep, style: PRIMARY, children: "Keep" }), _jsx("button", { type: "button", "data-testid": "better-discard", onClick: props.discard, style: QUIET, children: "Discard" })] })] })] })) : null, props.stuck && !props.working ? (_jsxs("div", { "data-testid": "better-stuck", style: ROW, children: [props.stuck.keepAnyway ? (_jsx("button", { type: "button", "data-testid": "better-keep-anyway", onClick: props.stuck.keepAnyway, style: QUIET, children: "Keep anyway" })) : null, _jsx("button", { type: "button", "data-testid": "better-stuck-stop", onClick: props.stuck.stop, style: QUIET, children: "Stop" })] })) : null, props.children, props.kept && !props.working ? (_jsxs("div", { "data-testid": "better-kept", style: ROW, children: [_jsx("p", { style: { margin: 0, flex: 1 }, children: props.kept.note ? (/^kept\b/i.test(props.kept.note.trim()) ? props.kept.note.trim() : `Kept. ${props.kept.note}`) : "Kept." }), props.kept.undo ? (_jsx("button", { type: "button", "data-testid": "better-undo", onClick: props.kept.undo, style: QUIET, children: "Undo" })) : null] })) : null, empty && !props.working ? (_jsxs("div", { style: ROW, children: [_jsx("button", { type: "button", "data-testid": "better-just", onClick: props.just, style: QUIET, children: "Make it easier to read" }), _jsx("button", { type: "button", "data-testid": "better-point", onClick: props.point, style: QUIET, children: "Point at a part\u2026" })] })) : null, props.pointed && !props.working ? (_jsxs("p", { "data-testid": "better-pointed", style: QUIET_LINE, children: ["You pointed at ", props.pointed, "."] })) : null, _jsxs("form", { onSubmit: (event) => {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
if (!typed.trim() || props.working)
|
|
110
|
+
return;
|
|
111
|
+
props.ask(typed.trim());
|
|
112
|
+
setTyped("");
|
|
113
|
+
}, style: { flexShrink: 0, display: "flex", gap: 6 }, children: [_jsx("label", { htmlFor: "graview-better-panel-words", style: VISUALLY_HIDDEN, children: "Tell Graview what to change" }), _jsx("input", { id: "graview-better-panel-words", ref: field, "data-testid": "better-words", value: typed, disabled: props.working, onChange: (event) => setTyped(event.target.value), placeholder: empty ? "What should change?" : "Tell Graview what to change…", style: FIELD }), _jsx("button", { type: "submit", disabled: props.working || !typed.trim(), "data-testid": "better-send", style: PRIMARY, children: "Send" })] })] }));
|
|
114
|
+
}
|
|
115
|
+
/* The shell's own surface, one line from the page: part of the app, in its light and dark alike. */
|
|
116
|
+
const BASE = {
|
|
117
|
+
position: "fixed",
|
|
118
|
+
zIndex: layer("popover"),
|
|
119
|
+
boxSizing: "border-box",
|
|
120
|
+
display: "flex",
|
|
121
|
+
flexDirection: "column",
|
|
122
|
+
gap: 10,
|
|
123
|
+
padding: 14,
|
|
124
|
+
margin: 0,
|
|
125
|
+
fontSize: "0.875rem",
|
|
126
|
+
lineHeight: 1.45,
|
|
127
|
+
color: "var(--graview-ink)",
|
|
128
|
+
background: "var(--graview-panel)",
|
|
129
|
+
overflow: "hidden",
|
|
130
|
+
};
|
|
131
|
+
const SIDE = { ...BASE, top: 0, right: 0, bottom: 0, width: WIDE, borderLeft: "1px solid var(--graview-edge)" };
|
|
132
|
+
const DRAWER_STYLE = { ...SIDE, width: `min(${WIDE}px, 86vw)`, boxShadow: "var(--graview-lift-high, -12px 0 32px rgba(0,0,0,0.18))" };
|
|
133
|
+
const SHEET = { ...BASE, left: 0, right: 0, bottom: 0, maxHeight: "55vh", borderTop: "1px solid var(--graview-edge)", borderRadius: "14px 14px 0 0", boxShadow: "var(--graview-lift-high, 0 -12px 32px rgba(0,0,0,0.18))" };
|
|
134
|
+
const CHIP = { flexShrink: 0, margin: 0, justifySelf: "start", alignSelf: "flex-start", padding: "2px 10px", borderRadius: 999, fontSize: "0.8125rem", color: "var(--graview-ink)", background: "var(--graview-ground)", border: "1px solid var(--graview-edge)" };
|
|
135
|
+
const HEAD = { flexShrink: 0, display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between" };
|
|
136
|
+
const QUIET_LINE = { flexShrink: 0, margin: 0, fontSize: "0.8125rem", color: "var(--graview-ink-muted)" };
|
|
137
|
+
const TALK = { margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 8, overflowY: "auto", flex: "1 1 0", minHeight: 0 };
|
|
138
|
+
const BUBBLE = { padding: "7px 10px", borderRadius: 10, maxWidth: "88%", whiteSpace: "pre-wrap", flex: "none" };
|
|
139
|
+
const MINE = { ...BUBBLE, alignSelf: "flex-end", background: "color-mix(in srgb, var(--graview-accent) 12%, var(--graview-panel))" };
|
|
140
|
+
const THEIRS = { ...BUBBLE, alignSelf: "flex-start", background: "var(--graview-ground)" };
|
|
141
|
+
const STEPS = { flex: "none", padding: "6px 10px", borderRadius: 10, border: "1px dashed var(--graview-edge)", fontSize: "0.8125rem" };
|
|
142
|
+
const ROW = { flexShrink: 0, display: "flex", flexWrap: "wrap", alignItems: "center", gap: 6 };
|
|
143
|
+
const BUTTON = { minHeight: 32, padding: "0 12px", borderRadius: 8, fontSize: "0.8125rem", cursor: "pointer" };
|
|
144
|
+
const PRIMARY = { ...BUTTON, color: "var(--graview-accent-ink, #fff)", background: "var(--graview-accent)", border: "1px solid var(--graview-accent)" };
|
|
145
|
+
const QUIET = { ...BUTTON, color: "var(--graview-ink)", background: "transparent", border: "1px solid var(--graview-edge)" };
|
|
146
|
+
const ICON = { ...QUIET, minHeight: 28, padding: "0 9px", fontSize: "1rem", lineHeight: 1 };
|
|
147
|
+
const FIELD = { flex: "1 1 auto", minWidth: 0, minHeight: 34, padding: "0 10px", borderRadius: 8, border: "1px solid var(--graview-edge)", background: "var(--graview-panel)", color: "var(--graview-ink)", fontSize: "0.875rem" };
|
|
148
|
+
const SWITCH = { display: "inline-flex", border: "1px solid var(--graview-edge)", borderRadius: 999, padding: 2 };
|
|
149
|
+
const SWITCH_ON = { ...BUTTON, minHeight: 28, borderRadius: 999, border: "none", color: "var(--graview-accent-ink, #fff)", background: "var(--graview-accent)" };
|
|
150
|
+
const SWITCH_OFF = { ...BUTTON, minHeight: 28, borderRadius: 999, border: "none", color: "var(--graview-ink)", background: "transparent" };
|
|
151
|
+
//# sourceMappingURL=better-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-panel.js","sourceRoot":"","sources":["../src/better-panel.tsx"],"names":[],"mappings":"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"}
|
package/dist/editable.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { type CSSProperties } from "react";
|
|
|
14
14
|
* it undoable, and what the invariants judge. Writing the graph here would
|
|
15
15
|
* create the one class of change nobody could take back.
|
|
16
16
|
*/
|
|
17
|
-
export declare function EditableValue<S extends AnySchema>({ nodeId, field, value, stored, said, blank, }: {
|
|
17
|
+
export declare function EditableValue<S extends AnySchema>({ nodeId, field, value, stored, said, blank, late, }: {
|
|
18
18
|
readonly nodeId: string;
|
|
19
19
|
readonly field: string;
|
|
20
20
|
/** The value as a person reads it: "Aug 28, 2026", "Tue". */
|
|
@@ -35,6 +35,13 @@ export declare function EditableValue<S extends AnySchema>({ nodeId, field, valu
|
|
|
35
35
|
* `said` names it ("Add Allocation").
|
|
36
36
|
*/
|
|
37
37
|
readonly blank?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* A DATE A RULE SAYS IS LATE (Roadmap f-facts-by-type): drawn in the
|
|
40
|
+
* warning color. Said by the page from its problems — a repair that asks
|
|
41
|
+
* for this field again — never guessed from the date alone: a talk given
|
|
42
|
+
* in 2017 is past, not late.
|
|
43
|
+
*/
|
|
44
|
+
readonly late?: boolean;
|
|
38
45
|
}): import("react").JSX.Element;
|
|
39
46
|
/**
|
|
40
47
|
* A PHONE OR A PLACE, AS WHERE IT LEADS: a `tel:` link that calls it, or a
|
package/dist/editable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable.d.ts","sourceRoot":"","sources":["../src/editable.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"editable.d.ts","sourceRoot":"","sources":["../src/editable.tsx"],"names":[],"mappings":"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"}
|
package/dist/editable.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import { fieldWords, humanizeField as humanize, TYPE_TEXT } from "@graview/core";
|
|
3
|
-
import { valueWords } from "@graview/core/words";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { defOf, fieldWords, humanizeField as humanize, TYPE_TEXT } from "@graview/core";
|
|
3
|
+
import { failureWords, valueWords } from "@graview/core/words";
|
|
4
4
|
import { amountBox, amountInBox, endAfterStartMoved, pageSections, parseDuration, readableFields, readAmount, startAndEndOf } from "@graview/core/words";
|
|
5
5
|
import { fileFieldsOf } from "@graview/core/blocks";
|
|
6
6
|
import { useEditableFields } from "@graview/react/drawing";
|
|
@@ -12,6 +12,7 @@ import { AppLink } from "./app-link-door.js";
|
|
|
12
12
|
import { LinkedRecordView } from "./linked-record-door.js";
|
|
13
13
|
import { RepeatEditor } from "./repeat-picker-door.js";
|
|
14
14
|
import { prefetchWhenInput, WhenInput } from "./when-input-door.js";
|
|
15
|
+
import { todayOf, whenSaid } from "./when-words.js";
|
|
15
16
|
/**
|
|
16
17
|
* One field's value, changeable where it is shown when something can change
|
|
17
18
|
* it — and visibly read-only when nothing can.
|
|
@@ -26,8 +27,8 @@ import { prefetchWhenInput, WhenInput } from "./when-input-door.js";
|
|
|
26
27
|
* it undoable, and what the invariants judge. Writing the graph here would
|
|
27
28
|
* create the one class of change nobody could take back.
|
|
28
29
|
*/
|
|
29
|
-
export function EditableValue({ nodeId, field, value, stored = value, said, blank = false, }) {
|
|
30
|
-
const { fields, commit } = useEditableFields(nodeId);
|
|
30
|
+
export function EditableValue({ nodeId, field, value, stored = value, said, blank = false, late = false, }) {
|
|
31
|
+
const { fields, commit: send } = useEditableFields(nodeId);
|
|
31
32
|
const editable = fields.find((candidate) => candidate.field === field);
|
|
32
33
|
// The field as the declaration says it: a tooltip read "changes "plannedAt"".
|
|
33
34
|
const { store, principal } = useGraview();
|
|
@@ -35,7 +36,11 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
35
36
|
const definition = store.schema.definitions.find((one) => one.kind === kind);
|
|
36
37
|
const fact = fieldWords(definition, field);
|
|
37
38
|
const words = fact.toLowerCase();
|
|
38
|
-
|
|
39
|
+
// An empty slot is named by what it does, with the fact where its words do not say it: "Add notes", "Due: pick a day".
|
|
40
|
+
const emptied = blank && editable ? blankWords(editable, fact) : undefined;
|
|
41
|
+
const named = emptied !== undefined
|
|
42
|
+
? emptied.toLowerCase().includes(words) ? emptied : `${fact.charAt(0).toUpperCase()}${fact.slice(1)}: ${emptied.charAt(0).toLowerCase()}${emptied.slice(1)}`
|
|
43
|
+
: said ?? `${fact.charAt(0).toUpperCase()}${fact.slice(1)}: ${value}`;
|
|
39
44
|
const [editing, setEditing] = useState(false);
|
|
40
45
|
// An amount is edited as it is said, less its symbol: "10,000" beside "$", never a bare 10000 (money said as money).
|
|
41
46
|
const amount = editable?.shape.type === "number" ? editable.shape.amount : undefined;
|
|
@@ -58,6 +63,22 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
58
63
|
const comeBack = useRef(false);
|
|
59
64
|
/* What emptying a field it cannot be without said, beside the value it kept (Roadmap f-clear-date-in-place). */
|
|
60
65
|
const [refused, setRefused] = useState(undefined);
|
|
66
|
+
/*
|
|
67
|
+
* A CHANGE THE STORE REFUSES IS SAID BESIDE ITS VALUE (Roadmap
|
|
68
|
+
* f-facts-by-type): a length past its longest, a rule's own refusal, in
|
|
69
|
+
* the words a form would say it — never a page error with the value
|
|
70
|
+
* quietly as it was.
|
|
71
|
+
*/
|
|
72
|
+
const refusing = (run) => {
|
|
73
|
+
try {
|
|
74
|
+
run();
|
|
75
|
+
setRefused(undefined);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
setRefused(failureWords(store.schema, store.allMutations(), error));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const commit = (writer, next) => refusing(() => send(writer, next));
|
|
61
82
|
const close = (keepTheKeyboard) => {
|
|
62
83
|
comeBack.current = keepTheKeyboard;
|
|
63
84
|
setEditing(false);
|
|
@@ -82,15 +103,72 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
82
103
|
opener.current?.focus();
|
|
83
104
|
}
|
|
84
105
|
}, [editing]);
|
|
106
|
+
/*
|
|
107
|
+
* EACH VALUE BY ITS TYPE (Roadmap f-facts-by-type). A yes or no is a
|
|
108
|
+
* switch, a day is said with its weekday and how far it is, a choice of a
|
|
109
|
+
* few is its options side by side and of many a menu — each still the one
|
|
110
|
+
* act the framework found, so the change is in the history and can be
|
|
111
|
+
* taken back. The scene's card and the record's page draw the same.
|
|
112
|
+
*/
|
|
113
|
+
const record = store.graph.getNode(nodeId);
|
|
114
|
+
const kept = record?.[field];
|
|
115
|
+
const declared = definition?.fields?.shape?.[field];
|
|
116
|
+
const formatted = definition?.display?.format?.[field];
|
|
117
|
+
const yesNo = typeof kept === "boolean" || ((kept === undefined || kept === null) && baseTypeOf(declared) === "boolean");
|
|
118
|
+
// A date that repeats says how, and the next one ("Every Tuesday, next Oct 27"): its own words, kept.
|
|
119
|
+
const repeats = record?.[`${field}Repeat`] !== undefined || Object.hasOwn(definition?.fields?.shape ?? {}, `${field}Repeat`);
|
|
120
|
+
const when = formatted === undefined && !blank && !repeats && typeof kept === "string" ? whenSaid(kept, todayOf(store)) : undefined;
|
|
121
|
+
const shown = when ? when.words : value;
|
|
122
|
+
const lateStyle = late && when?.past ? { color: "var(--graview-warn)" } : {};
|
|
123
|
+
const worked = definition?.computed !== undefined && Object.hasOwn(definition.computed, field);
|
|
124
|
+
const refusal = refused ? (_jsx("span", { role: "status", "data-graview-refused": field, style: { marginLeft: 6, fontSize: "0.75rem", color: "var(--graview-ink-muted)" }, children: refused })) : null;
|
|
125
|
+
if (editable && yesNo) {
|
|
126
|
+
const on = kept === true;
|
|
127
|
+
const writers = [editable, ...editable.alternatives];
|
|
128
|
+
const byValue = writers.find((one) => one.takesValue && one.shape.type === "boolean");
|
|
129
|
+
// A writer that takes the value is sent the other one; acts that take none, the one that would change it ("Mark it done", or "Put it back").
|
|
130
|
+
const call = byValue ? byValue.call(!on) : writers.map((one) => one.call(undefined)).find((one) => store.wouldChange(one, principal));
|
|
131
|
+
if (call) {
|
|
132
|
+
const words = value || (formatted ? formatted(on) : on ? "Yes" : "No");
|
|
133
|
+
const act = writers.find((one) => one.mutation === call.name) ?? editable;
|
|
134
|
+
return (_jsxs("span", { style: { display: "inline-flex", alignItems: "center", flexWrap: "wrap", gap: 6, maxWidth: "100%" }, children: [_jsxs("button", { type: "button", role: "switch", "aria-checked": on, "aria-label": `${fact.charAt(0).toUpperCase()}${fact.slice(1)}`, "data-graview-field": field, "data-graview-editable": act.mutation, "data-graview-switch": "", title: `${act.title} — changes the ${fact.toLowerCase()}, and can be undone`, onClick: () => refusing(() => store.apply(call, { author: principal })), style: SWITCH, children: [_jsx("span", { "aria-hidden": "true", "data-graview-track": "", style: { ...TRACK, background: on ? "var(--graview-accent)" : "color-mix(in oklab, var(--graview-ink) 24%, transparent)" }, children: _jsx("span", { style: { ...KNOB, transform: on ? "translateX(12px)" : "none", background: on ? "var(--graview-accent-ink, #fff)" : "var(--graview-ground)" } }) }), _jsx("span", { "aria-hidden": "true", children: words })] }), refusal] }));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
85
137
|
if (!editable) {
|
|
86
|
-
return (
|
|
138
|
+
return (_jsxs("span", { "data-graview-field": field, "data-graview-readonly": "",
|
|
87
139
|
// Said, not merely implied: a value that ignores a click looks broken.
|
|
88
|
-
title: `Read-only — nothing this app
|
|
140
|
+
title: `Read-only — nothing in this app changes the ${words}`,
|
|
89
141
|
// An address, a VIN, a URL has nowhere to break: it breaks anywhere rather than run into the next column.
|
|
90
|
-
style: { color: "var(--graview-ink)", cursor: "default", overflowWrap: "anywhere" }, children:
|
|
142
|
+
style: { color: "var(--graview-ink)", cursor: "default", overflowWrap: "anywhere", ...lateStyle }, children: [shown, worked ? (_jsx("span", { "data-graview-worked-out": "", title: "Worked out from the other facts; it changes when they do", style: { marginLeft: 8, fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: "worked out" })) : null] }));
|
|
143
|
+
}
|
|
144
|
+
/*
|
|
145
|
+
* A CHOICE IS ITS OPTIONS (Roadmap f-facts-by-type): a few, side by side,
|
|
146
|
+
* the one chosen pressed — one press to change; many, a menu that opens
|
|
147
|
+
* at the first press. Before, the value opened a menu that then had to be
|
|
148
|
+
* opened again.
|
|
149
|
+
*/
|
|
150
|
+
if (!editing && editable.takesValue && editable.shape.type === "choice" && editable.open.length === 0) {
|
|
151
|
+
const options = editable.shape.options;
|
|
152
|
+
const chosen = typeof kept === "string" ? kept : "";
|
|
153
|
+
const name = `${fact.charAt(0).toUpperCase()}${fact.slice(1)}`;
|
|
154
|
+
const few = options.length <= 4 && options.every((option) => valueWords(definition, field, option).length <= 14);
|
|
155
|
+
const pick = (next) => {
|
|
156
|
+
if (next === chosen)
|
|
157
|
+
return;
|
|
158
|
+
if (next === "") {
|
|
159
|
+
if (editable.clearable)
|
|
160
|
+
commit(editable, null);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
commit(editable, next);
|
|
164
|
+
};
|
|
165
|
+
return (_jsxs("span", { style: { display: "inline-flex", alignItems: "center", flexWrap: "wrap", gap: 6, maxWidth: "100%" }, children: [few ? (_jsx("span", { role: "group", "aria-label": name, "data-graview-field": field, "data-graview-editable": editable.mutation, "data-graview-choices": field, style: SEGMENTS, children: options.map((option) => {
|
|
166
|
+
const pressed = option === chosen;
|
|
167
|
+
return (_jsx("button", { type: "button", "aria-pressed": pressed, "data-graview-option": option, title: `${editable.title} — changes the ${words}, and can be undone`, onClick: () => pick(option), style: { ...SEGMENT, ...(pressed ? SEGMENT_ON : {}) }, children: valueWords(definition, field, option) }, option));
|
|
168
|
+
}) })) : (_jsxs("select", { "aria-label": name, "data-graview-field": field, "data-graview-editable": editable.mutation, title: `${editable.title} — changes the ${words}, and can be undone`, value: chosen, onChange: (event) => pick(event.target.value), style: MENU, children: [chosen === "" || editable.clearable ? _jsx("option", { value: "", children: chosen === "" && !editable.clearable ? "Choose…" : "None" }) : null, options.map((option) => (_jsx("option", { value: option, children: valueWords(definition, field, option) }, option)))] })), refusal] }));
|
|
91
169
|
}
|
|
92
170
|
if (!editing) {
|
|
93
|
-
const button = (
|
|
171
|
+
const button = (_jsxs("button", { ref: opener, type: "button", "data-graview-field": field, "data-graview-editable": editable.mutation, ...(blank ? { "data-graview-blank": "" } : {}), ...(named === value ? {} : { "aria-label": named }), title: `${editable.title} — changes the ${words}, and can be undone`, onClick: () => {
|
|
94
172
|
setRefused(undefined);
|
|
95
173
|
setEditing(true);
|
|
96
174
|
}, style: {
|
|
@@ -118,12 +196,13 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
118
196
|
overflowWrap: "anywhere",
|
|
119
197
|
paddingBottom: 1,
|
|
120
198
|
borderBottom: "1px dashed var(--graview-edge-bright)",
|
|
121
|
-
// An empty slot says
|
|
199
|
+
// An empty slot says what pressing it does, dim beside the values that are there.
|
|
122
200
|
color: blank ? "var(--graview-ink-muted)" : "var(--graview-ink)",
|
|
123
|
-
|
|
201
|
+
...lateStyle,
|
|
202
|
+
}, children: [blank ? blankWords(editable, fact) : shown, !blank && !editable.takesValue ? _jsx("span", { "aria-hidden": "true", style: { marginLeft: 4, fontSize: "0.75em", color: "var(--graview-ink-faint)" }, children: "\u25BE" }) : null] }));
|
|
124
203
|
if (!refused)
|
|
125
204
|
return button;
|
|
126
|
-
return (_jsxs(_Fragment, { children: [button,
|
|
205
|
+
return (_jsxs(_Fragment, { children: [button, refusal] }));
|
|
127
206
|
}
|
|
128
207
|
/** Commit the draft. `left` says the person already moved the keyboard elsewhere. */
|
|
129
208
|
const done = (next, { left = false } = {}) => {
|
|
@@ -145,6 +224,19 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
145
224
|
setRefused(`${fact.charAt(0).toUpperCase()}${fact.slice(1)} can't be empty; it keeps ${value}.`);
|
|
146
225
|
return;
|
|
147
226
|
}
|
|
227
|
+
/*
|
|
228
|
+
* A NUMBER PAST ITS RANGE IS SAID SO, IN WORDS, BESIDE IT (Roadmap
|
|
229
|
+
* f-facts-by-type): the box's own range stopped Enter in silence on one
|
|
230
|
+
* engine and in a bubble that left on another.
|
|
231
|
+
*/
|
|
232
|
+
if (editable.shape.type === "number" && typeof next === "number" && Number.isFinite(next)) {
|
|
233
|
+
const { min, max } = editable.shape;
|
|
234
|
+
const Fact = `${fact.charAt(0).toUpperCase()}${fact.slice(1)}`;
|
|
235
|
+
if (max !== undefined && next > max)
|
|
236
|
+
return void setRefused(`${Fact} is at most ${max}; it keeps ${value}.`);
|
|
237
|
+
if (min !== undefined && next < min)
|
|
238
|
+
return void setRefused(`${Fact} is at least ${min}; it keeps ${value}.`);
|
|
239
|
+
}
|
|
148
240
|
if (editable.shape.type === "date" && typeof next === "string" && withItsEnd(next))
|
|
149
241
|
return;
|
|
150
242
|
commit(editable, next);
|
|
@@ -171,7 +263,7 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
171
263
|
return false;
|
|
172
264
|
const starting = editable.call(next);
|
|
173
265
|
const following = ending.call(moved);
|
|
174
|
-
store.applyAll(starting.name === following.name ? [{ name: starting.name, args: { ...starting.args, ...following.args } }] : [starting, following], { author: principal });
|
|
266
|
+
refusing(() => store.applyAll(starting.name === following.name ? [{ name: starting.name, args: { ...starting.args, ...following.args } }] : [starting, following], { author: principal }));
|
|
175
267
|
return true;
|
|
176
268
|
};
|
|
177
269
|
/*
|
|
@@ -225,7 +317,9 @@ export function EditableValue({ nodeId, field, value, stored = value, said, blan
|
|
|
225
317
|
close(false);
|
|
226
318
|
}, children: [_jsx("legend", { style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)" }, children: humanize(field) }), options.map((option, index) => (_jsxs("label", { style: { display: "inline-flex", alignItems: "center", gap: 4, minHeight: 24, cursor: "pointer" }, children: [_jsx("input", { ref: index === 0 ? input : undefined, type: "checkbox", value: option, checked: chosen.includes(option), onChange: (event) => sendChosen(event.target.checked ? [...chosen, option] : chosen.filter((one) => one !== option)) }), valueWords(definition, field, option)] }, option)))] }));
|
|
227
319
|
}
|
|
228
|
-
return (_jsxs("form", {
|
|
320
|
+
return (_jsxs("form", {
|
|
321
|
+
// The range is said in words beside the value when it is passed (`done`), never stopped in silence by the box.
|
|
322
|
+
noValidate: true, style: { display: "inline-flex", flexWrap: "wrap", gap: 4, maxWidth: "100%" }, onSubmit: (event) => {
|
|
229
323
|
event.preventDefault();
|
|
230
324
|
done(coerce(editable, draft));
|
|
231
325
|
}, children: [editable.shape.type === "choice" ? (_jsxs("select", { ref: input, "aria-label": humanize(field), "data-graview-field": field, value: draft, onChange: (event) => done(event.target.value), onBlur: () => close(false), style: { font: "inherit", fontSize: "inherit" }, children: [draft === "" ? _jsx("option", { value: "", disabled: true, children: "Choose\u2026" }) : null, editable.shape.options.map((option) => (_jsx("option", { value: option, children: valueWords(definition, field, option) }, option)))] })) : editable.shape.type === "date" ? (
|
|
@@ -392,7 +486,7 @@ function EditableProse({ nodeId, field, label, value, labelStyle, valueStyle, st
|
|
|
392
486
|
close(!left);
|
|
393
487
|
if (draft !== value)
|
|
394
488
|
commit(editable, draft);
|
|
395
|
-
} }) })) : (_jsx("div", { "data-graview-field": field, ...(editable ? {} : { "data-graview-readonly": "", title: `Read-only — nothing this app
|
|
489
|
+
} }) })) : (_jsx("div", { "data-graview-field": field, ...(editable ? {} : { "data-graview-readonly": "", title: `Read-only — nothing in this app changes the ${words}` }), ...(editable ? { onClick: () => setEditing(true) } : {}), style: { cursor: editable ? "text" : "default", minWidth: 0 }, children: drawn })) })] }));
|
|
396
490
|
}
|
|
397
491
|
/* The text area, fetched the first time somebody opens one (FR-57's way: a page's first load carries what it draws). */
|
|
398
492
|
const ProseEditor = lazy(() => import("./prose-editor.js"));
|
|
@@ -436,4 +530,34 @@ export function EditableTitle({ nodeId, children, }) {
|
|
|
436
530
|
// A heading's words, said as they are: the heading says what it is.
|
|
437
531
|
return _jsx(EditableValue, { nodeId: nodeId, field: writable.field, value: children, said: children });
|
|
438
532
|
}
|
|
533
|
+
/** What a declared field holds under optional, default and nullable: "boolean", "string", "enum". */
|
|
534
|
+
function baseTypeOf(schema) {
|
|
535
|
+
const def = defOf(schema);
|
|
536
|
+
if (!def)
|
|
537
|
+
return undefined;
|
|
538
|
+
return def.type === "optional" || def.type === "nullable" || def.type === "default" ? baseTypeOf(def.innerType) : def.type;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* WHAT AN EMPTY SLOT SAYS PRESSING IT DOES (Roadmap f-facts-by-type): "Pick
|
|
542
|
+
* a day" beside "Due", "Choose…" beside a choice, "Add notes" beside
|
|
543
|
+
* "Notes" — not a bare "add" that names nothing.
|
|
544
|
+
*/
|
|
545
|
+
function blankWords(editable, fact) {
|
|
546
|
+
const shape = editable.shape;
|
|
547
|
+
if (shape.type === "date")
|
|
548
|
+
return shape.time ? "Pick a day and time" : "Pick a day";
|
|
549
|
+
if (shape.type === "choice" || (shape.type === "several" && shape.of.type === "choice"))
|
|
550
|
+
return "Choose…";
|
|
551
|
+
return `Add ${fact.toLowerCase()}`;
|
|
552
|
+
}
|
|
553
|
+
/* A yes or no: a switch with its word beside it, at least 24 pixels tall like every target here. */
|
|
554
|
+
const SWITCH = { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 8, minHeight: 24, minWidth: 24, color: "var(--graview-ink)" };
|
|
555
|
+
const TRACK = { position: "relative", display: "inline-block", width: 28, height: 16, borderRadius: 8, flex: "none", transition: "background 120ms" };
|
|
556
|
+
const KNOB = { position: "absolute", top: 2, left: 2, width: 12, height: 12, borderRadius: 6, background: "var(--graview-ground)", transition: "transform 120ms" };
|
|
557
|
+
/* A choice of a few: its options side by side, the chosen one filled — one hairline round them, no box per option. */
|
|
558
|
+
const SEGMENTS = { display: "inline-flex", flexWrap: "wrap", gap: 2, padding: 2, borderRadius: 8, border: "1px solid var(--graview-edge)", maxWidth: "100%" };
|
|
559
|
+
const SEGMENT = { all: "unset", cursor: "pointer", minHeight: 24, minWidth: 24, padding: "0 10px", display: "inline-flex", alignItems: "center", borderRadius: 6, fontSize: "0.875em", color: "var(--graview-ink-muted)" };
|
|
560
|
+
const SEGMENT_ON = { background: "var(--graview-accent)", color: "var(--graview-accent-ink, #fff)" };
|
|
561
|
+
/* A choice of many: the menu itself, as quiet as a value, open at a press. */
|
|
562
|
+
const MENU = { font: "inherit", fontSize: "inherit", color: "var(--graview-ink)", background: "transparent", border: 0, borderBottom: "1px dashed var(--graview-edge-bright)", borderRadius: 0, padding: "0 2px", minHeight: 24, maxWidth: "100%", cursor: "pointer" };
|
|
439
563
|
//# sourceMappingURL=editable.js.map
|