@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.
Files changed (136) hide show
  1. package/dist/app-bar.d.ts +114 -15
  2. package/dist/app-bar.d.ts.map +1 -1
  3. package/dist/app-bar.js +192 -130
  4. package/dist/app-bar.js.map +1 -1
  5. package/dist/app-menu.d.ts +9 -0
  6. package/dist/app-menu.d.ts.map +1 -0
  7. package/dist/app-menu.js +60 -0
  8. package/dist/app-menu.js.map +1 -0
  9. package/dist/bar-activity.d.ts +5 -9
  10. package/dist/bar-activity.d.ts.map +1 -1
  11. package/dist/bar-activity.js +24 -7
  12. package/dist/bar-activity.js.map +1 -1
  13. package/dist/bar-panes.d.ts +5 -5
  14. package/dist/bar-panes.d.ts.map +1 -1
  15. package/dist/bar-panes.js +9 -5
  16. package/dist/bar-panes.js.map +1 -1
  17. package/dist/bar-suggested.d.ts +9 -1
  18. package/dist/bar-suggested.d.ts.map +1 -1
  19. package/dist/bar-suggested.js +11 -17
  20. package/dist/bar-suggested.js.map +1 -1
  21. package/dist/better-bar.d.ts +77 -0
  22. package/dist/better-bar.d.ts.map +1 -0
  23. package/dist/better-bar.js +312 -0
  24. package/dist/better-bar.js.map +1 -0
  25. package/dist/better-panel.d.ts +55 -0
  26. package/dist/better-panel.d.ts.map +1 -0
  27. package/dist/better-panel.js +151 -0
  28. package/dist/better-panel.js.map +1 -0
  29. package/dist/editable.d.ts +8 -1
  30. package/dist/editable.d.ts.map +1 -1
  31. package/dist/editable.js +140 -16
  32. package/dist/editable.js.map +1 -1
  33. package/dist/first-look-door.d.ts +2 -2
  34. package/dist/first-look-door.js +2 -2
  35. package/dist/first-look.d.ts.map +1 -1
  36. package/dist/first-look.js +9 -7
  37. package/dist/first-look.js.map +1 -1
  38. package/dist/frame.d.ts +2 -2
  39. package/dist/frame.d.ts.map +1 -1
  40. package/dist/frame.js +1 -1
  41. package/dist/frame.js.map +1 -1
  42. package/dist/inbox-pane.d.ts +31 -0
  43. package/dist/inbox-pane.d.ts.map +1 -0
  44. package/dist/inbox-pane.js +89 -0
  45. package/dist/inbox-pane.js.map +1 -0
  46. package/dist/inbox.d.ts +17 -0
  47. package/dist/inbox.d.ts.map +1 -0
  48. package/dist/inbox.js +84 -0
  49. package/dist/inbox.js.map +1 -0
  50. package/dist/index.d.ts +4 -3
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +3 -2
  53. package/dist/index.js.map +1 -1
  54. package/dist/lens/calendar-drawing.js +7 -3
  55. package/dist/lens/calendar-drawing.js.map +1 -1
  56. package/dist/menu-suggested.d.ts +54 -0
  57. package/dist/menu-suggested.d.ts.map +1 -0
  58. package/dist/menu-suggested.js +140 -0
  59. package/dist/menu-suggested.js.map +1 -0
  60. package/dist/menu-told-door.js +1 -1
  61. package/dist/menu-told-door.js.map +1 -1
  62. package/dist/menu-told.d.ts +7 -0
  63. package/dist/menu-told.d.ts.map +1 -1
  64. package/dist/menu-told.js +24 -0
  65. package/dist/menu-told.js.map +1 -1
  66. package/dist/notify-sheet.js +2 -2
  67. package/dist/notify-sheet.js.map +1 -1
  68. package/dist/page-better.d.ts +27 -0
  69. package/dist/page-better.d.ts.map +1 -0
  70. package/dist/page-better.js +747 -0
  71. package/dist/page-better.js.map +1 -0
  72. package/dist/page-parts.d.ts +41 -0
  73. package/dist/page-parts.d.ts.map +1 -0
  74. package/dist/page-parts.js +101 -0
  75. package/dist/page-parts.js.map +1 -0
  76. package/dist/pages.d.ts +2 -3
  77. package/dist/pages.d.ts.map +1 -1
  78. package/dist/pages.js +2 -3
  79. package/dist/pages.js.map +1 -1
  80. package/dist/profile.d.ts +1 -10
  81. package/dist/profile.d.ts.map +1 -1
  82. package/dist/profile.js +2 -3
  83. package/dist/profile.js.map +1 -1
  84. package/dist/scene-bar.d.ts +1 -1
  85. package/dist/scene-bar.d.ts.map +1 -1
  86. package/dist/scene-bar.js +4 -7
  87. package/dist/scene-bar.js.map +1 -1
  88. package/dist/section-better.d.ts +66 -9
  89. package/dist/section-better.d.ts.map +1 -1
  90. package/dist/section-better.js +285 -136
  91. package/dist/section-better.js.map +1 -1
  92. package/dist/section-door.d.ts +7 -0
  93. package/dist/section-door.d.ts.map +1 -1
  94. package/dist/section-door.js +39 -5
  95. package/dist/section-door.js.map +1 -1
  96. package/dist/section-menu.d.ts +23 -9
  97. package/dist/section-menu.d.ts.map +1 -1
  98. package/dist/section-menu.js +176 -23
  99. package/dist/section-menu.js.map +1 -1
  100. package/dist/section-words.d.ts +8 -0
  101. package/dist/section-words.d.ts.map +1 -1
  102. package/dist/section-words.js +25 -0
  103. package/dist/section-words.js.map +1 -1
  104. package/dist/shell.d.ts +7 -1
  105. package/dist/shell.d.ts.map +1 -1
  106. package/dist/shell.js +4 -2
  107. package/dist/shell.js.map +1 -1
  108. package/dist/suggested.d.ts +21 -10
  109. package/dist/suggested.d.ts.map +1 -1
  110. package/dist/suggested.js +80 -66
  111. package/dist/suggested.js.map +1 -1
  112. package/dist/suggestion-sentence.d.ts +50 -0
  113. package/dist/suggestion-sentence.d.ts.map +1 -0
  114. package/dist/suggestion-sentence.js +119 -0
  115. package/dist/suggestion-sentence.js.map +1 -0
  116. package/dist/told-card.js +1 -1
  117. package/dist/told-card.js.map +1 -1
  118. package/dist/told-ui.d.ts +1 -1
  119. package/dist/told-ui.d.ts.map +1 -1
  120. package/dist/told-ui.js +1 -1
  121. package/dist/told-ui.js.map +1 -1
  122. package/dist/when-words.d.ts +21 -0
  123. package/dist/when-words.d.ts.map +1 -0
  124. package/dist/when-words.js +43 -0
  125. package/dist/when-words.js.map +1 -0
  126. package/dist/workbench/activity.d.ts +44 -0
  127. package/dist/workbench/activity.d.ts.map +1 -1
  128. package/dist/workbench/activity.js +74 -59
  129. package/dist/workbench/activity.js.map +1 -1
  130. package/dist/workbench/inspector.d.ts.map +1 -1
  131. package/dist/workbench/inspector.js +170 -31
  132. package/dist/workbench/inspector.js.map +1 -1
  133. package/dist/workbench/standing.d.ts.map +1 -1
  134. package/dist/workbench/standing.js +1 -1
  135. package/dist/workbench/standing.js.map +1 -1
  136. 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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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"editable.d.ts","sourceRoot":"","sources":["../src/editable.tsx"],"names":[],"mappings":"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"}
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, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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
- const named = said ?? `${fact.charAt(0).toUpperCase()}${fact.slice(1)}: ${value}`;
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 (_jsx("span", { "data-graview-field": field, "data-graview-readonly": "",
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 declares changes the ${words}`,
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: value }));
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 = (_jsx("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: () => {
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 "add", dim beside the values that are there.
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
- }, children: blank ? "add" : value }));
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, _jsx("span", { role: "status", "data-graview-refused": field, style: { marginLeft: 6, fontSize: "0.75rem", color: "var(--graview-ink-muted)" }, children: refused })] }));
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", { style: { display: "inline-flex", flexWrap: "wrap", gap: 4, maxWidth: "100%" }, onSubmit: (event) => {
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 declares changes the ${words}` }), ...(editable ? { onClick: () => setEditing(true) } : {}), style: { cursor: editable ? "text" : "default", minWidth: 0 }, children: drawn })) })] }));
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