@graview/primitives 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +96 -0
- package/README.md +25 -0
- package/dist/arrange-bar.d.ts +49 -0
- package/dist/arrange-bar.d.ts.map +1 -0
- package/dist/arrange-bar.js +264 -0
- package/dist/arrange-bar.js.map +1 -0
- package/dist/chat.d.ts +46 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +343 -0
- package/dist/chat.js.map +1 -0
- package/dist/companion.d.ts +58 -0
- package/dist/companion.d.ts.map +1 -0
- package/dist/companion.js +433 -0
- package/dist/companion.js.map +1 -0
- package/dist/connections.d.ts +23 -0
- package/dist/connections.d.ts.map +1 -0
- package/dist/connections.js +100 -0
- package/dist/connections.js.map +1 -0
- package/dist/default-views.d.ts +35 -0
- package/dist/default-views.d.ts.map +1 -0
- package/dist/default-views.js +605 -0
- package/dist/default-views.js.map +1 -0
- package/dist/editable.d.ts +71 -0
- package/dist/editable.d.ts.map +1 -0
- package/dist/editable.js +225 -0
- package/dist/editable.js.map +1 -0
- package/dist/figure.d.ts +30 -0
- package/dist/figure.d.ts.map +1 -0
- package/dist/figure.js +66 -0
- package/dist/figure.js.map +1 -0
- package/dist/find.d.ts +5 -0
- package/dist/find.d.ts.map +1 -0
- package/dist/find.js +252 -0
- package/dist/find.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +17 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +37 -0
- package/dist/installation.js.map +1 -0
- package/dist/ladder.d.ts +2 -0
- package/dist/ladder.d.ts.map +1 -0
- package/dist/ladder.js +53 -0
- package/dist/ladder.js.map +1 -0
- package/dist/lens/arranging.d.ts +41 -0
- package/dist/lens/arranging.d.ts.map +1 -0
- package/dist/lens/arranging.js +38 -0
- package/dist/lens/arranging.js.map +1 -0
- package/dist/lens/board.d.ts +146 -0
- package/dist/lens/board.d.ts.map +1 -0
- package/dist/lens/board.js +658 -0
- package/dist/lens/board.js.map +1 -0
- package/dist/lens/calendar-dates.d.ts +19 -0
- package/dist/lens/calendar-dates.d.ts.map +1 -0
- package/dist/lens/calendar-dates.js +55 -0
- package/dist/lens/calendar-dates.js.map +1 -0
- package/dist/lens/calendar-drawing.d.ts +59 -0
- package/dist/lens/calendar-drawing.d.ts.map +1 -0
- package/dist/lens/calendar-drawing.js +229 -0
- package/dist/lens/calendar-drawing.js.map +1 -0
- package/dist/lens/calendar-options.d.ts +107 -0
- package/dist/lens/calendar-options.d.ts.map +1 -0
- package/dist/lens/calendar-options.js +19 -0
- package/dist/lens/calendar-options.js.map +1 -0
- package/dist/lens/calendar-placing.d.ts +35 -0
- package/dist/lens/calendar-placing.d.ts.map +1 -0
- package/dist/lens/calendar-placing.js +113 -0
- package/dist/lens/calendar-placing.js.map +1 -0
- package/dist/lens/calendar-spans.d.ts +48 -0
- package/dist/lens/calendar-spans.d.ts.map +1 -0
- package/dist/lens/calendar-spans.js +146 -0
- package/dist/lens/calendar-spans.js.map +1 -0
- package/dist/lens/calendar-view.d.ts +34 -0
- package/dist/lens/calendar-view.d.ts.map +1 -0
- package/dist/lens/calendar-view.js +228 -0
- package/dist/lens/calendar-view.js.map +1 -0
- package/dist/lens/calendar.d.ts +43 -0
- package/dist/lens/calendar.d.ts.map +1 -0
- package/dist/lens/calendar.js +43 -0
- package/dist/lens/calendar.js.map +1 -0
- package/dist/lens/coverage.d.ts +183 -0
- package/dist/lens/coverage.d.ts.map +1 -0
- package/dist/lens/coverage.js +732 -0
- package/dist/lens/coverage.js.map +1 -0
- package/dist/lens/horizon.d.ts +14 -0
- package/dist/lens/horizon.d.ts.map +1 -0
- package/dist/lens/horizon.js +20 -0
- package/dist/lens/horizon.js.map +1 -0
- package/dist/lens/more.d.ts +16 -0
- package/dist/lens/more.d.ts.map +1 -0
- package/dist/lens/more.js +17 -0
- package/dist/lens/more.js.map +1 -0
- package/dist/lens/plan-lens.d.ts +17 -0
- package/dist/lens/plan-lens.d.ts.map +1 -0
- package/dist/lens/plan-lens.js +24 -0
- package/dist/lens/plan-lens.js.map +1 -0
- package/dist/lens/plan-state.d.ts +122 -0
- package/dist/lens/plan-state.d.ts.map +1 -0
- package/dist/lens/plan-state.js +152 -0
- package/dist/lens/plan-state.js.map +1 -0
- package/dist/lens/plan-view.d.ts +10 -0
- package/dist/lens/plan-view.d.ts.map +1 -0
- package/dist/lens/plan-view.js +576 -0
- package/dist/lens/plan-view.js.map +1 -0
- package/dist/lens/plan.d.ts +25 -0
- package/dist/lens/plan.d.ts.map +1 -0
- package/dist/lens/plan.js +25 -0
- package/dist/lens/plan.js.map +1 -0
- package/dist/lens/reach.d.ts +47 -0
- package/dist/lens/reach.d.ts.map +1 -0
- package/dist/lens/reach.js +67 -0
- package/dist/lens/reach.js.map +1 -0
- package/dist/lens/timeline.d.ts +137 -0
- package/dist/lens/timeline.d.ts.map +1 -0
- package/dist/lens/timeline.js +426 -0
- package/dist/lens/timeline.js.map +1 -0
- package/dist/markup.d.ts +23 -0
- package/dist/markup.d.ts.map +1 -0
- package/dist/markup.js +24 -0
- package/dist/markup.js.map +1 -0
- package/dist/places.d.ts +24 -0
- package/dist/places.d.ts.map +1 -0
- package/dist/places.js +227 -0
- package/dist/places.js.map +1 -0
- package/dist/popover.d.ts +28 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +59 -0
- package/dist/popover.js.map +1 -0
- package/dist/primitives/index.d.ts +214 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +381 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/profile.d.ts +65 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +233 -0
- package/dist/profile.js.map +1 -0
- package/dist/quick-relations.d.ts +16 -0
- package/dist/quick-relations.d.ts.map +1 -0
- package/dist/quick-relations.js +183 -0
- package/dist/quick-relations.js.map +1 -0
- package/dist/relation-key.d.ts +44 -0
- package/dist/relation-key.d.ts.map +1 -0
- package/dist/relation-key.js +196 -0
- package/dist/relation-key.js.map +1 -0
- package/dist/seat.d.ts +137 -0
- package/dist/seat.d.ts.map +1 -0
- package/dist/seat.js +162 -0
- package/dist/seat.js.map +1 -0
- package/dist/seats.d.ts +21 -0
- package/dist/seats.d.ts.map +1 -0
- package/dist/seats.js +62 -0
- package/dist/seats.js.map +1 -0
- package/dist/seeding.d.ts +150 -0
- package/dist/seeding.d.ts.map +1 -0
- package/dist/seeding.js +538 -0
- package/dist/seeding.js.map +1 -0
- package/dist/shell.d.ts +74 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +86 -0
- package/dist/shell.js.map +1 -0
- package/dist/theme.d.ts +50 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +1692 -0
- package/dist/theme.js.map +1 -0
- package/dist/wordmark.d.ts +15 -0
- package/dist/wordmark.d.ts.map +1 -0
- package/dist/wordmark.js +55 -0
- package/dist/wordmark.js.map +1 -0
- package/dist/workbench/activity.d.ts +75 -0
- package/dist/workbench/activity.d.ts.map +1 -0
- package/dist/workbench/activity.js +259 -0
- package/dist/workbench/activity.js.map +1 -0
- package/dist/workbench/agent-seat.d.ts +51 -0
- package/dist/workbench/agent-seat.d.ts.map +1 -0
- package/dist/workbench/agent-seat.js +112 -0
- package/dist/workbench/agent-seat.js.map +1 -0
- package/dist/workbench/answer-args.d.ts +31 -0
- package/dist/workbench/answer-args.d.ts.map +1 -0
- package/dist/workbench/answer-args.js +257 -0
- package/dist/workbench/answer-args.js.map +1 -0
- package/dist/workbench/back-out.d.ts +71 -0
- package/dist/workbench/back-out.d.ts.map +1 -0
- package/dist/workbench/back-out.js +238 -0
- package/dist/workbench/back-out.js.map +1 -0
- package/dist/workbench/following.d.ts +7 -0
- package/dist/workbench/following.d.ts.map +1 -0
- package/dist/workbench/following.js +26 -0
- package/dist/workbench/following.js.map +1 -0
- package/dist/workbench/index.d.ts +23 -0
- package/dist/workbench/index.d.ts.map +1 -0
- package/dist/workbench/index.js +23 -0
- package/dist/workbench/index.js.map +1 -0
- package/dist/workbench/inspector.d.ts +27 -0
- package/dist/workbench/inspector.d.ts.map +1 -0
- package/dist/workbench/inspector.js +745 -0
- package/dist/workbench/inspector.js.map +1 -0
- package/dist/workbench/standing.d.ts +16 -0
- package/dist/workbench/standing.d.ts.map +1 -0
- package/dist/workbench/standing.js +102 -0
- package/dist/workbench/standing.js.map +1 -0
- package/dist/workbench/trail.d.ts +35 -0
- package/dist/workbench/trail.d.ts.map +1 -0
- package/dist/workbench/trail.js +150 -0
- package/dist/workbench/trail.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-seat.js","sourceRoot":"","sources":["../../src/workbench/agent-seat.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,GAIT,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAqCrD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAsB,EAC7C,KAAK,EACL,SAAS,EACT,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,MAAM,EACN,MAAM,EACN,GAAG,GACe;IAClB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,EAAK,CAAC;IACxF;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,CAAC,GAAG,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAC3B,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CACH,iBAAiB,CAAC,KAAK,EAAE;QACvB,iFAAiF;QACjF,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,GAAG;YACP,OAAO;YACP,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD;QACD,kEAAkE;QAClE,+DAA+D;QAC/D,iEAAiE;QACjE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC;QACpC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE;KAC7B,CAAC,EACJ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CACxC,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,qEAAqE;IACrE,sDAAsD;IACtD,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAE/C,MAAM,SAAS,GACb,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC;IAE1C;;;;OAIG;IACH,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClH,MAAM,GAAG,GAAG,CAAC,SAAS;QACpB,CAAC,CAAC,mCACE,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE;YACpB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO;YACzB,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,yBACxF,mCAAmC;QACrC,CAAC,CAAC,OAAO;YACP,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,+GAA+G,CAAC;IAEnJ;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAE,KAAK,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,OAAO,EAAE,KAA6C,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/I,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/F,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE1D;;;;;;;;;OASG;IACH,OAAO,CACL,gBAAM,KAAK,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,aACrF,iBACE,IAAI,EAAC,QAAQ,iBACA,MAAM,0BACG,SAAS,IAAI,SAAS,EAC5C,QAAQ,EAAE,GAAG,EACb,KAAK,EAAE,OAAO,IAAI,GAAG,EACrB,OAAO,EAAE,GAAG,EAAE;oBACZ,OAAO,CAAC,IAAI,CAAC,CAAC;oBACd,UAAU,CAAC,IAAI,CAAC,CAAC;oBACjB,KAAK,CAAC,KAAK,IAAI,EAAE;wBACf,IAAI,CAAC;4BACH,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;wBAC5B,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf;;;;+BAIG;4BACH,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;wBACrE,CAAC;gCAAS,CAAC;4BACT,OAAO,CAAC,KAAK,CAAC,CAAC;wBACjB,CAAC;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,CAAC,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,YAE9B,IAAI,CAAC,CAAC,CAAC,CACN,SAAS,CACV,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CACf,sBAAI,KAAK,CAAC,KAAK,CAAC,GAAK,CACtB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CACZ,IAAI,CACL,CAAC,CAAC,CAAC,CACF,KAAK,CAAC,KAAK,CAAC,CACb,GACM,EACN,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,CACvB,8BACe,GAAG,MAAM,MAAM,EAC5B,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,0BAA0B,EAAE,QAAQ,EAAE,GAAG,EAAE,YAElG,OAAO,IAAI,GAAG,GACV,CACR,CAAC,CAAC,CAAC,IAAI,IACH,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type AnySchema, type Store } from "@graview/core";
|
|
2
|
+
import type { Affordance, OpenParameter } from "@graview/tools";
|
|
3
|
+
/**
|
|
4
|
+
* The controls for one action's unanswered arguments, walked in order.
|
|
5
|
+
*
|
|
6
|
+
* One at a time and in sequence, because an action can need several: drafting
|
|
7
|
+
* work needs both what it is and how big it is, and asking for the first
|
|
8
|
+
* while ignoring the second would produce a deliverable with an invented
|
|
9
|
+
* size. Each argument draws the control its declared shape asks for — a
|
|
10
|
+
* picker when it names a node, a date field when it is a date, an enum's own
|
|
11
|
+
* options when it is a choice.
|
|
12
|
+
*/
|
|
13
|
+
export declare function AnswerArgs({ affordance, onApply, onCancel, }: {
|
|
14
|
+
readonly affordance: Affordance;
|
|
15
|
+
onApply: (args: Record<string, unknown>) => void;
|
|
16
|
+
onCancel: () => void;
|
|
17
|
+
}): import("react").JSX.Element | null;
|
|
18
|
+
/** How many choices an ask shows at once. Past this it offers a filter. */
|
|
19
|
+
export declare const SHOWN = 10;
|
|
20
|
+
/**
|
|
21
|
+
* How one possible answer reads.
|
|
22
|
+
*
|
|
23
|
+
* A node reference reads as the node's own label; anything else reads as
|
|
24
|
+
* itself. `nameOf` would look "yes" up as a node id, fail to find one, and
|
|
25
|
+
* show the id — which is right for nodes and nonsense for a boolean or an
|
|
26
|
+
* enum value.
|
|
27
|
+
*/
|
|
28
|
+
export declare function said(store: Store<AnySchema>, shape: NonNullable<OpenParameter["shape"]>, choice: string): string;
|
|
29
|
+
/** A node's own label where there is one, so a picker never offers raw ids. */
|
|
30
|
+
export declare function nameOf(store: Store<AnySchema>, id: string): string;
|
|
31
|
+
//# sourceMappingURL=answer-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer-args.d.ts","sourceRoot":"","sources":["../../src/workbench/answer-args.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAItG,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIhE;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,OAAO,EACP,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,sCAwSA;AAID,2EAA2E;AAC3E,eAAO,MAAM,KAAK,KAAK,CAAC;AAoBxB;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,EACvB,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAC1C,MAAM,EAAE,MAAM,GACb,MAAM,CAIR;AAED,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAsBlE"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { humaniseField, labelOf, nounOf, tellApart } from "@graview/core";
|
|
3
|
+
import { relationWords } from "../relation-key.js";
|
|
4
|
+
import { edgeOfSelection, kindsOf } from "@graview/layout";
|
|
5
|
+
import { useGraview } from "@graview/react";
|
|
6
|
+
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
7
|
+
/**
|
|
8
|
+
* The controls for one action's unanswered arguments, walked in order.
|
|
9
|
+
*
|
|
10
|
+
* One at a time and in sequence, because an action can need several: drafting
|
|
11
|
+
* work needs both what it is and how big it is, and asking for the first
|
|
12
|
+
* while ignoring the second would produce a deliverable with an invented
|
|
13
|
+
* size. Each argument draws the control its declared shape asks for — a
|
|
14
|
+
* picker when it names a node, a date field when it is a date, an enum's own
|
|
15
|
+
* options when it is a choice.
|
|
16
|
+
*/
|
|
17
|
+
export function AnswerArgs({ affordance, onApply, onCancel, }) {
|
|
18
|
+
const { store } = useGraview();
|
|
19
|
+
const [answers, setAnswers] = useState({});
|
|
20
|
+
const [draft, setDraft] = useState("");
|
|
21
|
+
/** What has been chosen so far, for an argument that takes several. */
|
|
22
|
+
const [picked, setPicked] = useState(NOTHING_PICKED);
|
|
23
|
+
// Stable across the walk's steps, so the group's label never dangles.
|
|
24
|
+
const promptId = useId();
|
|
25
|
+
const asked = useRef(null);
|
|
26
|
+
const remaining = affordance.open.filter((parameter) => !(parameter.name in answers));
|
|
27
|
+
const parameter = remaining[0];
|
|
28
|
+
useEffect(() => setDraft(""), [parameter?.name]);
|
|
29
|
+
/*
|
|
30
|
+
* AND IT IS ON THE SCREEN.
|
|
31
|
+
*
|
|
32
|
+
* The pane scrolls inside itself, and an ask opened under a list of acts
|
|
33
|
+
* taller than the pane lands below its fold: on a phone the field, the
|
|
34
|
+
* Apply and the Skip were all off the bottom of the window, so pressing
|
|
35
|
+
* an act looked like pressing a button that did nothing. The ask is the
|
|
36
|
+
* thing that just happened, so it is what the pane shows. `nearest`
|
|
37
|
+
* moves the pane the least amount that works and leaves everything
|
|
38
|
+
* already visible where it is.
|
|
39
|
+
*/
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
// Optional: jsdom has no scrolling at all, and a pane that cannot
|
|
42
|
+
// scroll needs none.
|
|
43
|
+
asked.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
44
|
+
}, [parameter?.name]);
|
|
45
|
+
if (!parameter)
|
|
46
|
+
return null;
|
|
47
|
+
/*
|
|
48
|
+
* An OPTIONAL argument may be passed over. A skipped one is answered
|
|
49
|
+
* `undefined` here so the walk moves on, and left out of what is applied,
|
|
50
|
+
* so the mutation sees only what was actually said. Skipping every one
|
|
51
|
+
* of them is allowed: the mutation's own refusal then says what it
|
|
52
|
+
* needed, on the button, which is the honest answer to an empty change.
|
|
53
|
+
*/
|
|
54
|
+
const answer = (value) => {
|
|
55
|
+
const next = { ...answers, [parameter.name]: value };
|
|
56
|
+
const outstanding = affordance.open.filter((other) => !(other.name in next));
|
|
57
|
+
if (outstanding.length === 0) {
|
|
58
|
+
onApply(Object.fromEntries(Object.entries(next).filter(([, given]) => given !== undefined)));
|
|
59
|
+
}
|
|
60
|
+
else
|
|
61
|
+
setAnswers(next);
|
|
62
|
+
};
|
|
63
|
+
const skip = parameter.optional ? (_jsx("button", { type: "button", onClick: () => answer(undefined), style: { fontSize: "0.8125rem" }, children: "Skip" })) : null;
|
|
64
|
+
const shape = parameter.shape ?? { type: "unknown" };
|
|
65
|
+
const choices = choicesFor(parameter, shape);
|
|
66
|
+
/*
|
|
67
|
+
* A PICKER THAT DROPS CHOICES MAKES THE ACT IMPOSSIBLE, AND SAYS NOTHING.
|
|
68
|
+
*
|
|
69
|
+
* This listed the first ten and stopped. A property with twenty-two
|
|
70
|
+
* practices on it offered ten of them under "Name something that helps",
|
|
71
|
+
* and the other twelve could not be chosen at all — not behind a control,
|
|
72
|
+
* not summarised as "+12", simply absent, with the panel looking exactly
|
|
73
|
+
* as it would if ten were all there were.
|
|
74
|
+
*
|
|
75
|
+
* Ten is still the right number to SHOW; a wall of forty chips is its own
|
|
76
|
+
* kind of unusable. What was missing is the way through — a filter, and a
|
|
77
|
+
* count of what is not on screen. Neither is a new idea here: the strip
|
|
78
|
+
* has had both since it was written. It just never reached the ask.
|
|
79
|
+
*/
|
|
80
|
+
const [among, setAmong] = useState("");
|
|
81
|
+
/* Two candidates with one name are told apart by what differs (see `tellApart`). */
|
|
82
|
+
const apart = useMemo(() => {
|
|
83
|
+
const nodes = choices.map((choice) => store.graph.getNode(choice)).filter((node) => node !== undefined);
|
|
84
|
+
return tellApart(nodes, (kind) => store.schema.tryDefinition(kind));
|
|
85
|
+
}, [choices, store]);
|
|
86
|
+
const say = (choice) => {
|
|
87
|
+
const words = said(store, shape, choice);
|
|
88
|
+
const told = apart.get(choice);
|
|
89
|
+
return told ? `${words} · ${told}` : words;
|
|
90
|
+
};
|
|
91
|
+
const matching = useMemo(() => {
|
|
92
|
+
const term = among.trim().toLowerCase();
|
|
93
|
+
if (term === "")
|
|
94
|
+
return choices;
|
|
95
|
+
return choices.filter((choice) => say(choice).toLowerCase().includes(term));
|
|
96
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
97
|
+
}, [choices, among, store, shape, apart]);
|
|
98
|
+
/*
|
|
99
|
+
* AN ARGUMENT THAT TAKES A LIST IS ANSWERED WITH A LIST.
|
|
100
|
+
*
|
|
101
|
+
* "Invite somebody as coordinator and gardener" is one act with several
|
|
102
|
+
* roles in one argument. Answered one press at a time it would be one
|
|
103
|
+
* role, silently — so the presses TOGGLE and a separate one settles the
|
|
104
|
+
* question. Nothing else about the walk changes: it is still one
|
|
105
|
+
* parameter, still skippable when optional, still applied when the last
|
|
106
|
+
* outstanding one is answered.
|
|
107
|
+
*/
|
|
108
|
+
const several = shape.type === "several";
|
|
109
|
+
/*
|
|
110
|
+
* THE ASK SAYS WHAT IT IS ASKING, IN WORDS.
|
|
111
|
+
*
|
|
112
|
+
* The text branch has said so since W-004 — the input's own label and
|
|
113
|
+
* placeholder are the question. The CHOICES branch said nothing at all: an
|
|
114
|
+
* act with one node reference to fill put two bare buttons on the strip
|
|
115
|
+
* ("Ana", "Bo") under no heading, so what was being asked was a guess for
|
|
116
|
+
* anyone looking and unsaid entirely for anyone listening. And where a
|
|
117
|
+
* step counter did name the parameter it used the declaration's
|
|
118
|
+
* IDENTIFIER — "dependsOn · 1 of 2" — which is the same bug W-004 fixed
|
|
119
|
+
* one element lower down.
|
|
120
|
+
*/
|
|
121
|
+
/*
|
|
122
|
+
* A NODE PICKER IS NAMED BY WHAT IT PICKS — "Item", not "Id".
|
|
123
|
+
*
|
|
124
|
+
* The routed face has said so since it was written ("the argument's name
|
|
125
|
+
* is an implementation detail, and the kinds it accepts are the
|
|
126
|
+
* declaration's own word for the thing" — `formFields` in
|
|
127
|
+
* `@graview/pages`), and the strip asked with the argument's identifier.
|
|
128
|
+
* Every scaffolded app names its subject argument `id`, as the skills'
|
|
129
|
+
* own examples do, so an act offered from the FAR END of its tie — "Hand
|
|
130
|
+
* one back", standing on the person — put the word "Id" over a list of
|
|
131
|
+
* items.
|
|
132
|
+
*/
|
|
133
|
+
const asking = parameter.kinds && parameter.kinds.length > 0 && !parameter.kinds.includes("*")
|
|
134
|
+
? parameter.kinds.map((kind) => humaniseField(nounOf(store.schema.tryDefinition(kind), kind))).join(" or ")
|
|
135
|
+
: humaniseField(parameter.name);
|
|
136
|
+
const step = affordance.open.length > 1
|
|
137
|
+
? `${asking} · ${affordance.open.length - remaining.length + 1} of ${affordance.open.length}`
|
|
138
|
+
: asking;
|
|
139
|
+
return (_jsxs("div", { ref: asked, "data-graview-asking": affordance.id, style: {
|
|
140
|
+
display: "grid",
|
|
141
|
+
/*
|
|
142
|
+
* THE ASK FITS THE PANE IT OPENS IN.
|
|
143
|
+
*
|
|
144
|
+
* An auto track takes the min-content width of what is in it, and a
|
|
145
|
+
* text input's is its own default size — so a field, an Apply and a
|
|
146
|
+
* Skip came to 257 inside a 236-wide rail, and the Skip was drawn
|
|
147
|
+
* past the pane's edge, half of it painted and none of it reachable
|
|
148
|
+
* without scrolling a pane that shows no scrollbar. `minmax(0, 1fr)`
|
|
149
|
+
* says the track may not be wider than the pane; the input already
|
|
150
|
+
* carries `minWidth: 0`, so it is the thing that gives.
|
|
151
|
+
*/
|
|
152
|
+
gridTemplateColumns: "minmax(0, 1fr)",
|
|
153
|
+
gap: 4,
|
|
154
|
+
padding: "5px 0 2px",
|
|
155
|
+
}, children: [affordance.open.length > 1 || choices.length > 0 ? (_jsx("span", { id: promptId, style: { fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: step })) : null, choices.length > SHOWN ? (_jsx("input", { type: "search", value: among, onChange: (event) => setAmong(event.target.value), placeholder: `Filter ${choices.length}…`, "aria-label": `Filter ${asking}`, "data-testid": "ask-filter", style: { font: "inherit", fontSize: "0.8125rem", minWidth: 0, padding: "3px 7px" } })) : null, choices.length > 0 ? (_jsxs("div", { role: "group", "aria-labelledby": promptId, style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: [matching.slice(0, SHOWN).map((choice) => {
|
|
156
|
+
const held = picked.includes(choice);
|
|
157
|
+
return (_jsx("button", { type: "button", "aria-label": `${asking}: ${say(choice)}`, ...(several ? { "aria-pressed": held } : {}), style: {
|
|
158
|
+
padding: "3px 9px",
|
|
159
|
+
fontSize: "0.8125rem",
|
|
160
|
+
...(held
|
|
161
|
+
? { borderColor: "var(--graview-accent)", color: "var(--graview-accent)" }
|
|
162
|
+
: {}),
|
|
163
|
+
}, onClick: () => several
|
|
164
|
+
? setPicked((current) => current.includes(choice)
|
|
165
|
+
? current.filter((other) => other !== choice)
|
|
166
|
+
: [...current, choice])
|
|
167
|
+
: answer(shape.type === "boolean" ? choice === "yes" : choice), children: say(choice) }, choice));
|
|
168
|
+
}), matching.length > SHOWN ? (_jsxs("span", { "data-testid": "ask-more", style: { alignSelf: "center", fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: [matching.length - SHOWN, " more \u2014 type to narrow"] })) : null, matching.length === 0 ? (_jsxs("span", { "data-testid": "ask-none", style: { alignSelf: "center", fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: ["None of the ", choices.length, " match that."] })) : null, several ? (_jsx("button", { type: "button", disabled: picked.length === 0, style: { fontSize: "0.8125rem" }, onClick: () => {
|
|
169
|
+
const chosen = picked;
|
|
170
|
+
setPicked(NOTHING_PICKED);
|
|
171
|
+
answer(chosen);
|
|
172
|
+
}, children: remaining.length > 1 ? "Next" : "Apply" })) : null, skip] })) : (_jsxs("form", {
|
|
173
|
+
// And where even a shrunk field would leave no room to type, the
|
|
174
|
+
// buttons drop to a line of their own rather than squeezing it to
|
|
175
|
+
// nothing.
|
|
176
|
+
style: { display: "flex", flexWrap: "wrap", gap: 4 }, onSubmit: (event) => {
|
|
177
|
+
event.preventDefault();
|
|
178
|
+
if (draft.trim().length === 0)
|
|
179
|
+
return;
|
|
180
|
+
answer(shape.type === "number" ? Number(draft) : draft);
|
|
181
|
+
}, children: [_jsx("input", { autoFocus: true, type: shape.type === "date" ? (shape.time ? "datetime-local" : "date") : shape.type === "number" ? "number" : "text", "aria-label": humaniseField(parameter.name), placeholder: humaniseField(parameter.name), value: draft, ...(shape.type === "number" && shape.min !== undefined ? { min: shape.min } : {}), ...(shape.type === "number" && shape.max !== undefined ? { max: shape.max } : {}), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
|
|
182
|
+
if (event.key === "Escape")
|
|
183
|
+
onCancel();
|
|
184
|
+
}, style: {
|
|
185
|
+
flex: 1,
|
|
186
|
+
minWidth: 0,
|
|
187
|
+
font: "inherit",
|
|
188
|
+
fontSize: "0.875rem",
|
|
189
|
+
padding: "5px 8px",
|
|
190
|
+
borderRadius: 7,
|
|
191
|
+
border: "1px solid var(--graview-edge)",
|
|
192
|
+
background: "var(--graview-panel)",
|
|
193
|
+
color: "var(--graview-ink)",
|
|
194
|
+
} }), _jsx("button", { type: "submit", disabled: draft.trim().length === 0, style: { fontSize: "0.8125rem" }, children: remaining.length > 1 ? "Next" : "Apply" }), skip] }))] }));
|
|
195
|
+
}
|
|
196
|
+
const NOTHING_PICKED = [];
|
|
197
|
+
/** How many choices an ask shows at once. Past this it offers a filter. */
|
|
198
|
+
export const SHOWN = 10;
|
|
199
|
+
function choicesFor(parameter, shape) {
|
|
200
|
+
if (parameter.candidates && parameter.candidates.length > 0)
|
|
201
|
+
return parameter.candidates;
|
|
202
|
+
if (shape.type === "choice")
|
|
203
|
+
return shape.options;
|
|
204
|
+
// SEVERAL OF A CHOICE is the same list of buttons; what differs is that
|
|
205
|
+
// pressing one adds it rather than settling the question.
|
|
206
|
+
if (shape.type === "several" && shape.of.type === "choice")
|
|
207
|
+
return shape.of.options;
|
|
208
|
+
// Yes or no is a choice of two, and reads better as two buttons than as
|
|
209
|
+
// a text field somebody has to know to type "true" into.
|
|
210
|
+
if (shape.type === "boolean")
|
|
211
|
+
return YES_NO;
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
/** The two answers to a boolean, in the words a person would use. */
|
|
215
|
+
const YES_NO = ["yes", "no"];
|
|
216
|
+
/**
|
|
217
|
+
* How one possible answer reads.
|
|
218
|
+
*
|
|
219
|
+
* A node reference reads as the node's own label; anything else reads as
|
|
220
|
+
* itself. `nameOf` would look "yes" up as a node id, fail to find one, and
|
|
221
|
+
* show the id — which is right for nodes and nonsense for a boolean or an
|
|
222
|
+
* enum value.
|
|
223
|
+
*/
|
|
224
|
+
export function said(store, shape, choice) {
|
|
225
|
+
if (shape.type === "boolean" || shape.type === "choice")
|
|
226
|
+
return choice;
|
|
227
|
+
if (shape.type === "several" && shape.of.type === "choice")
|
|
228
|
+
return choice;
|
|
229
|
+
return nameOf(store, choice);
|
|
230
|
+
}
|
|
231
|
+
/** A node's own label where there is one, so a picker never offers raw ids. */
|
|
232
|
+
export function nameOf(store, id) {
|
|
233
|
+
/*
|
|
234
|
+
* A selected KIND CARD names its kind, in the plural the declaration
|
|
235
|
+
* already carries — "Gardeners", never "kind:gardener". In an empty app
|
|
236
|
+
* the kind card is the first thing anyone selects, so the raw id here was
|
|
237
|
+
* the first string the interface ever showed them.
|
|
238
|
+
*/
|
|
239
|
+
const edge = edgeOfSelection(id);
|
|
240
|
+
// A relation by its words ("Where they work"), never its name ("Works at").
|
|
241
|
+
if (edge)
|
|
242
|
+
return relationWords(store.schema, edge.kind).words;
|
|
243
|
+
const kinds = kindsOf(id);
|
|
244
|
+
if (kinds.length > 0) {
|
|
245
|
+
return kinds
|
|
246
|
+
.map((kind) => {
|
|
247
|
+
const definition = store.schema.tryDefinition(kind);
|
|
248
|
+
return definition?.plural ?? `${kind}s`;
|
|
249
|
+
})
|
|
250
|
+
.join(" + ");
|
|
251
|
+
}
|
|
252
|
+
const node = store.graph.getNode(id);
|
|
253
|
+
if (!node)
|
|
254
|
+
return id;
|
|
255
|
+
return labelOf(store.schema.tryDefinition(node.kind), node);
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=answer-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer-args.js","sourceRoot":"","sources":["../../src/workbench/answer-args.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type ViewState } from "@graview/layout";
|
|
2
|
+
/**
|
|
3
|
+
* WHERE THE KEYBOARD GOES WHEN ESCAPE TAKES AWAY WHAT IT STOOD ON.
|
|
4
|
+
*
|
|
5
|
+
* Backing out of a record removes its card; the keyboard was on the card, or
|
|
6
|
+
* on the title renamed in it a moment ago, and fell to `<body>`. Chromium
|
|
7
|
+
* then tabs on from wherever the card was, into the zoom buttons, and WebKit
|
|
8
|
+
* from somewhere else again. The honest place is the card that still draws
|
|
9
|
+
* what was left — the district holding its chip — and failing that any card
|
|
10
|
+
* in the scene, so the next arrow or Enter still means the picture.
|
|
11
|
+
*
|
|
12
|
+
* Asked for a while rather than once, because a card leaving on a rise may
|
|
13
|
+
* fade out before it is removed; and only while the keyboard is still on
|
|
14
|
+
* nothing, so a person who moved it in the meantime keeps where they went.
|
|
15
|
+
*/
|
|
16
|
+
export declare function landTheKeyboard(stoodOn: HTMLElement, left: string | null, tries?: number): void;
|
|
17
|
+
/**
|
|
18
|
+
* Escape backs out one level: leave the full page, then the Graview, then
|
|
19
|
+
* drop the selection, then the raised relation, then the focus. A spatial
|
|
20
|
+
* interface has to have a way out that does not require finding the right
|
|
21
|
+
* small × in a trail.
|
|
22
|
+
*
|
|
23
|
+
* THE OVERVIEW IS ONLY A RUNG WHEN IT IS SOMETHING YOU CLIMBED TO. An app
|
|
24
|
+
* that OPENS from altitude — which is what `graview create` writes, and what
|
|
25
|
+
* every app with no in-stack default does — is already home up there, and
|
|
26
|
+
* leaving it would be going further IN. It is also, until this was fixed, the
|
|
27
|
+
* state in which Escape did nothing at all: the provider lands a focusless
|
|
28
|
+
* descent back on the overview (deliberately, so the key is never a void),
|
|
29
|
+
* which means the rung neither moved nor fell through, and every rung below
|
|
30
|
+
* it — the selection, the moves, the raised relation — was unreachable from
|
|
31
|
+
* the first screen of every scaffolded app.
|
|
32
|
+
*/
|
|
33
|
+
export declare function BackOut({ home }: {
|
|
34
|
+
readonly home: string | null;
|
|
35
|
+
}): null;
|
|
36
|
+
/**
|
|
37
|
+
* The way out to the Graview, and back — one control, two directions.
|
|
38
|
+
*
|
|
39
|
+
* The framework's own name for the view of the whole thing, which is the
|
|
40
|
+
* right name: everything else here is a lens over part of the graph, and this
|
|
41
|
+
* is the graph. It is a TOGGLE and presents as one: labelled "Graview" from
|
|
42
|
+
* the ground (the place it takes you) and "Focus" from altitude (the way back
|
|
43
|
+
* down), with the pressed state saying the same thing to a screen reader.
|
|
44
|
+
*
|
|
45
|
+
* THE MARK MORPHS. The scene's own rising is a morph rather than a cut — the
|
|
46
|
+
* grid dissolves into the iso lattice, the districts grow out of their cards,
|
|
47
|
+
* all riding one registered number. The control sits beside the scene rather
|
|
48
|
+
* than inside it, so it carries its OWN copy of that number, transitioned on
|
|
49
|
+
* the same 640ms curve (`.graview-altitude-control` in the theme): the three
|
|
50
|
+
* kinds on their ring gather into one node inside one ring as the scene
|
|
51
|
+
* rises, and open back out as it lands. Where an engine cannot register the
|
|
52
|
+
* property the scene cuts, and so does the mark — the same mechanism, so they
|
|
53
|
+
* cannot disagree.
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* Where "Focus" lands from altitude when nothing is focused.
|
|
57
|
+
*
|
|
58
|
+
* An app that opens from the city has no in-stack default, and the provider
|
|
59
|
+
* lands a focusless descent back on the overview — which made the control a
|
|
60
|
+
* button that did nothing, in every such app. Descending has to go
|
|
61
|
+
* SOMEWHERE: into the district that is selected, or the first one declared.
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* WHERE "FOCUS" LANDS FROM ALTITUDE: the drive-in that is focused, else the
|
|
65
|
+
* selected kind's, else the first kind that has a drive-in — a kind with a
|
|
66
|
+
* picture of its own is a better place to walk up to than the first kind
|
|
67
|
+
* in the declaration — else the first kind at all.
|
|
68
|
+
*/
|
|
69
|
+
export declare function descentTarget(view: ViewState, kinds: readonly string[], driveIns?: readonly string[]): string | null;
|
|
70
|
+
export declare function OverviewButton(): import("react").JSX.Element;
|
|
71
|
+
//# sourceMappingURL=back-out.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"back-out.d.ts","sourceRoot":"","sources":["../../src/workbench/back-out.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EAEf,MAAM,iBAAiB,CAAC;AAIzB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,SAAK,GAAG,IAAI,CAmB3F;AAGD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,QAgEjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH;;;;;;;GAOG;AACH;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,GAAG,IAAI,CAKxH;AAED,wBAAgB,cAAc,gCAoH7B"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { aggregateId, kindOfCard, withFocus, withoutMoves, withOverview, withoutSearch, kindsOfAggregate, } from "@graview/layout";
|
|
3
|
+
import { useGraview, useJackIn, useNavigation, useSelection } from "@graview/react";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* WHERE THE KEYBOARD GOES WHEN ESCAPE TAKES AWAY WHAT IT STOOD ON.
|
|
7
|
+
*
|
|
8
|
+
* Backing out of a record removes its card; the keyboard was on the card, or
|
|
9
|
+
* on the title renamed in it a moment ago, and fell to `<body>`. Chromium
|
|
10
|
+
* then tabs on from wherever the card was, into the zoom buttons, and WebKit
|
|
11
|
+
* from somewhere else again. The honest place is the card that still draws
|
|
12
|
+
* what was left — the district holding its chip — and failing that any card
|
|
13
|
+
* in the scene, so the next arrow or Enter still means the picture.
|
|
14
|
+
*
|
|
15
|
+
* Asked for a while rather than once, because a card leaving on a rise may
|
|
16
|
+
* fade out before it is removed; and only while the keyboard is still on
|
|
17
|
+
* nothing, so a person who moved it in the meantime keeps where they went.
|
|
18
|
+
*/
|
|
19
|
+
export function landTheKeyboard(stoodOn, left, tries = 40) {
|
|
20
|
+
const attempt = (remaining) => {
|
|
21
|
+
const active = document.activeElement;
|
|
22
|
+
const onNothing = active === null || active === document.body || active === stoodOn;
|
|
23
|
+
if (!onNothing)
|
|
24
|
+
return;
|
|
25
|
+
if (stoodOn.isConnected) {
|
|
26
|
+
if (remaining > 0)
|
|
27
|
+
setTimeout(() => attempt(remaining - 1), 25);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const escaped = left === null ? null : left.replace(/["\\]/g, "\\$&");
|
|
31
|
+
const target = (escaped === null
|
|
32
|
+
? null
|
|
33
|
+
: (document.querySelector(`[data-graview-view="${escaped}"]`) ??
|
|
34
|
+
document.querySelector(`[data-graview-pick="${escaped}"]`)?.closest("[data-graview-view]"))) ??
|
|
35
|
+
document.querySelector("[data-graview-view][tabindex]");
|
|
36
|
+
target?.focus({ preventScroll: true });
|
|
37
|
+
};
|
|
38
|
+
attempt(tries);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Escape backs out one level: leave the full page, then the Graview, then
|
|
42
|
+
* drop the selection, then the raised relation, then the focus. A spatial
|
|
43
|
+
* interface has to have a way out that does not require finding the right
|
|
44
|
+
* small × in a trail.
|
|
45
|
+
*
|
|
46
|
+
* THE OVERVIEW IS ONLY A RUNG WHEN IT IS SOMETHING YOU CLIMBED TO. An app
|
|
47
|
+
* that OPENS from altitude — which is what `graview create` writes, and what
|
|
48
|
+
* every app with no in-stack default does — is already home up there, and
|
|
49
|
+
* leaving it would be going further IN. It is also, until this was fixed, the
|
|
50
|
+
* state in which Escape did nothing at all: the provider lands a focusless
|
|
51
|
+
* descent back on the overview (deliberately, so the key is never a void),
|
|
52
|
+
* which means the rung neither moved nor fell through, and every rung below
|
|
53
|
+
* it — the selection, the moves, the raised relation — was unreachable from
|
|
54
|
+
* the first screen of every scaffolded app.
|
|
55
|
+
*/
|
|
56
|
+
export function BackOut({ home }) {
|
|
57
|
+
const { view, focus, show, go } = useNavigation();
|
|
58
|
+
const { homeView } = useGraview();
|
|
59
|
+
const { selection, clear } = useSelection();
|
|
60
|
+
const { isJackedIn, exit } = useJackIn();
|
|
61
|
+
// Up here on purpose, with somewhere below to land: only then is rising
|
|
62
|
+
// something Escape can undo.
|
|
63
|
+
const overview = (view.overview ?? false) && homeView.overview !== true;
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const onKey = (event) => {
|
|
66
|
+
if (event.key !== "Escape")
|
|
67
|
+
return;
|
|
68
|
+
// Never steal Escape from a field someone is typing in.
|
|
69
|
+
const active = document.activeElement;
|
|
70
|
+
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement)
|
|
71
|
+
return;
|
|
72
|
+
/*
|
|
73
|
+
* A POPOVER IS THE OUTERMOST RUNG, and it climbs down by itself.
|
|
74
|
+
*
|
|
75
|
+
* The activity rail, the problems list and the chat each close on
|
|
76
|
+
* Escape with a listener of their own — and this one ran too, so one
|
|
77
|
+
* press closed the rail AND dropped the selection under it (or, on
|
|
78
|
+
* the ground, backed out of the focus). Whatever is open over the
|
|
79
|
+
* scene owns the press; the ladder takes the next one.
|
|
80
|
+
*
|
|
81
|
+
* Asked in the CAPTURE phase, because the popover's own listener sits
|
|
82
|
+
* on the document, runs first in the bubble, and React commits its
|
|
83
|
+
* closing in the microtask between listeners — by the time a bubble
|
|
84
|
+
* listener on the window looked, the popover was already gone.
|
|
85
|
+
*/
|
|
86
|
+
// A pane kept in the tree but hidden — the profile, shut — is not open over anything.
|
|
87
|
+
if (document.querySelector("[data-graview-overlay]:not([hidden])"))
|
|
88
|
+
return;
|
|
89
|
+
// The keyboard, if it is on the picture: the rung may take its card away.
|
|
90
|
+
const stoodOn = active instanceof HTMLElement && active.closest("[data-graview-view]") !== null ? active : null;
|
|
91
|
+
if (stoodOn)
|
|
92
|
+
landTheKeyboard(stoodOn, view.focusId ?? null);
|
|
93
|
+
/*
|
|
94
|
+
* Outermost first, and the full page is the outermost thing there is.
|
|
95
|
+
*
|
|
96
|
+
* It is a modal dialog covering everything, and Escape did not close it
|
|
97
|
+
* — the first press dropped the selection underneath it instead, which
|
|
98
|
+
* from inside the page looked like Escape doing nothing at all. A modal
|
|
99
|
+
* that cannot be dismissed from the keyboard is a trap; the only way
|
|
100
|
+
* out was the button.
|
|
101
|
+
*/
|
|
102
|
+
if (isJackedIn)
|
|
103
|
+
exit();
|
|
104
|
+
// A search lights the whole picture, so it comes off first, and the
|
|
105
|
+
// emphasis goes back to what the selection reaches.
|
|
106
|
+
else if (view.q)
|
|
107
|
+
go(withoutSearch(view));
|
|
108
|
+
// Then the Graview: rising is the biggest change of place Escape can
|
|
109
|
+
// undo, and it should not also drop a selection on the way past.
|
|
110
|
+
else if (overview)
|
|
111
|
+
go(withOverview(view, false));
|
|
112
|
+
else if (selection.length > 0)
|
|
113
|
+
clear();
|
|
114
|
+
// A move is an adjustment of where you are, so it comes off before the
|
|
115
|
+
// things that decide where you are.
|
|
116
|
+
else if (view.pan !== undefined || Object.keys(view.pins).length > 0) {
|
|
117
|
+
go(withoutMoves(view));
|
|
118
|
+
}
|
|
119
|
+
else if (view.relation)
|
|
120
|
+
show(null);
|
|
121
|
+
else if (view.focusId !== home)
|
|
122
|
+
focus(home);
|
|
123
|
+
};
|
|
124
|
+
window.addEventListener("keydown", onKey, true);
|
|
125
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
126
|
+
}, [view, focus, show, go, selection, clear, home, overview, isJackedIn, exit]);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The way out to the Graview, and back — one control, two directions.
|
|
131
|
+
*
|
|
132
|
+
* The framework's own name for the view of the whole thing, which is the
|
|
133
|
+
* right name: everything else here is a lens over part of the graph, and this
|
|
134
|
+
* is the graph. It is a TOGGLE and presents as one: labelled "Graview" from
|
|
135
|
+
* the ground (the place it takes you) and "Focus" from altitude (the way back
|
|
136
|
+
* down), with the pressed state saying the same thing to a screen reader.
|
|
137
|
+
*
|
|
138
|
+
* THE MARK MORPHS. The scene's own rising is a morph rather than a cut — the
|
|
139
|
+
* grid dissolves into the iso lattice, the districts grow out of their cards,
|
|
140
|
+
* all riding one registered number. The control sits beside the scene rather
|
|
141
|
+
* than inside it, so it carries its OWN copy of that number, transitioned on
|
|
142
|
+
* the same 640ms curve (`.graview-altitude-control` in the theme): the three
|
|
143
|
+
* kinds on their ring gather into one node inside one ring as the scene
|
|
144
|
+
* rises, and open back out as it lands. Where an engine cannot register the
|
|
145
|
+
* property the scene cuts, and so does the mark — the same mechanism, so they
|
|
146
|
+
* cannot disagree.
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* Where "Focus" lands from altitude when nothing is focused.
|
|
150
|
+
*
|
|
151
|
+
* An app that opens from the city has no in-stack default, and the provider
|
|
152
|
+
* lands a focusless descent back on the overview — which made the control a
|
|
153
|
+
* button that did nothing, in every such app. Descending has to go
|
|
154
|
+
* SOMEWHERE: into the district that is selected, or the first one declared.
|
|
155
|
+
*/
|
|
156
|
+
/**
|
|
157
|
+
* WHERE "FOCUS" LANDS FROM ALTITUDE: the drive-in that is focused, else the
|
|
158
|
+
* selected kind's, else the first kind that has a drive-in — a kind with a
|
|
159
|
+
* picture of its own is a better place to walk up to than the first kind
|
|
160
|
+
* in the declaration — else the first kind at all.
|
|
161
|
+
*/
|
|
162
|
+
export function descentTarget(view, kinds, driveIns = []) {
|
|
163
|
+
if (view.focusId)
|
|
164
|
+
return view.focusId;
|
|
165
|
+
const selected = (view.selection ?? []).map(kindOfCard).find((kind) => kind !== null);
|
|
166
|
+
const kind = selected ?? driveIns.find((one) => kinds.includes(one)) ?? kinds[0] ?? null;
|
|
167
|
+
return kind === null ? null : aggregateId(kind);
|
|
168
|
+
}
|
|
169
|
+
export function OverviewButton() {
|
|
170
|
+
const { view, go } = useNavigation();
|
|
171
|
+
const { store, views, hiddenKinds } = useGraview();
|
|
172
|
+
const overview = view.overview ?? false;
|
|
173
|
+
const driveIns = views.places().map((place) => place.kind).filter((kind) => !hiddenKinds.has(kind));
|
|
174
|
+
const target = descentTarget(view, store.schema.kinds, driveIns);
|
|
175
|
+
const descend = () => {
|
|
176
|
+
go(withFocus(withOverview(view, false), target));
|
|
177
|
+
};
|
|
178
|
+
/*
|
|
179
|
+
* UP AND DOWN. "Graview" and "Focus" said neither: a person meeting the
|
|
180
|
+
* control for the first time had to press it to learn what it did. Up is
|
|
181
|
+
* up; down says where you land — the place whose picture is showing, or
|
|
182
|
+
* the district the focus names, in its own words.
|
|
183
|
+
*/
|
|
184
|
+
const landing = (() => {
|
|
185
|
+
if (!target)
|
|
186
|
+
return null;
|
|
187
|
+
const kind = kindsOfAggregate(target)[0];
|
|
188
|
+
// The showing that is showing, else the kind's first place.
|
|
189
|
+
const showing = view.within?.["view"];
|
|
190
|
+
const place = (showing ? views.places().find((one) => one.as === showing) : undefined) ??
|
|
191
|
+
(kind ? views.places().find((one) => one.kind === kind) : undefined);
|
|
192
|
+
if (place)
|
|
193
|
+
return place.title;
|
|
194
|
+
if (kind)
|
|
195
|
+
return store.schema.tryDefinition(kind)?.plural ?? kind;
|
|
196
|
+
return store.graph.getNode(target)?.label ?? null;
|
|
197
|
+
})();
|
|
198
|
+
const label = overview ? (landing ? `Down to ${landing}` : "Down") : "Up";
|
|
199
|
+
return (_jsxs("button", { type: "button", "data-testid": "overview", className: "graview-altitude-control", "aria-pressed": overview, "aria-label": label, title: overview ? `${label} — back down into the view` : "Up — the whole thing, from outside",
|
|
200
|
+
// A view state, so it is a URL, the back button works, and the cards
|
|
201
|
+
// already on screen fly out into the ring rather than being replaced.
|
|
202
|
+
onClick: () => (overview ? descend() : go(withOverview(view, true))),
|
|
203
|
+
/*
|
|
204
|
+
* SCENE FURNITURE, in the scene's corner — the way a map carries its
|
|
205
|
+
* own altitude control.
|
|
206
|
+
*
|
|
207
|
+
* It has lived in two wrong places: floating over the scene as a
|
|
208
|
+
* labelled pill ("awkwardly slammed on top", twice), and then in the
|
|
209
|
+
* command bar, where it spent prime chrome on a control that is about
|
|
210
|
+
* the CANVAS, not the app. The bar is for what the app is; rising and
|
|
211
|
+
* descending is something you do to the picture, so the control sits
|
|
212
|
+
* on the picture — quiet, in the one corner every state leaves empty.
|
|
213
|
+
*/
|
|
214
|
+
style: {
|
|
215
|
+
position: "absolute",
|
|
216
|
+
top: 14,
|
|
217
|
+
right: 14,
|
|
218
|
+
zIndex: 5,
|
|
219
|
+
display: "inline-flex",
|
|
220
|
+
alignItems: "center",
|
|
221
|
+
justifyContent: "center",
|
|
222
|
+
gap: 7,
|
|
223
|
+
height: 38,
|
|
224
|
+
padding: "0 13px 0 11px",
|
|
225
|
+
borderRadius: 999,
|
|
226
|
+
fontSize: "0.875rem",
|
|
227
|
+
whiteSpace: "nowrap",
|
|
228
|
+
background: "var(--graview-float)",
|
|
229
|
+
boxShadow: "var(--graview-lift-low)",
|
|
230
|
+
// The number the mark rides. Inline, like the ground's own, so the
|
|
231
|
+
// theme's transition on the class carries it between the two.
|
|
232
|
+
["--graview-altitude"]: overview ? 1 : 0,
|
|
233
|
+
...(overview
|
|
234
|
+
? { borderColor: "var(--graview-accent)", color: "var(--graview-accent)" }
|
|
235
|
+
: {}),
|
|
236
|
+
}, children: [_jsxs("svg", { className: "graview-altitude-mark", width: "16", height: "16", viewBox: "0 0 12 12", "aria-hidden": "true", children: [_jsx("ellipse", { className: "graview-altitude-mark-ring", cx: "6", cy: "6.6", rx: "5", ry: "2.6", fill: "none", stroke: "currentColor", strokeWidth: "0.9" }), _jsx("circle", { className: "graview-altitude-mark-apex", cx: "6", cy: "4", r: "1.5", fill: "currentColor" }), _jsx("circle", { className: "graview-altitude-mark-wing", "data-side": "left", cx: "1.6", cy: "7.4", r: "1.2", fill: "currentColor" }), _jsx("circle", { className: "graview-altitude-mark-wing", "data-side": "right", cx: "10.4", cy: "7.4", r: "1.2", fill: "currentColor" })] }), _jsx("span", { className: "graview-altitude-label", children: label })] }));
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=back-out.js.map
|