@skillcdn/console 0.0.0-stage → 0.1.1

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 (128) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +79 -2
  3. package/dist/api.d.ts +7 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +11 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli/cli.d.ts +34 -0
  8. package/dist/cli/cli.d.ts.map +1 -0
  9. package/dist/cli/cli.js +557 -0
  10. package/dist/cli/cli.js.map +1 -0
  11. package/dist/cli/credentials.d.ts +16 -0
  12. package/dist/cli/credentials.d.ts.map +1 -0
  13. package/dist/cli/credentials.js +46 -0
  14. package/dist/cli/credentials.js.map +1 -0
  15. package/dist/cli/format.d.ts +16 -0
  16. package/dist/cli/format.d.ts.map +1 -0
  17. package/dist/cli/format.js +151 -0
  18. package/dist/cli/format.js.map +1 -0
  19. package/dist/cli/help.d.ts +16 -0
  20. package/dist/cli/help.d.ts.map +1 -0
  21. package/dist/cli/help.js +181 -0
  22. package/dist/cli/help.js.map +1 -0
  23. package/dist/cli/main.d.ts +3 -0
  24. package/dist/cli/main.d.ts.map +1 -0
  25. package/dist/cli/main.js +32 -0
  26. package/dist/cli/main.js.map +1 -0
  27. package/dist/cli/terminal.d.ts +12 -0
  28. package/dist/cli/terminal.d.ts.map +1 -0
  29. package/dist/cli/terminal.js +68 -0
  30. package/dist/cli/terminal.js.map +1 -0
  31. package/dist/client.d.ts +92 -0
  32. package/dist/client.d.ts.map +1 -0
  33. package/dist/client.js +117 -0
  34. package/dist/client.js.map +1 -0
  35. package/dist/components/board.d.ts +20 -0
  36. package/dist/components/board.d.ts.map +1 -0
  37. package/dist/components/board.js +19 -0
  38. package/dist/components/board.js.map +1 -0
  39. package/dist/components/decision-form.d.ts +13 -0
  40. package/dist/components/decision-form.d.ts.map +1 -0
  41. package/dist/components/decision-form.js +23 -0
  42. package/dist/components/decision-form.js.map +1 -0
  43. package/dist/components/decision-list.d.ts +22 -0
  44. package/dist/components/decision-list.d.ts.map +1 -0
  45. package/dist/components/decision-list.js +28 -0
  46. package/dist/components/decision-list.js.map +1 -0
  47. package/dist/components/event-feed.d.ts +13 -0
  48. package/dist/components/event-feed.d.ts.map +1 -0
  49. package/dist/components/event-feed.js +59 -0
  50. package/dist/components/event-feed.js.map +1 -0
  51. package/dist/components/markdown.d.ts +4 -0
  52. package/dist/components/markdown.d.ts.map +1 -0
  53. package/dist/components/markdown.js +34 -0
  54. package/dist/components/markdown.js.map +1 -0
  55. package/dist/components/people.d.ts +11 -0
  56. package/dist/components/people.d.ts.map +1 -0
  57. package/dist/components/people.js +7 -0
  58. package/dist/components/people.js.map +1 -0
  59. package/dist/components/runs.d.ts +27 -0
  60. package/dist/components/runs.d.ts.map +1 -0
  61. package/dist/components/runs.js +45 -0
  62. package/dist/components/runs.js.map +1 -0
  63. package/dist/components/shell.d.ts +22 -0
  64. package/dist/components/shell.d.ts.map +1 -0
  65. package/dist/components/shell.js +16 -0
  66. package/dist/components/shell.js.map +1 -0
  67. package/dist/components/sign-in.d.ts +11 -0
  68. package/dist/components/sign-in.d.ts.map +1 -0
  69. package/dist/components/sign-in.js +15 -0
  70. package/dist/components/sign-in.js.map +1 -0
  71. package/dist/components/skills.d.ts +7 -0
  72. package/dist/components/skills.d.ts.map +1 -0
  73. package/dist/components/skills.js +26 -0
  74. package/dist/components/skills.js.map +1 -0
  75. package/dist/components/task-form.d.ts +14 -0
  76. package/dist/components/task-form.d.ts.map +1 -0
  77. package/dist/components/task-form.js +34 -0
  78. package/dist/components/task-form.js.map +1 -0
  79. package/dist/components/task-view.d.ts +22 -0
  80. package/dist/components/task-view.d.ts.map +1 -0
  81. package/dist/components/task-view.js +32 -0
  82. package/dist/components/task-view.js.map +1 -0
  83. package/dist/components/tokens.d.ts +26 -0
  84. package/dist/components/tokens.d.ts.map +1 -0
  85. package/dist/components/tokens.js +42 -0
  86. package/dist/components/tokens.js.map +1 -0
  87. package/dist/components/ui.d.ts +61 -0
  88. package/dist/components/ui.d.ts.map +1 -0
  89. package/dist/components/ui.js +109 -0
  90. package/dist/components/ui.js.map +1 -0
  91. package/dist/console.css +1382 -0
  92. package/dist/console.d.ts +44 -0
  93. package/dist/console.d.ts.map +1 -0
  94. package/dist/console.js +181 -0
  95. package/dist/console.js.map +1 -0
  96. package/dist/data.d.ts +41 -0
  97. package/dist/data.d.ts.map +1 -0
  98. package/dist/data.js +208 -0
  99. package/dist/data.js.map +1 -0
  100. package/dist/index.d.ts +19 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +23 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/limits.d.ts +37 -0
  105. package/dist/limits.d.ts.map +1 -0
  106. package/dist/limits.js +40 -0
  107. package/dist/limits.js.map +1 -0
  108. package/dist/router.d.ts +37 -0
  109. package/dist/router.d.ts.map +1 -0
  110. package/dist/router.js +55 -0
  111. package/dist/router.js.map +1 -0
  112. package/dist/routes.d.ts +47 -0
  113. package/dist/routes.d.ts.map +1 -0
  114. package/dist/routes.js +53 -0
  115. package/dist/routes.js.map +1 -0
  116. package/dist/schemas.d.ts +789 -0
  117. package/dist/schemas.d.ts.map +1 -0
  118. package/dist/schemas.js +341 -0
  119. package/dist/schemas.js.map +1 -0
  120. package/dist/text.d.ts +6 -0
  121. package/dist/text.d.ts.map +1 -0
  122. package/dist/text.js +31 -0
  123. package/dist/text.js.map +1 -0
  124. package/dist/vocabulary.d.ts +35 -0
  125. package/dist/vocabulary.d.ts.map +1 -0
  126. package/dist/vocabulary.js +57 -0
  127. package/dist/vocabulary.js.map +1 -0
  128. package/package.json +70 -3
@@ -0,0 +1,92 @@
1
+ import { type RestAnswerInput, type RestArtifactInput, type RestDecision, type RestDecisionInput, type RestDecisions, type RestEvents, type RestMe, type RestPeople, type RestPerson, type RestPersonPatch, type RestReportInput, type RestRun, type RestRunEndInput, type RestRunInput, type RestRuns, type RestSkills, type RestTask, type RestTaskInput, type RestTaskPatch, type RestTasks, type RestTokenCreated, type RestTokenInput, type RestTokens } from "./schemas.js";
2
+ import type { TaskState } from "./vocabulary.js";
3
+ export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
4
+ /** A file to hand in: its bytes, what to call it, and what it is. */
5
+ export interface FileUpload {
6
+ /** The file's name, without a path. */
7
+ readonly name: string;
8
+ readonly bytes: Uint8Array | Blob;
9
+ /** The media type; `application/octet-stream` when left out. */
10
+ readonly contentType?: string | undefined;
11
+ readonly label?: string | undefined;
12
+ }
13
+ export interface ClientOptions {
14
+ /** The origin of the console, without a path. Empty: the origin of the page. */
15
+ readonly baseUrl?: string;
16
+ /** The platform's `fetch` when left out. Tests hand in one that never leaves the process. */
17
+ readonly fetch?: FetchLike;
18
+ /**
19
+ * A token a person made, for an agent, a script or a console of their own: sent as
20
+ * `Authorization: Bearer`, and the browser's cookies left out. Left out, the session cookie of
21
+ * the page's own origin is what the console answers to.
22
+ */
23
+ readonly token?: string;
24
+ }
25
+ export declare class ApiError extends Error {
26
+ /** HTTP status, or 0 when there was no response at all. */
27
+ readonly status: number;
28
+ /** The stable code from the error body, `network` or `invalid_response`. */
29
+ readonly code: string;
30
+ constructor(status: number, code: string, message: string);
31
+ }
32
+ export interface ConsoleClient {
33
+ me(signal?: AbortSignal): Promise<RestMe>;
34
+ people(signal?: AbortSignal): Promise<RestPeople>;
35
+ /** Changes what a person is; for an administrator. */
36
+ updatePerson(id: string, patch: RestPersonPatch): Promise<RestPerson>;
37
+ tasks(filter?: {
38
+ readonly state?: TaskState;
39
+ }, signal?: AbortSignal): Promise<RestTasks>;
40
+ /** One task, by its id or by its number. */
41
+ task(ref: string, signal?: AbortSignal): Promise<RestTask>;
42
+ createTask(input: RestTaskInput): Promise<RestTask>;
43
+ updateTask(id: string, patch: RestTaskPatch): Promise<RestTask>;
44
+ /** The decisions, or only those that wait, or only those about one task. */
45
+ decisions(filter?: {
46
+ readonly open?: boolean;
47
+ readonly task?: string;
48
+ }, signal?: AbortSignal): Promise<RestDecisions>;
49
+ decision(id: string, signal?: AbortSignal): Promise<RestDecision>;
50
+ /**
51
+ * One decision, after waiting up to `waitSeconds` for its answer: the server holds the request
52
+ * while the decision waits, for as long as it allows, and answers the decision as it stands.
53
+ */
54
+ awaitDecision(id: string, waitSeconds: number, signal?: AbortSignal): Promise<RestDecision>;
55
+ raiseDecision(input: RestDecisionInput): Promise<RestDecision>;
56
+ answerDecision(id: string, input: RestAnswerInput): Promise<RestDecision>;
57
+ /** The runs, newest first; or only those on one task, only the open ones, only the asker's own. */
58
+ runs(filter?: {
59
+ readonly task?: string;
60
+ readonly open?: boolean;
61
+ readonly mine?: boolean;
62
+ }, signal?: AbortSignal): Promise<RestRuns>;
63
+ run(id: string, signal?: AbortSignal): Promise<RestRun>;
64
+ /** Takes a task: a run begins, for the person the asker is or acts for. */
65
+ startRun(input: RestRunInput): Promise<RestRun>;
66
+ /** Says how the work goes, on a run of the asker's. */
67
+ report(runId: string, input: RestReportInput): Promise<RestRun>;
68
+ /** Hands in a link, on a run of the asker's. */
69
+ handIn(runId: string, input: RestArtifactInput): Promise<RestRun>;
70
+ /** Hands in a file, on a run of the asker's: the console keeps the bytes. */
71
+ handInFile(runId: string, input: FileUpload): Promise<RestRun>;
72
+ /** Where the bytes of a file handed in are read, by the artifact's id. */
73
+ fileUrl(artifactId: string): string;
74
+ /** Ends a run: finished or failed by the agent; abandoned by the person it is for, or an administrator. */
75
+ endRun(runId: string, input: RestRunEndInput): Promise<RestRun>;
76
+ /** What happened after event number `after`; `0` for the beginning. */
77
+ events(after: number, signal?: AbortSignal): Promise<RestEvents>;
78
+ /** Where an `EventSource` subscribes to what happens after event number `after`. */
79
+ eventStreamUrl(after: number): string;
80
+ /** The organization's skills, as SkillCDN serves them at the console's address. */
81
+ skills(signal?: AbortSignal): Promise<RestSkills>;
82
+ /** The tokens of whoever asks. */
83
+ tokens(signal?: AbortSignal): Promise<RestTokens>;
84
+ /** Makes a token; the answer carries the secret, this once. */
85
+ createToken(input: RestTokenInput): Promise<RestTokenCreated>;
86
+ /** Takes a token away, whoever holds it. */
87
+ revokeToken(id: string): Promise<void>;
88
+ /** Ends the session on this browser. */
89
+ signOut(): Promise<void>;
90
+ }
91
+ export declare function createClient(options?: ClientOptions): ConsoleClient;
92
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,117 @@
1
+ import { AUTH_ROUTES, REST_ROUTES, restPath } from "./routes.js";
2
+ import { restDecisionSchema, restDecisionsSchema, restErrorSchema, restEventsSchema, restMeSchema, restPeopleSchema, restPersonSchema, restRunSchema, restRunsSchema, restSkillsSchema, restTaskSchema, restTasksSchema, restTokenCreatedSchema, restTokensSchema, } from "./schemas.js";
3
+ export class ApiError extends Error {
4
+ /** HTTP status, or 0 when there was no response at all. */
5
+ status;
6
+ /** The stable code from the error body, `network` or `invalid_response`. */
7
+ code;
8
+ constructor(status, code, message) {
9
+ super(message);
10
+ this.name = "ApiError";
11
+ this.status = status;
12
+ this.code = code;
13
+ }
14
+ }
15
+ const INVALID = "The server answered unexpectedly.";
16
+ export function createClient(options = {}) {
17
+ const base = (options.baseUrl ?? "").replace(/\/+$/, "");
18
+ const send = options.fetch ?? ((input, init) => fetch(input, init));
19
+ const { token } = options;
20
+ const withQuery = (path, params) => {
21
+ const query = new URLSearchParams();
22
+ for (const [name, value] of Object.entries(params)) {
23
+ if (value !== undefined) {
24
+ query.set(name, value);
25
+ }
26
+ }
27
+ return query.size === 0 ? `${base}${path}` : `${base}${path}?${query}`;
28
+ };
29
+ /** What a response says when it is not what was asked for. */
30
+ const failure = async (response) => {
31
+ const parsed = restErrorSchema.safeParse(await response.json().catch(() => undefined));
32
+ return parsed.success
33
+ ? new ApiError(response.status, parsed.data.error.code, parsed.data.error.message)
34
+ : new ApiError(response.status, "invalid_response", INVALID);
35
+ };
36
+ const request = async (method, url, body, schema, signal) => {
37
+ const form = body instanceof FormData;
38
+ let response;
39
+ try {
40
+ response = await send(url, {
41
+ method,
42
+ ...(signal === undefined ? {} : { signal }),
43
+ // Same origin, so the session cookie goes with it; the browser names the origin of a
44
+ // request that changes something, which the server checks. With a token, the token is
45
+ // the credential and no cookie travels.
46
+ credentials: token === undefined ? "same-origin" : "omit",
47
+ headers: {
48
+ accept: "application/json",
49
+ // A form names its own type, boundary included; everything else is JSON.
50
+ ...(body === undefined || form ? {} : { "content-type": "application/json" }),
51
+ ...(token === undefined ? {} : { authorization: `Bearer ${token}` }),
52
+ },
53
+ ...(body === undefined ? {} : { body: form ? body : JSON.stringify(body) }),
54
+ });
55
+ }
56
+ catch (error) {
57
+ if (signal?.aborted === true) {
58
+ throw error;
59
+ }
60
+ throw new ApiError(0, "network", "The server could not be reached.");
61
+ }
62
+ if (!response.ok) {
63
+ throw await failure(response);
64
+ }
65
+ if (schema === undefined) {
66
+ return undefined;
67
+ }
68
+ const parsed = schema.safeParse(await response.json().catch(() => undefined));
69
+ if (!parsed.success) {
70
+ throw new ApiError(response.status, "invalid_response", INVALID);
71
+ }
72
+ return parsed.data;
73
+ };
74
+ const flag = (value) => value === undefined ? undefined : String(value);
75
+ return {
76
+ me: (signal) => request("GET", `${base}${REST_ROUTES.me}`, undefined, restMeSchema, signal),
77
+ people: (signal) => request("GET", `${base}${REST_ROUTES.people}`, undefined, restPeopleSchema, signal),
78
+ updatePerson: (id, patch) => request("PATCH", `${base}${restPath("people", id)}`, patch, restPersonSchema),
79
+ tasks: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.tasks, { state: filter.state }), undefined, restTasksSchema, signal),
80
+ task: (ref, signal) => request("GET", `${base}${restPath("tasks", ref)}`, undefined, restTaskSchema, signal),
81
+ createTask: (input) => request("POST", `${base}${REST_ROUTES.tasks}`, input, restTaskSchema),
82
+ updateTask: (id, patch) => request("PATCH", `${base}${restPath("tasks", id)}`, patch, restTaskSchema),
83
+ decisions: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.decisions, { open: flag(filter.open), task: filter.task }), undefined, restDecisionsSchema, signal),
84
+ decision: (id, signal) => request("GET", `${base}${restPath("decisions", id)}`, undefined, restDecisionSchema, signal),
85
+ awaitDecision: (id, waitSeconds, signal) => request("GET", withQuery(restPath("decisions", id), { wait: String(waitSeconds) }), undefined, restDecisionSchema, signal),
86
+ raiseDecision: (input) => request("POST", `${base}${REST_ROUTES.decisions}`, input, restDecisionSchema),
87
+ answerDecision: (id, input) => request("POST", `${base}${restPath("decisions", id)}/answer`, input, restDecisionSchema),
88
+ runs: (filter = {}, signal) => request("GET", withQuery(REST_ROUTES.runs, {
89
+ task: filter.task,
90
+ open: flag(filter.open),
91
+ mine: flag(filter.mine),
92
+ }), undefined, restRunsSchema, signal),
93
+ run: (id, signal) => request("GET", `${base}${restPath("runs", id)}`, undefined, restRunSchema, signal),
94
+ startRun: (input) => request("POST", `${base}${REST_ROUTES.runs}`, input, restRunSchema),
95
+ report: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/reports`, input, restRunSchema),
96
+ handIn: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/artifacts`, input, restRunSchema),
97
+ handInFile: (runId, input) => {
98
+ const form = new FormData();
99
+ const bytes = input.bytes instanceof Blob ? input.bytes : new Blob([Uint8Array.from(input.bytes)]);
100
+ form.set("file", new File([bytes], input.name, { type: input.contentType ?? "application/octet-stream" }), input.name);
101
+ if (input.label !== undefined) {
102
+ form.set("label", input.label);
103
+ }
104
+ return request("POST", `${base}${restPath("runs", runId)}/files`, form, restRunSchema);
105
+ },
106
+ fileUrl: (artifactId) => `${base}${restPath("files", artifactId)}`,
107
+ endRun: (runId, input) => request("POST", `${base}${restPath("runs", runId)}/end`, input, restRunSchema),
108
+ events: (after, signal) => request("GET", withQuery(REST_ROUTES.events, { after: String(after) }), undefined, restEventsSchema, signal),
109
+ eventStreamUrl: (after) => withQuery(`${REST_ROUTES.events}/stream`, { after: String(after) }),
110
+ skills: (signal) => request("GET", `${base}${REST_ROUTES.skills}`, undefined, restSkillsSchema, signal),
111
+ tokens: (signal) => request("GET", `${base}${REST_ROUTES.tokens}`, undefined, restTokensSchema, signal),
112
+ createToken: (input) => request("POST", `${base}${REST_ROUTES.tokens}`, input, restTokenCreatedSchema),
113
+ revokeToken: (id) => request("DELETE", `${base}${restPath("tokens", id)}`, undefined, undefined),
114
+ signOut: () => request("POST", `${base}${AUTH_ROUTES.logout}`, undefined, undefined),
115
+ };
116
+ }
117
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAwBL,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAiCtB,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,2DAA2D;IAClD,MAAM,CAAS;IACxB,4EAA4E;IACnE,IAAI,CAAS;IAEtB,YAAY,MAAc,EAAE,IAAY,EAAE,OAAe;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AA+DD,MAAM,OAAO,GAAG,mCAAmC,CAAC;AAEpD,MAAM,UAAU,YAAY,CAAC,OAAO,GAAkB,EAAE;IACtD,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE1B,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,MAA0C,EAAU,EAAE;QACrF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;IACzE,CAAC,CAAC;IAEF,8DAA8D;IAC9D,MAAM,OAAO,GAAG,KAAK,EAAE,QAAkB,EAAqB,EAAE;QAC9D,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC,OAAO;YACnB,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;YAClF,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,EACnB,MAA2C,EAC3C,GAAW,EACX,IAAa,EACb,MAA6B,EAC7B,MAAoB,EACR,EAAE;QACd,MAAM,IAAI,GAAG,IAAI,YAAY,QAAQ,CAAC;QACtC,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE;gBACzB,MAAM;gBACN,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;gBAC3C,qFAAqF;gBACrF,sFAAsF;gBACtF,wCAAwC;gBACxC,WAAW,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM;gBACzD,OAAO,EAAE;oBACP,MAAM,EAAE,kBAAkB;oBAC1B,yEAAyE;oBACzE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;oBAC7E,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;iBACrE;gBACD,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;aAC5E,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC7B,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAI,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,kCAAkC,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,SAAc,CAAC;QACxB,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,KAA0B,EAAsB,EAAE,CAC9D,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAElD,OAAO;QACL,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC;QAC3F,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CACjB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC;QACrF,YAAY,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAC1B,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,gBAAgB,CAAC;QAC/E,KAAK,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,CAC7B,OAAO,CACL,KAAK,EACL,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EACrD,SAAS,EACT,eAAe,EACf,MAAM,CACP;QACH,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CACpB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC;QACvF,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,cAAc,CAAC;QAC5F,UAAU,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CACxB,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,cAAc,CAAC;QAC5E,SAAS,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,CACjC,OAAO,CACL,KAAK,EACL,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,EAChF,SAAS,EACT,mBAAmB,EACnB,MAAM,CACP;QACH,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CACvB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,CAAC;QAC9F,aAAa,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,CACzC,OAAO,CACL,KAAK,EACL,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,EACnE,SAAS,EACT,kBAAkB,EAClB,MAAM,CACP;QACH,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CACvB,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,kBAAkB,CAAC;QAC/E,cAAc,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAC5B,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,kBAAkB,CAAC;QAC1F,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,CAC5B,OAAO,CACL,KAAK,EACL,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE;YAC1B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;SACxB,CAAC,EACF,SAAS,EACT,cAAc,EACd,MAAM,CACP;QACH,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAClB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC;QACpF,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC;QACxF,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACvB,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,aAAa,CAAC;QACpF,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACvB,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,aAAa,CAAC;QACtF,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,GAAG,CACN,MAAM,EACN,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,IAAI,0BAA0B,EAAE,CAAC,EACxF,KAAK,CAAC,IAAI,CACX,CAAC;YACF,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE;QAClE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACvB,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC;QAChF,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CACxB,OAAO,CACL,KAAK,EACL,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACvD,SAAS,EACT,gBAAgB,EAChB,MAAM,CACP;QACH,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9F,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CACjB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC;QACrF,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CACjB,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC;QACrF,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,CACrB,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,sBAAsB,CAAC;QAChF,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAClB,OAAO,CAAC,QAAQ,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC;QAC7E,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC;KACrF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from "react";
2
+ import { type RestTask, type TaskState } from "../api.js";
3
+ export interface BoardProps {
4
+ readonly tasks: readonly RestTask[];
5
+ /** The link to a task's own page, as the composition routes it. */
6
+ readonly taskHref: (task: RestTask) => string;
7
+ readonly onOpen: (task: RestTask) => void;
8
+ /** Called when a person moves a task to another column. Left out, the board is read-only. */
9
+ readonly onMove?: ((task: RestTask, state: TaskState) => void) | undefined;
10
+ /** What a column shows when it has nothing; the way to write the first task, for example. */
11
+ readonly empty?: ReactNode;
12
+ }
13
+ export declare function TaskCard(props: {
14
+ readonly task: RestTask;
15
+ readonly href: string;
16
+ readonly onOpen: (task: RestTask) => void;
17
+ readonly onMove?: ((task: RestTask, state: TaskState) => void) | undefined;
18
+ }): import("react").JSX.Element;
19
+ export declare function Board(props: BoardProps): import("react").JSX.Element;
20
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/components/board.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,KAAK,QAAQ,EAAe,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAMvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3E,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC5E,+BAqDA;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,+BAgCtC"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TASK_STATES } from "../api.js";
3
+ import { Avatar, Badge, cx, PriorityBadge, STATE_LABELS } from "./ui.js";
4
+ export function TaskCard(props) {
5
+ const { task } = props;
6
+ return (_jsxs("article", { className: "sc-card", "aria-label": `#${task.number} ${task.title}`, children: [_jsxs("a", { className: "sc-card-title", href: props.href, onClick: (event) => {
7
+ if (event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey) {
8
+ event.preventDefault();
9
+ props.onOpen(task);
10
+ }
11
+ }, children: [_jsxs("span", { className: "sc-card-number", children: ["#", task.number] }), " ", task.title] }), _jsxs("div", { className: "sc-card-meta", children: [_jsx(PriorityBadge, { priority: task.priority }), task.openDecisions > 0 && (_jsx(Badge, { tone: "warning", title: "Decisions waiting for a person", children: task.openDecisions === 1 ? "1 decision" : `${task.openDecisions} decisions` })), task.openRuns > 0 && (_jsx(Badge, { tone: "accent", title: "An agent is at work on it", children: "agent at work" })), task.links.length > 0 && (_jsx(Badge, { tone: "neutral", children: task.links.length === 1 ? "1 link" : `${task.links.length} links` })), _jsx("span", { className: "sc-card-spacer" }), task.assignee !== null && _jsx(Avatar, { person: task.assignee, size: "sm" })] }), props.onMove !== undefined && (_jsxs("label", { className: "sc-card-move", children: [_jsx("span", { className: "sc-visually-hidden", children: "Move to" }), _jsx("select", { value: task.state, onChange: (event) => props.onMove?.(task, event.target.value), children: TASK_STATES.map((state) => (_jsx("option", { value: state, children: STATE_LABELS[state] }, state))) })] }))] }));
12
+ }
13
+ export function Board(props) {
14
+ return (_jsx("div", { className: "sc-board", children: TASK_STATES.map((state) => {
15
+ const tasks = props.tasks.filter((task) => task.state === state);
16
+ return (_jsxs("section", { className: cx("sc-column", `sc-column-${state}`), "aria-label": STATE_LABELS[state], children: [_jsxs("header", { className: "sc-column-header", children: [_jsx("h2", { className: "sc-column-title", children: STATE_LABELS[state] }), _jsx("span", { className: "sc-column-count", children: tasks.length })] }), _jsxs("div", { className: "sc-column-body", children: [tasks.map((task) => (_jsx(TaskCard, { task: task, href: props.taskHref(task), onOpen: props.onOpen, onMove: props.onMove }, task.id))), tasks.length === 0 && state === "idea" && props.empty] })] }, state));
17
+ }) }));
18
+ }
19
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/components/board.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type RestDecisionInput, type RestTask } from "../api.js";
2
+ export interface DecisionFormProps {
3
+ /** The tasks the decision may be about. */
4
+ readonly tasks: readonly RestTask[];
5
+ /** The task it is about from the start, when raised from a task's page. */
6
+ readonly taskId?: string | undefined;
7
+ readonly busy?: boolean | undefined;
8
+ readonly error?: string | undefined;
9
+ readonly onSubmit: (input: RestDecisionInput) => void;
10
+ readonly onCancel?: (() => void) | undefined;
11
+ }
12
+ export declare function DecisionForm(props: DecisionFormProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=decision-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-form.d.ts","sourceRoot":"","sources":["../../src/components/decision-form.tsx"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAKnB,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CAC9C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BA2GpD"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { MAX_BODY_LENGTH, MAX_OPTION_LABEL_LENGTH, MAX_OPTIONS, MAX_QUESTION_LENGTH, MIN_OPTIONS, } from "../api.js";
4
+ import { Button } from "./ui.js";
5
+ export function DecisionForm(props) {
6
+ const [question, setQuestion] = useState("");
7
+ const [body, setBody] = useState("");
8
+ const [taskId, setTaskId] = useState(props.taskId ?? "");
9
+ const [options, setOptions] = useState(["", ""]);
10
+ const labels = options.map((option) => option.trim()).filter((option) => option.length > 0);
11
+ const ready = question.trim().length > 0 && labels.length >= MIN_OPTIONS;
12
+ const submit = (event) => {
13
+ event.preventDefault();
14
+ props.onSubmit({
15
+ question: question.trim(),
16
+ body,
17
+ options: labels.map((label) => ({ label })),
18
+ taskId: taskId === "" ? null : taskId,
19
+ });
20
+ };
21
+ return (_jsxs("form", { className: "sc-form", onSubmit: submit, children: [_jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "Question" }), _jsx("input", { className: "sc-input", value: question, maxLength: MAX_QUESTION_LENGTH, required: true, onChange: (event) => setQuestion(event.target.value) })] }), _jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "Context" }), _jsx("textarea", { className: "sc-input sc-textarea", value: body, maxLength: MAX_BODY_LENGTH, rows: 4, placeholder: "What a person needs to know to answer, in Markdown.", onChange: (event) => setBody(event.target.value) })] }), props.taskId === undefined && props.tasks.length > 0 && (_jsxs("label", { className: "sc-field", children: [_jsx("span", { className: "sc-field-label", children: "About" }), _jsxs("select", { className: "sc-input", value: taskId, onChange: (event) => setTaskId(event.target.value), children: [_jsx("option", { value: "", children: "No task in particular" }), props.tasks.map((task) => (_jsxs("option", { value: task.id, children: ["#", task.number, " ", task.title] }, task.id)))] })] })), _jsxs("fieldset", { className: "sc-field sc-options", children: [_jsx("legend", { className: "sc-field-label", children: "Options" }), options.map((option, index) => (_jsxs("div", { className: "sc-link-row", children: [_jsx("input", { className: "sc-input", value: option, maxLength: MAX_OPTION_LABEL_LENGTH, placeholder: `Option ${index + 1}`, onChange: (event) => setOptions(options.map((entry, at) => (at === index ? event.target.value : entry))) }), options.length > MIN_OPTIONS && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setOptions(options.filter((_, at) => at !== index)), children: "Remove" }))] }, index))), options.length < MAX_OPTIONS && (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setOptions([...options, ""]), children: "Add an option" }))] }), props.error !== undefined && (_jsx("p", { className: "sc-form-error", role: "alert", children: props.error })), _jsxs("div", { className: "sc-form-actions", children: [_jsx(Button, { type: "submit", variant: "primary", disabled: props.busy === true || !ready, children: "Raise the decision" }), props.onCancel !== undefined && (_jsx(Button, { variant: "ghost", onClick: props.onCancel, children: "Cancel" }))] })] }));
22
+ }
23
+ //# sourceMappingURL=decision-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-form.js","sourceRoot":"","sources":["../../src/components/decision-form.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,WAAW,GAGZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAejC,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAoB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEpE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC;IAEzE,MAAM,MAAM,GAAG,CAAC,KAAgB,EAAE,EAAE;QAClC,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,QAAQ,CAAC;YACb,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;YACzB,IAAI;YACJ,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3C,MAAM,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;SACtC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACL,gBAAM,SAAS,EAAC,SAAS,EAAC,QAAQ,EAAE,MAAM,aACxC,iBAAO,SAAS,EAAC,UAAU,aACzB,eAAM,SAAS,EAAC,gBAAgB,yBAAgB,EAChD,gBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,mBAAmB,EAC9B,QAAQ,QACR,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GACpD,IACI,EACR,iBAAO,SAAS,EAAC,UAAU,aACzB,eAAM,SAAS,EAAC,gBAAgB,wBAAe,EAC/C,mBACE,SAAS,EAAC,sBAAsB,EAChC,KAAK,EAAE,IAAI,EACX,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,CAAC,EACP,WAAW,EAAC,qDAAqD,EACjE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAChD,IACI,EACP,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CACvD,iBAAO,SAAS,EAAC,UAAU,aACzB,eAAM,SAAS,EAAC,gBAAgB,sBAAa,EAC7C,kBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,aAElD,iBAAQ,KAAK,EAAC,EAAE,sCAA+B,EAC9C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,kBAAsB,KAAK,EAAE,IAAI,CAAC,EAAE,kBAChC,IAAI,CAAC,MAAM,OAAG,IAAI,CAAC,KAAK,KADf,IAAI,CAAC,EAAE,CAEX,CACV,CAAC,IACK,IACH,CACT,EACD,oBAAU,SAAS,EAAC,qBAAqB,aACvC,iBAAQ,SAAS,EAAC,gBAAgB,wBAAiB,EAClD,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAE9B,eAAiB,SAAS,EAAC,aAAa,aACtC,gBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,uBAAuB,EAClC,WAAW,EAAE,UAAU,KAAK,GAAG,CAAC,EAAE,EAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAErF,EACD,OAAO,CAAC,MAAM,GAAG,WAAW,IAAI,CAC/B,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,uBAG3D,CACV,KAlBO,KAAK,CAmBT,CACP,CAAC,EACD,OAAO,CAAC,MAAM,GAAG,WAAW,IAAI,CAC/B,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,CAAC,CAAC,8BAEpE,CACV,IACQ,EACV,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,CAC5B,YAAG,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,OAAO,YACtC,KAAK,CAAC,KAAK,GACV,CACL,EACD,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,mCAEtE,EACR,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,CAC/B,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,uBAEtC,CACV,IACG,IACD,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type RestAnswerInput, type RestDecision, type RestTask } from "../api.js";
2
+ export interface DecisionCardProps {
3
+ readonly decision: RestDecision;
4
+ /** The task the decision is about, when it is about one and the page knows it. */
5
+ readonly task?: RestTask | undefined;
6
+ readonly taskHref?: ((task: RestTask) => string) | undefined;
7
+ /** Called with the person's answer. Left out, a waiting decision cannot be answered here. */
8
+ readonly onAnswer?: ((decision: RestDecision, input: RestAnswerInput) => void) | undefined;
9
+ readonly busy?: boolean | undefined;
10
+ }
11
+ export declare function DecisionCard(props: DecisionCardProps): import("react").JSX.Element;
12
+ export interface DecisionListProps {
13
+ readonly decisions: readonly RestDecision[];
14
+ /** The tasks the decisions may be about, by id, for the cards to name them. */
15
+ readonly tasks: ReadonlyMap<string, RestTask>;
16
+ readonly taskHref?: ((task: RestTask) => string) | undefined;
17
+ readonly onAnswer?: ((decision: RestDecision, input: RestAnswerInput) => void) | undefined;
18
+ readonly busy?: boolean | undefined;
19
+ readonly empty?: React.ReactNode;
20
+ }
21
+ export declare function DecisionList(props: DecisionListProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=decision-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-list.d.ts","sourceRoot":"","sources":["../../src/components/decision-list.tsx"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAOpG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAiGpD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BA+BpD"}
@@ -0,0 +1,28 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { MAX_NOTE_LENGTH } from "../api.js";
4
+ import { Markdown } from "./markdown.js";
5
+ import { Button, cx, PersonChip, Time } from "./ui.js";
6
+ export function DecisionCard(props) {
7
+ const { decision, task } = props;
8
+ const [chosen, setChosen] = useState(undefined);
9
+ const [note, setNote] = useState("");
10
+ const answered = decision.answer !== null;
11
+ const chosenLabel = (id) => decision.options.find((option) => option.id === id)?.label ?? id;
12
+ return (_jsxs("article", { className: cx("sc-decision", answered && "sc-decision-answered"), children: [_jsxs("header", { className: "sc-decision-header", children: [_jsx("h3", { className: "sc-decision-question", children: decision.question }), _jsxs("p", { className: "sc-decision-meta", children: [_jsx(PersonChip, { person: decision.raisedBy }), " ", decision.run === null ? "asked" : `asked through ${decision.run.agent}`, " ", _jsx(Time, { iso: decision.createdAt }), task !== undefined && (_jsxs(_Fragment, { children: [" ", "about", " ", props.taskHref === undefined ? (_jsxs("span", { children: ["#", task.number, " ", task.title] })) : (_jsxs("a", { href: props.taskHref(task), children: ["#", task.number, " ", task.title] }))] }))] })] }), decision.body.length > 0 && _jsx(Markdown, { source: decision.body }), decision.answer !== null ? (_jsxs("div", { className: "sc-answer", children: [_jsx("p", { className: "sc-answer-option", children: chosenLabel(decision.answer.option) }), decision.answer.note !== null && (_jsx("p", { className: "sc-answer-note", children: decision.answer.note })), _jsxs("p", { className: "sc-decision-meta", children: [_jsx(PersonChip, { person: decision.answer.by }), " answered ", _jsx(Time, { iso: decision.answer.at })] })] })) : props.onAnswer === undefined ? (_jsx("p", { className: "sc-decision-waiting", children: "Waiting for a person." })) : (_jsxs("form", { className: "sc-answer-form", onSubmit: (event) => {
13
+ event.preventDefault();
14
+ if (chosen !== undefined) {
15
+ props.onAnswer?.(decision, {
16
+ option: chosen,
17
+ ...(note.trim() === "" ? {} : { note: note.trim() }),
18
+ });
19
+ }
20
+ }, children: [_jsx("div", { className: "sc-options-list", role: "radiogroup", "aria-label": "Options", children: decision.options.map((option) => (_jsxs("label", { className: cx("sc-option", chosen === option.id && "sc-option-chosen"), children: [_jsx("input", { type: "radio", name: `decision-${decision.id}`, value: option.id, checked: chosen === option.id, onChange: () => setChosen(option.id) }), _jsx("span", { children: option.label })] }, option.id))) }), _jsx("input", { className: "sc-input", placeholder: "A word about it, if any", maxLength: MAX_NOTE_LENGTH, value: note, onChange: (event) => setNote(event.target.value) }), _jsx("div", { className: "sc-form-actions", children: _jsx(Button, { type: "submit", variant: "primary", size: "sm", disabled: chosen === undefined || props.busy === true, children: "Answer" }) })] }))] }));
21
+ }
22
+ export function DecisionList(props) {
23
+ const waiting = props.decisions.filter((decision) => decision.answer === null);
24
+ const answered = props.decisions.filter((decision) => decision.answer !== null);
25
+ const card = (decision) => (_jsx(DecisionCard, { decision: decision, task: decision.taskId === null ? undefined : props.tasks.get(decision.taskId), taskHref: props.taskHref, onAnswer: props.onAnswer, busy: props.busy }, decision.id));
26
+ return (_jsxs("div", { className: "sc-decisions", children: [_jsxs("section", { "aria-label": "Waiting", children: [_jsxs("h2", { className: "sc-section-title", children: ["Waiting ", _jsx("span", { className: "sc-column-count", children: waiting.length })] }), waiting.length === 0 ? (props.empty ?? null) : waiting.map(card)] }), answered.length > 0 && (_jsxs("section", { "aria-label": "Answered", children: [_jsxs("h2", { className: "sc-section-title", children: ["Answered ", _jsx("span", { className: "sc-column-count", children: answered.length })] }), answered.map(card)] }))] }));
27
+ }
28
+ //# sourceMappingURL=decision-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-list.js","sourceRoot":"","sources":["../../src/components/decision-list.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ import type { RestEvent } from "../api.js";
3
+ /** What an event says, without its actor: the words after the name. */
4
+ export declare function describeEvent(event: RestEvent): string;
5
+ export interface EventFeedProps {
6
+ /** Oldest first, as the API hands them over; the feed shows them newest first. */
7
+ readonly events: readonly RestEvent[];
8
+ /** Where the line of an event leads, when it is about a task or a decision. */
9
+ readonly href?: ((event: RestEvent) => string | undefined) | undefined;
10
+ readonly empty?: ReactNode;
11
+ }
12
+ export declare function EventFeed(props: EventFeedProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=event-feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-feed.d.ts","sourceRoot":"","sources":["../../src/components/event-feed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAkB3C,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAgCtD;AAED,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BA4B9C"}
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PersonChip, STATE_LABELS, Time } from "./ui.js";
3
+ // The feed: one line per event, newest first, as a sentence a person reads at a glance. It
4
+ // takes its data as props and nothing from the network.
5
+ const FIELD_WORDS = {
6
+ title: "the title",
7
+ body: "the body",
8
+ priority: "the priority",
9
+ assigneeId: "the assignee",
10
+ parentId: "what it is part of",
11
+ links: "the links",
12
+ };
13
+ /** "(as Claude Code)": what an agent did is said with what the agent calls itself. */
14
+ const as = (agent) => (agent === undefined ? "" : ` (as ${agent})`);
15
+ /** What an event says, without its actor: the words after the name. */
16
+ export function describeEvent(event) {
17
+ const { data } = event;
18
+ const task = data.number === undefined
19
+ ? "a task"
20
+ : `#${data.number}${data.title === undefined ? "" : ` ${data.title}`}`;
21
+ switch (event.kind) {
22
+ case "person.joined":
23
+ return "joined the board";
24
+ case "person.role_changed":
25
+ return `made ${data.login ?? "someone"} ${data.role === "admin" ? "an administrator" : "a member"}`;
26
+ case "task.created":
27
+ return `wrote ${task}`;
28
+ case "task.moved":
29
+ return `moved ${task} from ${STATE_LABELS[data.from ?? "idea"]} to ${STATE_LABELS[data.to ?? "idea"]}`;
30
+ case "task.updated": {
31
+ const fields = (data.fields ?? []).map((field) => FIELD_WORDS[field] ?? field);
32
+ return `changed ${fields.length === 0 ? "something" : fields.join(", ")} of ${task}`;
33
+ }
34
+ case "decision.raised":
35
+ return `asked${as(data.agent)}: ${data.question ?? "a question"}`;
36
+ case "decision.answered":
37
+ return `answered "${data.question ?? "a question"}": ${data.option ?? ""}`;
38
+ case "run.started":
39
+ return `started on ${task}${as(data.agent)}`;
40
+ case "run.reported":
41
+ return `reported on ${task}${as(data.agent)}${data.excerpt === undefined ? "" : `: ${data.excerpt}`}`;
42
+ case "run.handed_in":
43
+ return `handed in ${data.label ?? "something"} on ${task}${as(data.agent)}`;
44
+ case "run.ended":
45
+ return `${data.status === "finished" ? "finished" : data.status === "failed" ? "failed on" : "gave up on"} ${task}${as(data.agent)}`;
46
+ }
47
+ }
48
+ export function EventFeed(props) {
49
+ if (props.events.length === 0) {
50
+ return _jsx("div", { className: "sc-feed", children: props.empty ?? null });
51
+ }
52
+ const newestFirst = [...props.events].reverse();
53
+ return (_jsx("ol", { className: "sc-feed", "aria-label": "What happened", children: newestFirst.map((event) => {
54
+ const href = props.href?.(event);
55
+ const words = describeEvent(event);
56
+ return (_jsxs("li", { className: "sc-feed-item", children: [_jsx("span", { className: "sc-feed-actor", children: event.actor === null ? (_jsx("span", { className: "sc-person-login", children: "The console" })) : (_jsx(PersonChip, { person: event.actor })) }), _jsx("span", { className: "sc-feed-words", children: href === undefined ? words : _jsx("a", { href: href, children: words }) }), _jsx(Time, { iso: event.createdAt })] }, event.id));
57
+ }) }));
58
+ }
59
+ //# sourceMappingURL=event-feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-feed.js","sourceRoot":"","sources":["../../src/components/event-feed.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function Markdown(props: {
2
+ readonly source: string;
3
+ }): import("react").JSX.Element;
4
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/components/markdown.tsx"],"names":[],"mappings":"AAUA,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,+BA8C1D"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import ReactMarkdown from "react-markdown";
3
+ import remarkGfm from "remark-gfm";
4
+ // What people and agents write is untrusted. It is rendered as React elements, never as HTML:
5
+ // raw HTML in the source stays text, links are limited to a few schemes and open elsewhere,
6
+ // and pictures come over https only, lazily and without a referrer.
7
+ const SAFE_LINK = /^(https?:|mailto:)/i;
8
+ const SAFE_IMAGE = /^https:\/\//i;
9
+ export function Markdown(props) {
10
+ return (_jsx("div", { className: "sc-prose", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm],
11
+ // Everything passes through here unchanged; the components below decide what a URL may do.
12
+ urlTransform: (url) => url, components: {
13
+ a({ href, children }) {
14
+ if (href === undefined || href === "") {
15
+ return _jsx("span", { children: children });
16
+ }
17
+ if (href.startsWith("#")) {
18
+ return _jsx("a", { href: href, children: children });
19
+ }
20
+ if (SAFE_LINK.test(href)) {
21
+ return (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer nofollow ugc", children: children }));
22
+ }
23
+ return _jsx("span", { children: children });
24
+ },
25
+ img({ src, alt, title }) {
26
+ const url = typeof src === "string" && SAFE_IMAGE.test(src) ? src : undefined;
27
+ if (url === undefined) {
28
+ return _jsx("span", { className: "sc-prose-image-text", children: alt ?? "" });
29
+ }
30
+ return (_jsx("img", { src: url, alt: alt ?? "", title: title, loading: "lazy", decoding: "async", referrerPolicy: "no-referrer" }));
31
+ },
32
+ }, children: props.source }) }));
33
+ }
34
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/components/markdown.tsx"],"names":[],"mappings":";AAAA,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,8FAA8F;AAC9F,4FAA4F;AAC5F,oEAAoE;AAEpE,MAAM,SAAS,GAAG,qBAAqB,CAAC;AACxC,MAAM,UAAU,GAAG,cAAc,CAAC;AAElC,MAAM,UAAU,QAAQ,CAAC,KAAkC;IACzD,OAAO,CACL,cAAK,SAAS,EAAC,UAAU,YACvB,KAAC,aAAa,IACZ,aAAa,EAAE,CAAC,SAAS,CAAC;YAC1B,2FAA2F;YAC3F,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAC1B,UAAU,EAAE;gBACV,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAClB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;wBACtC,OAAO,yBAAO,QAAQ,GAAQ,CAAC;oBACjC,CAAC;oBACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;wBACzB,OAAO,YAAG,IAAI,EAAE,IAAI,YAAG,QAAQ,GAAK,CAAC;oBACvC,CAAC;oBACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACzB,OAAO,CACL,YAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,kCAAkC,YAClE,QAAQ,GACP,CACL,CAAC;oBACJ,CAAC;oBACD,OAAO,yBAAO,QAAQ,GAAQ,CAAC;gBACjC,CAAC;gBACD,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;oBACrB,MAAM,GAAG,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC9E,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;wBACtB,OAAO,eAAM,SAAS,EAAC,qBAAqB,YAAE,GAAG,IAAI,EAAE,GAAQ,CAAC;oBAClE,CAAC;oBACD,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,IAAI,EAAE,EACd,KAAK,EAAE,KAAK,EACZ,OAAO,EAAC,MAAM,EACd,QAAQ,EAAC,OAAO,EAChB,cAAc,EAAC,aAAa,GAC5B,CACH,CAAC;gBACJ,CAAC;aACF,YAEA,KAAK,CAAC,MAAM,GACC,GACZ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PersonRole, RestPerson } from "../api.js";
2
+ export interface PeopleListProps {
3
+ readonly people: readonly RestPerson[];
4
+ /** Whoever is looking, so that their own row says so. */
5
+ readonly me?: RestPerson | undefined;
6
+ /** Called with the role an administrator chose. Left out, roles are read here, not changed. */
7
+ readonly onChangeRole?: ((person: RestPerson, role: PersonRole) => void) | undefined;
8
+ readonly busy?: boolean | undefined;
9
+ }
10
+ export declare function PeopleList(props: PeopleListProps): import("react").JSX.Element;
11
+ //# sourceMappingURL=people.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"people.d.ts","sourceRoot":"","sources":["../../src/components/people.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAOxD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACrC,+FAA+F;IAC/F,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BAiChD"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PERSON_ROLES } from "../vocabulary.js";
3
+ import { PersonChip, ROLE_LABELS, RoleBadge } from "./ui.js";
4
+ export function PeopleList(props) {
5
+ return (_jsx("ul", { className: "sc-people", "aria-label": "People", children: props.people.map((person) => (_jsxs("li", { className: "sc-person-row", children: [_jsx(PersonChip, { person: person, size: "md" }), _jsxs("span", { className: "sc-person-name", children: [person.name ?? "", props.me?.id === person.id && _jsx("span", { className: "sc-muted", children: " (you)" })] }), props.onChangeRole === undefined ? (_jsx(RoleBadge, { role: person.role })) : (_jsxs("label", { className: "sc-field sc-field-inline", children: [_jsxs("span", { className: "sc-visually-hidden", children: ["Role of ", person.login] }), _jsx("select", { className: "sc-input", value: person.role, disabled: props.busy === true, onChange: (event) => props.onChangeRole?.(person, event.target.value), children: PERSON_ROLES.map((role) => (_jsx("option", { value: role, children: ROLE_LABELS[role] }, role))) })] }))] }, person.id))) }));
6
+ }
7
+ //# sourceMappingURL=people.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"people.js","sourceRoot":"","sources":["../../src/components/people.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAc7D,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,OAAO,CACL,aAAI,SAAS,EAAC,WAAW,gBAAY,QAAQ,YAC1C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC5B,cAAoB,SAAS,EAAC,eAAe,aAC3C,KAAC,UAAU,IAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAC,IAAI,GAAG,EACxC,gBAAM,SAAS,EAAC,gBAAgB,aAC7B,MAAM,CAAC,IAAI,IAAI,EAAE,EACjB,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,MAAM,CAAC,EAAE,IAAI,eAAM,SAAS,EAAC,UAAU,uBAAc,IAClE,EACN,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,CAClC,KAAC,SAAS,IAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAI,CACjC,CAAC,CAAC,CAAC,CACF,iBAAO,SAAS,EAAC,0BAA0B,aACzC,gBAAM,SAAS,EAAC,oBAAoB,yBAAU,MAAM,CAAC,KAAK,IAAQ,EAClE,iBACE,SAAS,EAAC,UAAU,EACpB,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,EAC7B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KAAmB,CAAC,YAElF,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC1B,iBAAmB,KAAK,EAAE,IAAI,YAC3B,WAAW,CAAC,IAAI,CAAC,IADP,IAAI,CAER,CACV,CAAC,GACK,IACH,CACT,KAxBM,MAAM,CAAC,EAAE,CAyBb,CACN,CAAC,GACC,CACN,CAAC;AACJ,CAAC"}