@kelpie/ui 0.13.0 → 0.15.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.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAA;AAE9C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,yDAAyD;AACzD,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;IAExC,YAAY,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,WAAW,EAAO,EAM9F;CACF;AAED,4DAA4D;AAC5D,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,CACpC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAC1E,CAAA;AAED,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CACzC;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7E;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACtC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACxF,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACpE;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACzE;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACrE;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AA+DD,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CA4GpE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAA;AAE9C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,yDAAyD;AACzD,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;IAExC,YAAY,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,WAAW,EAAO,EAM9F;CACF;AAED,4DAA4D;AAC5D,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,CACpC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAC1E,CAAA;AAED,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CACzC;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7E;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACtC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACxF,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACpE;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACzE;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACrE;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAsED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAgIpE"}
@@ -55,9 +55,15 @@ function buildUrl(baseUrl, path, query) {
55
55
  * Turns a failed response into an `ApiError`. A body that does not match the
56
56
  * documented error shape still produces an error carrying the HTTP status,
57
57
  * because the alternative is a rejected promise with no cause.
58
+ *
59
+ * `502`, `503` and `504` from a dev or reverse proxy mean the API itself is
60
+ * down, so they get a friendly `service_unreachable` code that `QueryState`
61
+ * turns into a plain sentence instead of "HTTP 504".
58
62
  */
59
63
  function readErrorBody(status, payload) {
60
- const unreadable = new ApiError(status, 'internal_error', `Unreadable error response (HTTP ${status})`);
64
+ const unreadable = status === 502 || status === 503 || status === 504
65
+ ? new ApiError(status, 'service_unreachable', 'The service is unreachable. Try again in a moment.')
66
+ : new ApiError(status, 'internal_error', `Unreadable error response (HTTP ${status})`);
61
67
  if (!isRecord(payload) || !isRecord(payload.error)) {
62
68
  return unreadable;
63
69
  }
@@ -78,7 +84,21 @@ function readPage(payload, decodeItem) {
78
84
  return { items: payload.data.map((item) => decodeItem(item)), nextCursor };
79
85
  }
80
86
  export function createApiClient(options) {
81
- const doFetch = options.fetch ?? globalThis.fetch.bind(globalThis);
87
+ const rawFetch = options.fetch ?? globalThis.fetch.bind(globalThis);
88
+ /**
89
+ * A fetch that turns a rejection into an `ApiError`. `fetch` rejects only
90
+ * when the network layer failed (DNS, connection refused, offline), and the
91
+ * raw rejection is a `TypeError` whose message is either "Failed to fetch"
92
+ * or "Load failed" depending on the browser. Neither belongs in the UI.
93
+ */
94
+ async function doFetch(url, init) {
95
+ try {
96
+ return await rawFetch(url, init);
97
+ }
98
+ catch {
99
+ throw new ApiError(0, 'service_unreachable', 'The service is unreachable. Check that the API is running.');
100
+ }
101
+ }
82
102
  function headersFor(body) {
83
103
  return body === undefined
84
104
  ? { Accept: 'application/json' }
@@ -95,13 +115,20 @@ export function createApiClient(options) {
95
115
  ...(body === undefined ? {} : { body: JSON.stringify(body) }),
96
116
  });
97
117
  }
98
- /** Reads a JSON response, converting any non-2xx into an `ApiError`. */
118
+ /**
119
+ * Reads a JSON response, converting any non-2xx into an `ApiError`.
120
+ *
121
+ * The body is parsed defensively on failure: a dev proxy answering `504` with
122
+ * an empty body, or a reverse proxy answering `502` with an HTML page, would
123
+ * otherwise throw `SyntaxError: Unexpected end of JSON input` and hide the
124
+ * status that explains the failure.
125
+ */
99
126
  async function readJson(response) {
100
- const payload = await response.json();
101
127
  if (!response.ok) {
128
+ const payload = await response.json().catch(() => null);
102
129
  throw readErrorBody(response.status, payload);
103
130
  }
104
- return payload;
131
+ return response.json();
105
132
  }
106
133
  async function send(method, url, decode, body) {
107
134
  return decode(await readJson(await request(method, url, body)));
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -24,7 +24,13 @@ export function ErrorPanel({ error, onRetry }) {
24
24
  }
25
25
  function describe(error) {
26
26
  if (!(error instanceof ApiError)) {
27
- return `Could not reach the service. ${error.message}`;
27
+ // A non-`ApiError` here is a decoder throwing on an unexpected shape, or a
28
+ // programmer error. Neither is actionable, so name the class of failure and
29
+ // keep the raw message out of the UI.
30
+ return 'The response could not be read. Reload the page, or check the service logs.';
31
+ }
32
+ if (error.code === 'service_unreachable') {
33
+ return error.message;
28
34
  }
29
35
  if (error.status === 403) {
30
36
  return 'This workspace is not available to your account.';
@@ -1 +1 @@
1
- {"version":3,"file":"QueryState.js","sourceRoot":"","sources":["../../src/components/QueryState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C;;;GAGG;AAEH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,GAAG,UAAU,EAA+B;IAC9E,OAAO,CACL,cAAK,SAAS,EAAC,mEAAmE,YAAE,KAAK,GAAO,CACjG,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,MAAM,GAIP;IACC,OAAO,CACL,eAAK,SAAS,EAAC,mBAAmB,aAChC,aAAG,SAAS,EAAC,kCAAkC,aAAE,KAAK,kBAAe,EACrE,KAAC,IAAI,IAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAC,2CAA2C,wBAEhE,IACH,CACP,CAAA;AACH,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAmB;IAC5D,MAAM,OAAO,GAAG,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAE9D,OAAO,CACL,eAAK,SAAS,EAAC,6DAA6D,aAC1E,YAAG,SAAS,EAAC,qCAAqC,YAAE,QAAQ,CAAC,KAAK,CAAC,GAAK,EACvE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CACrB,aAAI,SAAS,EAAC,kBAAkB,YAC7B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,cAA8C,SAAS,EAAC,yBAAyB,aAC/E,eAAM,SAAS,EAAC,WAAW,YAAE,MAAM,CAAC,KAAK,GAAQ,QAAG,MAAM,CAAC,OAAO,KAD3D,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAEvC,CACN,CAAC,GACC,CACN,EACA,OAAO,KAAK,SAAS,IAAI,CACxB,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,uHAAuH,0BAG1H,CACV,IACG,CACP,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,gCAAgC,KAAK,CAAC,OAAO,EAAE,CAAA;IACxD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzB,OAAO,kDAAkD,CAAA;IAC3D,CAAC;IAED,OAAO,KAAK,CAAC,OAAO,CAAA;AACtB,CAAC"}
1
+ {"version":3,"file":"QueryState.js","sourceRoot":"","sources":["../../src/components/QueryState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C;;;GAGG;AAEH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,GAAG,UAAU,EAA+B;IAC9E,OAAO,CACL,cAAK,SAAS,EAAC,mEAAmE,YAAE,KAAK,GAAO,CACjG,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,MAAM,GAIP;IACC,OAAO,CACL,eAAK,SAAS,EAAC,mBAAmB,aAChC,aAAG,SAAS,EAAC,kCAAkC,aAAE,KAAK,kBAAe,EACrE,KAAC,IAAI,IAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAC,2CAA2C,wBAEhE,IACH,CACP,CAAA;AACH,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAmB;IAC5D,MAAM,OAAO,GAAG,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAE9D,OAAO,CACL,eAAK,SAAS,EAAC,6DAA6D,aAC1E,YAAG,SAAS,EAAC,qCAAqC,YAAE,QAAQ,CAAC,KAAK,CAAC,GAAK,EACvE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CACrB,aAAI,SAAS,EAAC,kBAAkB,YAC7B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,cAA8C,SAAS,EAAC,yBAAyB,aAC/E,eAAM,SAAS,EAAC,WAAW,YAAE,MAAM,CAAC,KAAK,GAAQ,QAAG,MAAM,CAAC,OAAO,KAD3D,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAEvC,CACN,CAAC,GACC,CACN,EACA,OAAO,KAAK,SAAS,IAAI,CACxB,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,uHAAuH,0BAG1H,CACV,IACG,CACP,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,EAAE,CAAC;QACjC,2EAA2E;QAC3E,4EAA4E;QAC5E,sCAAsC;QACtC,OAAO,6EAA6E,CAAA;IACtF,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC,OAAO,CAAA;IACtB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzB,OAAO,kDAAkD,CAAA;IAC3D,CAAC;IAED,OAAO,KAAK,CAAC,OAAO,CAAA;AACtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardPage.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/DashboardPage.tsx"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AAEH,wBAAgB,aAAa,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CA+BjD"}
1
+ {"version":3,"file":"DashboardPage.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/DashboardPage.tsx"],"names":[],"mappings":"AAcA;;;;;;;GAOG;AAEH,wBAAgB,aAAa,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAyDjD"}
@@ -1,4 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useNavigate } from 'react-router';
2
4
  import { useTimezone } from '../../api/resources/account.js';
3
5
  import { useDashboard } from '../../api/resources/dashboard.js';
4
6
  import { useMembers } from '../../api/resources/members.js';
@@ -21,8 +23,19 @@ export function DashboardPage() {
21
23
  const { workspace } = useWorkspace();
22
24
  const { nameById } = useMembers();
23
25
  const timezone = useTimezone();
26
+ const navigate = useNavigate();
27
+ const [query, setQuery] = useState('');
24
28
  const workspaceName = workspace?.name ?? 'This workspace';
25
- return (_jsxs("div", { className: "animate-fade-in", children: [_jsx(PageHeader, { title: "Dashboard", description: "What needs attention across this workspace.", actions: workspace?.id !== undefined ? (_jsx(AgentTasks, { targetType: "workspace", targetId: workspace.id, targetLabel: workspaceName })) : undefined }), error !== null && _jsx(ErrorPanel, { error: error }), isLoading && _jsx(LoadingPanel, { label: "Loading the workspace\u2026" }), dashboard !== undefined && (_jsx(DashboardBody, { dashboard: dashboard, nameById: nameById, timezone: timezone }))] }));
29
+ return (_jsxs("div", { className: "animate-fade-in", children: [_jsx(PageHeader, { title: "Dashboard", description: "What needs attention across this workspace.", actions: workspace?.id !== undefined ? (_jsx(AgentTasks, { targetType: "workspace", targetId: workspace.id, targetLabel: workspaceName })) : undefined }), _jsx("form", { className: "mb-6", onSubmit: (event) => {
30
+ event.preventDefault();
31
+ const term = query.trim();
32
+ if (term.length === 0) {
33
+ return;
34
+ }
35
+ void navigate(`/search?q=${encodeURIComponent(term)}`);
36
+ }, children: _jsx("input", { value: query, onChange: (event) => {
37
+ setQuery(event.target.value);
38
+ }, "aria-label": "Search", placeholder: "Search\u2026", className: "w-full max-w-xl rounded-md border border-transparent bg-surface-sunken px-3 py-2 text-[15px] text-ink outline-none transition placeholder:text-ink-faint focus:border-border focus:bg-surface-raised" }) }), error !== null && _jsx(ErrorPanel, { error: error }), isLoading && _jsx(LoadingPanel, { label: "Loading the workspace\u2026" }), dashboard !== undefined && (_jsx(DashboardBody, { dashboard: dashboard, nameById: nameById, timezone: timezone }))] }));
26
39
  }
27
40
  function DashboardBody({ dashboard, nameById, timezone, }) {
28
41
  // `generatedAt` rather than a fresh `new Date()`: every relative time on the
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardPage.js","sourceRoot":"","sources":["../../../src/pages/dashboard/DashboardPage.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAiC,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAiC,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gCAAiC,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAgB,CAAA;AAEtF;;;;;;;GAOG;AAEH,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAA;IACtD,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAA;IACpC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,aAAa,GAAG,SAAS,EAAE,IAAI,IAAI,gBAAgB,CAAA;IAEzD,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,UAAU,IACT,KAAK,EAAC,WAAW,EACjB,WAAW,EAAC,6CAA6C,EACzD,OAAO,EACL,SAAS,EAAE,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAC5B,KAAC,UAAU,IACT,UAAU,EAAC,WAAW,EACtB,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,WAAW,EAAE,aAAa,GAC1B,CACH,CAAC,CAAC,CAAC,SAAS,GAEf,EAED,KAAK,KAAK,IAAI,IAAI,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAC9C,SAAS,IAAI,KAAC,YAAY,IAAC,KAAK,EAAC,6BAAwB,GAAG,EAE5D,SAAS,KAAK,SAAS,IAAI,CAC1B,KAAC,aAAa,IAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAChF,IACG,CACP,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAQ,GAKT;IACC,6EAA6E;IAC7E,6EAA6E;IAC7E,sEAAsE;IACtE,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAA;IAEjC,OAAO,CACL,0BACE,eAAK,SAAS,EAAC,gCAAgC,aAC7C,KAAC,aAAa,IAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,GAAI,EACjD,KAAC,YAAY,IACX,UAAU,EAAE,SAAS,CAAC,cAAc,EACpC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GAClB,IACE,EACN,eAAK,SAAS,EAAC,2BAA2B,aACxC,KAAC,SAAS,IAAC,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAI,EAC7F,KAAC,aAAa,IAAC,SAAS,EAAE,SAAS,CAAC,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,IAC3F,IACF,CACP,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"DashboardPage.js","sourceRoot":"","sources":["../../../src/pages/dashboard/DashboardPage.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAiC,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAiC,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gCAAiC,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAgB,CAAA;AAEtF;;;;;;;GAOG;AAEH,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAA;IACtD,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAA;IACpC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAA;IACjC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACtC,MAAM,aAAa,GAAG,SAAS,EAAE,IAAI,IAAI,gBAAgB,CAAA;IAEzD,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,UAAU,IACT,KAAK,EAAC,WAAW,EACjB,WAAW,EAAC,6CAA6C,EACzD,OAAO,EACL,SAAS,EAAE,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAC5B,KAAC,UAAU,IACT,UAAU,EAAC,WAAW,EACtB,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,WAAW,EAAE,aAAa,GAC1B,CACH,CAAC,CAAC,CAAC,SAAS,GAEf,EAEF,eACE,SAAS,EAAC,MAAM,EAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;oBAClB,KAAK,CAAC,cAAc,EAAE,CAAA;oBACtB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;oBAEzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACtB,OAAM;oBACR,CAAC;oBAED,KAAK,QAAQ,CAAC,aAAa,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACxD,CAAC,YAED,gBACE,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;wBAClB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;oBAC9B,CAAC,gBACU,QAAQ,EACnB,WAAW,EAAC,cAAS,EACrB,SAAS,EAAC,sMAAsM,GAChN,GACG,EAEN,KAAK,KAAK,IAAI,IAAI,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAC9C,SAAS,IAAI,KAAC,YAAY,IAAC,KAAK,EAAC,6BAAwB,GAAG,EAE5D,SAAS,KAAK,SAAS,IAAI,CAC1B,KAAC,aAAa,IAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAChF,IACG,CACP,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAQ,GAKT;IACC,6EAA6E;IAC7E,6EAA6E;IAC7E,sEAAsE;IACtE,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAA;IAEjC,OAAO,CACL,0BACE,eAAK,SAAS,EAAC,gCAAgC,aAC7C,KAAC,aAAa,IAAC,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,GAAI,EACjD,KAAC,YAAY,IACX,UAAU,EAAE,SAAS,CAAC,cAAc,EACpC,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,QAAQ,GAClB,IACE,EACN,eAAK,SAAS,EAAC,2BAA2B,aACxC,KAAC,SAAS,IAAC,KAAK,EAAE,SAAS,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAI,EAC7F,KAAC,aAAa,IAAC,SAAS,EAAE,SAAS,CAAC,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,IAC3F,IACF,CACP,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/sections.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AASxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAyDlD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkCrG;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,QAAQ,EACR,GAAG,EACH,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACjD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAqDpB;AAiBD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,GAAG,EACH,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAiCpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAChD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuCpB"}
1
+ {"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/sections.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EAEd,MAAM,iBAAiB,CAAA;AASxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAiFlD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkCrG;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,QAAQ,EACR,GAAG,EACH,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACjD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAqDpB;AAiBD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,GAAG,EACH,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAiCpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAChD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuCpB"}
@@ -36,11 +36,19 @@ function TargetLink({ target, className = 'text-ink-muted hover:text-accent hove
36
36
  function EmptyOr({ isEmpty, empty, children, }) {
37
37
  return isEmpty ? _jsx("p", { className: "text-[13px] text-ink-faint", children: empty }) : _jsx(_Fragment, { children: children });
38
38
  }
39
+ /** Shared inner-list chrome: row rules only — the well is the outer edge. */
40
+ const LIST_DIVIDE = 'divide-y divide-border';
41
+ function SectionWell({ children, tone = 'raised', }) {
42
+ if (tone === 'attention') {
43
+ return (_jsxs("section", { className: "relative overflow-hidden rounded-md border border-border bg-surface-sunken p-4 pl-5", children: [_jsx("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 w-[3px] bg-danger" }), children] }));
44
+ }
45
+ return (_jsx("section", { className: "rounded-md border border-border bg-surface-raised p-4", children: children }));
46
+ }
39
47
  export function AttentionList({ rows }) {
40
- return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Needs attention", description: "Overdue Plans, partnership touchpoints, and contacts going cold." }), _jsx(EmptyOr, { isEmpty: rows.length === 0, empty: "Nothing urgent right now.", children: _jsx("ul", { className: "divide-y divide-border border-y border-border", children: rows.map((row) => (_jsxs("li", { className: "py-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Chip, { tone: row.tone, children: row.label }), _jsx("span", { className: "text-[11px] text-ink-faint", children: row.meta })] }), row.href === undefined ? (_jsx("p", { className: "mt-1.5 text-[13px] font-medium text-ink", children: row.title })) : (_jsx(Link, { to: row.href, className: "mt-1.5 block text-[13px] font-medium text-ink hover:text-accent", children: row.title })), row.detail !== '' && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-[12px] text-ink-muted", children: row.detail }))] }, row.id))) }) })] }));
48
+ return (_jsxs(SectionWell, { tone: "attention", children: [_jsx(SectionHeader, { title: "Needs attention", description: "Overdue Plans, partnership touchpoints, and contacts going cold." }), _jsx(EmptyOr, { isEmpty: rows.length === 0, empty: "Nothing urgent right now.", children: _jsx("ul", { className: LIST_DIVIDE, children: rows.map((row) => (_jsxs("li", { className: "py-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Chip, { tone: row.tone, children: row.label }), _jsx("span", { className: "text-[11px] text-ink-faint", children: row.meta })] }), row.href === undefined ? (_jsx("p", { className: "mt-1.5 text-[13px] font-medium text-ink", children: row.title })) : (_jsx(Link, { to: row.href, className: "mt-1.5 block text-[13px] font-medium text-ink hover:text-accent", children: row.title })), row.detail !== '' && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-[12px] text-ink-muted", children: row.detail }))] }, row.id))) }) })] }));
41
49
  }
42
50
  export function ActivityFeed({ activities, nameById, now, timezone, }) {
43
- return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Recent activity", description: "The latest events across people, companies, and pipelines." }), _jsx(EmptyOr, { isEmpty: activities.length === 0, empty: "No activity yet.", children: _jsx("ol", { className: "divide-y divide-border border-y border-border", children: activities.map((activity, index) => (_jsxs("li", { className: "flex gap-2 py-3", children: [_jsxs("div", { className: "relative flex w-5 shrink-0 justify-center", children: [index < activities.length - 1 && (_jsx("span", { "aria-hidden": true, className: "absolute top-5 bottom-[-12px] left-1/2 w-px -translate-x-1/2 bg-border" })), _jsx("div", { className: "relative z-10 flex h-5 w-5 items-center justify-center rounded border border-border bg-surface text-[9px] font-medium tracking-wide text-ink-muted uppercase", title: activity.kind, children: KIND_GLYPHS[activity.kind] })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsxs("p", { className: "min-w-0 text-[12px] leading-snug text-ink", children: [_jsx("span", { className: "font-semibold", children: actorNameFor(activity, nameById) }), ' ', _jsx("span", { className: "text-ink-muted", children: activity.action })] }), _jsx("time", { dateTime: activity.createdAt.toISOString(), className: "shrink-0 text-[11px] text-ink-faint", children: formatRelativeTime(activity.createdAt, timezone, now) })] }), _jsxs("p", { className: "text-[11px] leading-snug text-ink-faint", children: ["on ", _jsx("span", { className: "text-ink-muted", children: targetTypeLabel(activity.targetType) }), ' · ', _jsx(TargetLink, { target: activity })] }), activity.detail !== null && (_jsx("p", { className: "text-[11px] leading-snug text-ink-faint", children: activity.detail }))] })] }, activity.id))) }) })] }));
51
+ return (_jsxs(SectionWell, { children: [_jsx(SectionHeader, { title: "Recent activity", description: "The latest events across people, companies, and pipelines." }), _jsx(EmptyOr, { isEmpty: activities.length === 0, empty: "No activity yet.", children: _jsx("ol", { className: LIST_DIVIDE, children: activities.map((activity, index) => (_jsxs("li", { className: "flex gap-2 py-3", children: [_jsxs("div", { className: "relative flex w-5 shrink-0 justify-center", children: [index < activities.length - 1 && (_jsx("span", { "aria-hidden": true, className: "absolute top-5 bottom-[-12px] left-1/2 w-px -translate-x-1/2 bg-border" })), _jsx("div", { className: "relative z-10 flex h-5 w-5 items-center justify-center rounded border border-border bg-surface text-[9px] font-medium tracking-wide text-ink-muted uppercase", title: activity.kind, children: KIND_GLYPHS[activity.kind] })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsxs("p", { className: "min-w-0 text-[12px] leading-snug text-ink", children: [_jsx("span", { className: "font-semibold", children: actorNameFor(activity, nameById) }), ' ', _jsx("span", { className: "text-ink-muted", children: activity.action })] }), _jsx("time", { dateTime: activity.createdAt.toISOString(), className: "shrink-0 text-[11px] text-ink-faint", children: formatRelativeTime(activity.createdAt, timezone, now) })] }), _jsxs("p", { className: "text-[11px] leading-snug text-ink-faint", children: ["on ", _jsx("span", { className: "text-ink-muted", children: targetTypeLabel(activity.targetType) }), ' · ', _jsx(TargetLink, { target: activity })] }), activity.detail !== null && (_jsx("p", { className: "text-[11px] leading-snug text-ink-faint", children: activity.detail }))] })] }, activity.id))) }) })] }));
44
52
  }
45
53
  /**
46
54
  * Exactly one of the two actor columns is set. `actorLabel` carries the display
@@ -53,9 +61,9 @@ function actorNameFor(activity, nameById) {
53
61
  return nameById.get(activity.actorMemberId) ?? 'Unknown';
54
62
  }
55
63
  export function NotesList({ notes, nameById, now, timezone, }) {
56
- return (_jsxs("section", { children: [_jsx(SectionHeader, { title: "Recent notes", description: "Pinned notes surface first." }), _jsx(EmptyOr, { isEmpty: notes.length === 0, empty: "No notes yet.", children: _jsx("ul", { className: "divide-y divide-border border-y border-border", children: notes.map((note) => (_jsxs("li", { className: "py-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("div", { className: "line-clamp-3 min-w-0 flex-1", children: _jsx(MarkdownView, { source: note.body }) }), note.pinned && (_jsx("span", { className: "shrink-0 text-[10px] font-medium tracking-wide text-accent uppercase", children: "Pinned" }))] }), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-ink-faint", children: [_jsx(TargetLink, { target: note }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: targetTypeLabel(note.targetType) }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: note.authorId === null ? 'System' : (nameById.get(note.authorId) ?? 'Unknown') }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: formatRelativeTime(note.createdAt, timezone, now) })] })] }, note.id))) }) })] }));
64
+ return (_jsxs(SectionWell, { children: [_jsx(SectionHeader, { title: "Recent notes", description: "Pinned notes surface first." }), _jsx(EmptyOr, { isEmpty: notes.length === 0, empty: "No notes yet.", children: _jsx("ul", { className: LIST_DIVIDE, children: notes.map((note) => (_jsxs("li", { className: "py-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsx("div", { className: "line-clamp-3 min-w-0 flex-1", children: _jsx(MarkdownView, { source: note.body }) }), note.pinned && (_jsx("span", { className: "shrink-0 text-[10px] font-medium tracking-wide text-accent uppercase", children: "Pinned" }))] }), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-ink-faint", children: [_jsx(TargetLink, { target: note }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: targetTypeLabel(note.targetType) }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: note.authorId === null ? 'System' : (nameById.get(note.authorId) ?? 'Unknown') }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: formatRelativeTime(note.createdAt, timezone, now) })] })] }, note.id))) }) })] }));
57
65
  }
58
66
  export function DecisionsList({ decisions, nameById, timezone, }) {
59
- return (_jsxs("section", { children: [_jsxs("div", { className: "mb-3 flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "text-[13px] font-semibold text-ink", children: "Recent decisions" }), _jsx("p", { className: "mt-0.5 text-[11px] text-ink-faint", children: "Commitments agents should not contradict." })] }), _jsx(Link, { to: "/decisions", className: "shrink-0 text-[12px] font-medium text-accent hover:underline", children: "View all" })] }), _jsx(EmptyOr, { isEmpty: decisions.length === 0, empty: "No decisions yet.", children: _jsx("ul", { className: "divide-y divide-border border-y border-border", children: decisions.map((decision) => (_jsxs("li", { className: "py-3", children: [_jsx("p", { className: "text-[13px] font-medium text-ink", children: decision.body }), decision.rationale !== null && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-[12px] text-ink-muted", children: decision.rationale })), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-ink-faint", children: [_jsx(TargetLink, { target: decision }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: formatDate(decision.decidedAt, timezone) }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: decision.ownerId === null ? '—' : (nameById.get(decision.ownerId) ?? 'Unknown') })] })] }, decision.id))) }) })] }));
67
+ return (_jsxs(SectionWell, { children: [_jsxs("div", { className: "mb-3 flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h2", { className: "text-[13px] font-semibold text-ink", children: "Recent decisions" }), _jsx("p", { className: "mt-0.5 text-[11px] text-ink-faint", children: "Commitments agents should not contradict." })] }), _jsx(Link, { to: "/decisions", className: "shrink-0 text-[12px] font-medium text-accent hover:underline", children: "View all" })] }), _jsx(EmptyOr, { isEmpty: decisions.length === 0, empty: "No decisions yet.", children: _jsx("ul", { className: LIST_DIVIDE, children: decisions.map((decision) => (_jsxs("li", { className: "py-3", children: [_jsx("p", { className: "text-[13px] font-medium text-ink", children: decision.body }), decision.rationale !== null && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-[12px] text-ink-muted", children: decision.rationale })), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-ink-faint", children: [_jsx(TargetLink, { target: decision }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: formatDate(decision.decidedAt, timezone) }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: decision.ownerId === null ? '—' : (nameById.get(decision.ownerId) ?? 'Unknown') })] })] }, decision.id))) }) })] }));
60
68
  }
61
69
  //# sourceMappingURL=sections.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sections.js","sourceRoot":"","sources":["../../../src/pages/dashboard/sections.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sections.js","sourceRoot":"","sources":["../../../src/pages/dashboard/sections.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAEnC,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA2B,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAmC,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAoC,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAG5D;;;;;;GAMG;AAEH,wEAAwE;AACxE,MAAM,WAAW,GAA2C;IAC1D,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,IAAI;CACf,CAAA;AAED,kFAAkF;AAClF,SAAS,UAAU,CAAC,EAClB,MAAM,EACN,SAAS,GAAG,kDAAkD,GAI/D;IACC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAErE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,eAAM,SAAS,EAAE,SAAS,YAAG,KAAK,GAAQ,CAAA;IACnD,CAAC;IAED,OAAO,CACL,KAAC,IAAI,IAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,YACjC,KAAK,GACD,CACR,CAAA;AACH,CAAC;AAED,SAAS,OAAO,CAAC,EACf,OAAO,EACP,KAAK,EACL,QAAQ,GAKT;IACC,OAAO,OAAO,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,4BAA4B,YAAE,KAAK,GAAK,CAAC,CAAC,CAAC,4BAAG,QAAQ,GAAI,CAAA;AAC1F,CAAC;AAED,6EAA6E;AAC7E,MAAM,WAAW,GAAG,wBAAwB,CAAA;AAE5C,SAAS,WAAW,CAAC,EACnB,QAAQ,EACR,IAAI,GAAG,QAAQ,GAIhB;IACC,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO,CACL,mBAAS,SAAS,EAAC,qFAAqF,aACtG,oCAAkB,SAAS,EAAC,6CAA6C,GAAG,EAC3E,QAAQ,IACD,CACX,CAAA;IACH,CAAC;IAED,OAAO,CACL,kBAAS,SAAS,EAAC,uDAAuD,YAAE,QAAQ,GAAW,CAChG,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAA8C;IAChF,OAAO,CACL,MAAC,WAAW,IAAC,IAAI,EAAC,WAAW,aAC3B,KAAC,aAAa,IACZ,KAAK,EAAC,iBAAiB,EACvB,WAAW,EAAC,kEAAkE,GAC9E,EACF,KAAC,OAAO,IAAC,OAAO,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAC,2BAA2B,YACpE,aAAI,SAAS,EAAE,WAAW,YACvB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,cAAiB,SAAS,EAAC,MAAM,aAC/B,eAAK,SAAS,EAAC,mCAAmC,aAChD,KAAC,IAAI,IAAC,IAAI,EAAE,GAAG,CAAC,IAAI,YAAG,GAAG,CAAC,KAAK,GAAQ,EACxC,eAAM,SAAS,EAAC,4BAA4B,YAAE,GAAG,CAAC,IAAI,GAAQ,IAC1D,EACL,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACxB,YAAG,SAAS,EAAC,yCAAyC,YAAE,GAAG,CAAC,KAAK,GAAK,CACvE,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,IACH,EAAE,EAAE,GAAG,CAAC,IAAI,EACZ,SAAS,EAAC,iEAAiE,YAE1E,GAAG,CAAC,KAAK,GACL,CACR,EACA,GAAG,CAAC,MAAM,KAAK,EAAE,IAAI,CACpB,YAAG,SAAS,EAAC,gDAAgD,YAAE,GAAG,CAAC,MAAM,GAAK,CAC/E,KAjBM,GAAG,CAAC,EAAE,CAkBV,CACN,CAAC,GACC,GACG,IACE,CACf,CAAA;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAC3B,UAAU,EACV,QAAQ,EACR,GAAG,EACH,QAAQ,GAMT;IACC,OAAO,CACL,MAAC,WAAW,eACV,KAAC,aAAa,IACZ,KAAK,EAAC,iBAAiB,EACvB,WAAW,EAAC,4DAA4D,GACxE,EACF,KAAC,OAAO,IAAC,OAAO,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAC,kBAAkB,YACjE,aAAI,SAAS,EAAE,WAAW,YACvB,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CACnC,cAAsB,SAAS,EAAC,iBAAiB,aAC/C,eAAK,SAAS,EAAC,2CAA2C,aACvD,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAChC,oCAEE,SAAS,EAAC,wEAAwE,GAClF,CACH,EACD,cACE,SAAS,EAAC,8JAA8J,EACxK,KAAK,EAAE,QAAQ,CAAC,IAAI,YAEnB,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,GACvB,IACF,EACN,eAAK,SAAS,EAAC,gBAAgB,aAC7B,eAAK,SAAS,EAAC,2CAA2C,aACxD,aAAG,SAAS,EAAC,2CAA2C,aACtD,eAAM,SAAS,EAAC,eAAe,YAAE,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAQ,EAAC,GAAG,EAC7E,eAAM,SAAS,EAAC,gBAAgB,YAAE,QAAQ,CAAC,MAAM,GAAQ,IACvD,EACJ,eACE,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,EAC1C,SAAS,EAAC,qCAAqC,YAE9C,kBAAkB,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,GACjD,IACH,EACN,aAAG,SAAS,EAAC,yCAAyC,oBACjD,eAAM,SAAS,EAAC,gBAAgB,YAAE,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAQ,EAChF,KAAK,EACN,KAAC,UAAU,IAAC,MAAM,EAAE,QAAQ,GAAI,IAC9B,EACH,QAAQ,CAAC,MAAM,KAAK,IAAI,IAAI,CAC3B,YAAG,SAAS,EAAC,yCAAyC,YAAE,QAAQ,CAAC,MAAM,GAAK,CAC7E,IACG,KApCC,QAAQ,CAAC,EAAE,CAqCf,CACN,CAAC,GACC,GACG,IACE,CACf,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CACnB,QAA2B,EAC3B,QAAqC;IAErC,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAA;IACxC,CAAC;IAED,OAAO,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,SAAS,CAAA;AAC1D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,GAAG,EACH,QAAQ,GAMT;IACC,OAAO,CACL,MAAC,WAAW,eACV,KAAC,aAAa,IAAC,KAAK,EAAC,cAAc,EAAC,WAAW,EAAC,6BAA6B,GAAG,EAChF,KAAC,OAAO,IAAC,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAC,eAAe,YACzD,aAAI,SAAS,EAAE,WAAW,YACvB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,cAAkB,SAAS,EAAC,MAAM,aAChC,eAAK,SAAS,EAAC,wCAAwC,aACrD,cAAK,SAAS,EAAC,6BAA6B,YAC1C,KAAC,YAAY,IAAC,MAAM,EAAE,IAAI,CAAC,IAAI,GAAI,GAC/B,EACL,IAAI,CAAC,MAAM,IAAI,CACd,eAAM,SAAS,EAAC,sEAAsE,uBAE/E,CACR,IACG,EACN,eAAK,SAAS,EAAC,mEAAmE,aAChF,KAAC,UAAU,IAAC,MAAM,EAAE,IAAI,GAAI,EAC5B,oCAAc,EACd,yBAAO,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,GAAQ,EAC/C,oCAAc,EACd,yBAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,GAAQ,EAC7F,oCAAc,EACd,yBAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAQ,IAC5D,KAnBC,IAAI,CAAC,EAAE,CAoBX,CACN,CAAC,GACC,GACG,IACE,CACf,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,QAAQ,GAKT;IACC,OAAO,CACL,MAAC,WAAW,eACV,eAAK,SAAS,EAAC,6CAA6C,aAC1D,eAAK,SAAS,EAAC,SAAS,aACtB,aAAI,SAAS,EAAC,oCAAoC,iCAAsB,EACxE,YAAG,SAAS,EAAC,mCAAmC,0DAE5C,IACA,EACN,KAAC,IAAI,IAAC,EAAE,EAAC,YAAY,EAAC,SAAS,EAAC,8DAA8D,yBAEvF,IACH,EACN,KAAC,OAAO,IAAC,OAAO,EAAE,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAC,mBAAmB,YACjE,aAAI,SAAS,EAAE,WAAW,YACvB,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC3B,cAAsB,SAAS,EAAC,MAAM,aACpC,YAAG,SAAS,EAAC,kCAAkC,YAAE,QAAQ,CAAC,IAAI,GAAK,EAClE,QAAQ,CAAC,SAAS,KAAK,IAAI,IAAI,CAC9B,YAAG,SAAS,EAAC,gDAAgD,YAC1D,QAAQ,CAAC,SAAS,GACjB,CACL,EACD,eAAK,SAAS,EAAC,mEAAmE,aAChF,KAAC,UAAU,IAAC,MAAM,EAAE,QAAQ,GAAI,EAChC,oCAAc,EACd,yBAAO,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAQ,EACvD,oCAAc,EACd,yBACG,QAAQ,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,GAC3E,IACH,KAfC,QAAQ,CAAC,EAAE,CAgBf,CACN,CAAC,GACC,GACG,IACE,CACf,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kelpie/ui",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "React UI for Kelpie: components, pages, API client, and the extension registry an assembly composes modules through.",
5
5
  "keywords": [
6
6
  "kelpie",
@@ -48,7 +48,7 @@
48
48
  "@dnd-kit/core": "^6.3.1",
49
49
  "@dnd-kit/sortable": "^10.0.0",
50
50
  "@dnd-kit/utilities": "^3.2.2",
51
- "@kelpie/schemas": "^0.13.0",
51
+ "@kelpie/schemas": "^0.15.0",
52
52
  "@tanstack/react-query": "^5.101.4",
53
53
  "react-markdown": "^10.1.0",
54
54
  "react-router": "^8.3.0",
package/src/api/client.ts CHANGED
@@ -128,9 +128,16 @@ function buildUrl(baseUrl: string, path: string, query: QueryParameters | undefi
128
128
  * Turns a failed response into an `ApiError`. A body that does not match the
129
129
  * documented error shape still produces an error carrying the HTTP status,
130
130
  * because the alternative is a rejected promise with no cause.
131
+ *
132
+ * `502`, `503` and `504` from a dev or reverse proxy mean the API itself is
133
+ * down, so they get a friendly `service_unreachable` code that `QueryState`
134
+ * turns into a plain sentence instead of "HTTP 504".
131
135
  */
132
136
  function readErrorBody(status: number, payload: unknown): ApiError {
133
- const unreadable = new ApiError(status, 'internal_error', `Unreadable error response (HTTP ${status})`)
137
+ const unreadable =
138
+ status === 502 || status === 503 || status === 504
139
+ ? new ApiError(status, 'service_unreachable', 'The service is unreachable. Try again in a moment.')
140
+ : new ApiError(status, 'internal_error', `Unreadable error response (HTTP ${status})`)
134
141
 
135
142
  if (!isRecord(payload) || !isRecord(payload.error)) {
136
143
  return unreadable
@@ -160,7 +167,21 @@ function readPage<T>(payload: unknown, decodeItem: Decoder<T>): Page<T> {
160
167
  }
161
168
 
162
169
  export function createApiClient(options: ApiClientOptions): ApiClient {
163
- const doFetch = options.fetch ?? globalThis.fetch.bind(globalThis)
170
+ const rawFetch = options.fetch ?? globalThis.fetch.bind(globalThis)
171
+
172
+ /**
173
+ * A fetch that turns a rejection into an `ApiError`. `fetch` rejects only
174
+ * when the network layer failed (DNS, connection refused, offline), and the
175
+ * raw rejection is a `TypeError` whose message is either "Failed to fetch"
176
+ * or "Load failed" depending on the browser. Neither belongs in the UI.
177
+ */
178
+ async function doFetch(url: string, init: RequestInit): Promise<Response> {
179
+ try {
180
+ return await rawFetch(url, init)
181
+ } catch {
182
+ throw new ApiError(0, 'service_unreachable', 'The service is unreachable. Check that the API is running.')
183
+ }
184
+ }
164
185
 
165
186
  function headersFor(body: unknown): Record<string, string> {
166
187
  return body === undefined
@@ -180,15 +201,21 @@ export function createApiClient(options: ApiClientOptions): ApiClient {
180
201
  })
181
202
  }
182
203
 
183
- /** Reads a JSON response, converting any non-2xx into an `ApiError`. */
204
+ /**
205
+ * Reads a JSON response, converting any non-2xx into an `ApiError`.
206
+ *
207
+ * The body is parsed defensively on failure: a dev proxy answering `504` with
208
+ * an empty body, or a reverse proxy answering `502` with an HTML page, would
209
+ * otherwise throw `SyntaxError: Unexpected end of JSON input` and hide the
210
+ * status that explains the failure.
211
+ */
184
212
  async function readJson(response: Response): Promise<unknown> {
185
- const payload: unknown = await response.json()
186
-
187
213
  if (!response.ok) {
214
+ const payload: unknown = await response.json().catch(() => null)
188
215
  throw readErrorBody(response.status, payload)
189
216
  }
190
217
 
191
- return payload
218
+ return response.json()
192
219
  }
193
220
 
194
221
  async function send<T>(method: string, url: string, decode: Decoder<T>, body?: unknown): Promise<T> {
@@ -72,7 +72,14 @@ export function ErrorPanel({ error, onRetry }: ErrorPanelProps): React.JSX.Eleme
72
72
 
73
73
  function describe(error: Error): string {
74
74
  if (!(error instanceof ApiError)) {
75
- return `Could not reach the service. ${error.message}`
75
+ // A non-`ApiError` here is a decoder throwing on an unexpected shape, or a
76
+ // programmer error. Neither is actionable, so name the class of failure and
77
+ // keep the raw message out of the UI.
78
+ return 'The response could not be read. Reload the page, or check the service logs.'
79
+ }
80
+
81
+ if (error.code === 'service_unreachable') {
82
+ return error.message
76
83
  }
77
84
 
78
85
  if (error.status === 403) {
@@ -1,4 +1,6 @@
1
1
  import type { Dashboard } from '@kelpie/schemas'
2
+ import { useState } from 'react'
3
+ import { useNavigate } from 'react-router'
2
4
 
3
5
  import { useTimezone } from '../../api/resources/account.ts'
4
6
  import { useDashboard } from '../../api/resources/dashboard.ts'
@@ -24,6 +26,8 @@ export function DashboardPage(): React.JSX.Element {
24
26
  const { workspace } = useWorkspace()
25
27
  const { nameById } = useMembers()
26
28
  const timezone = useTimezone()
29
+ const navigate = useNavigate()
30
+ const [query, setQuery] = useState('')
27
31
  const workspaceName = workspace?.name ?? 'This workspace'
28
32
 
29
33
  return (
@@ -42,6 +46,30 @@ export function DashboardPage(): React.JSX.Element {
42
46
  }
43
47
  />
44
48
 
49
+ <form
50
+ className="mb-6"
51
+ onSubmit={(event) => {
52
+ event.preventDefault()
53
+ const term = query.trim()
54
+
55
+ if (term.length === 0) {
56
+ return
57
+ }
58
+
59
+ void navigate(`/search?q=${encodeURIComponent(term)}`)
60
+ }}
61
+ >
62
+ <input
63
+ value={query}
64
+ onChange={(event) => {
65
+ setQuery(event.target.value)
66
+ }}
67
+ aria-label="Search"
68
+ placeholder="Search…"
69
+ className="w-full max-w-xl rounded-md border border-transparent bg-surface-sunken px-3 py-2 text-[15px] text-ink outline-none transition placeholder:text-ink-faint focus:border-border focus:bg-surface-raised"
70
+ />
71
+ </form>
72
+
45
73
  {error !== null && <ErrorPanel error={error} />}
46
74
  {isLoading && <LoadingPanel label="Loading the workspace…" />}
47
75
 
@@ -70,15 +70,39 @@ function EmptyOr({
70
70
  return isEmpty ? <p className="text-[13px] text-ink-faint">{empty}</p> : <>{children}</>
71
71
  }
72
72
 
73
+ /** Shared inner-list chrome: row rules only — the well is the outer edge. */
74
+ const LIST_DIVIDE = 'divide-y divide-border'
75
+
76
+ function SectionWell({
77
+ children,
78
+ tone = 'raised',
79
+ }: {
80
+ readonly children: ReactNode
81
+ readonly tone?: 'raised' | 'attention'
82
+ }): React.JSX.Element {
83
+ if (tone === 'attention') {
84
+ return (
85
+ <section className="relative overflow-hidden rounded-md border border-border bg-surface-sunken p-4 pl-5">
86
+ <span aria-hidden className="absolute inset-y-0 left-0 w-[3px] bg-danger" />
87
+ {children}
88
+ </section>
89
+ )
90
+ }
91
+
92
+ return (
93
+ <section className="rounded-md border border-border bg-surface-raised p-4">{children}</section>
94
+ )
95
+ }
96
+
73
97
  export function AttentionList({ rows }: { readonly rows: readonly AttentionRow[] }): React.JSX.Element {
74
98
  return (
75
- <section>
99
+ <SectionWell tone="attention">
76
100
  <SectionHeader
77
101
  title="Needs attention"
78
102
  description="Overdue Plans, partnership touchpoints, and contacts going cold."
79
103
  />
80
104
  <EmptyOr isEmpty={rows.length === 0} empty="Nothing urgent right now.">
81
- <ul className="divide-y divide-border border-y border-border">
105
+ <ul className={LIST_DIVIDE}>
82
106
  {rows.map((row) => (
83
107
  <li key={row.id} className="py-3">
84
108
  <div className="flex flex-wrap items-center gap-2">
@@ -102,7 +126,7 @@ export function AttentionList({ rows }: { readonly rows: readonly AttentionRow[]
102
126
  ))}
103
127
  </ul>
104
128
  </EmptyOr>
105
- </section>
129
+ </SectionWell>
106
130
  )
107
131
  }
108
132
 
@@ -118,13 +142,13 @@ export function ActivityFeed({
118
142
  readonly timezone: string
119
143
  }): React.JSX.Element {
120
144
  return (
121
- <section>
145
+ <SectionWell>
122
146
  <SectionHeader
123
147
  title="Recent activity"
124
148
  description="The latest events across people, companies, and pipelines."
125
149
  />
126
150
  <EmptyOr isEmpty={activities.length === 0} empty="No activity yet.">
127
- <ol className="divide-y divide-border border-y border-border">
151
+ <ol className={LIST_DIVIDE}>
128
152
  {activities.map((activity, index) => (
129
153
  <li key={activity.id} className="flex gap-2 py-3">
130
154
  <div className="relative flex w-5 shrink-0 justify-center">
@@ -167,7 +191,7 @@ export function ActivityFeed({
167
191
  ))}
168
192
  </ol>
169
193
  </EmptyOr>
170
- </section>
194
+ </SectionWell>
171
195
  )
172
196
  }
173
197
 
@@ -198,10 +222,10 @@ export function NotesList({
198
222
  readonly timezone: string
199
223
  }): React.JSX.Element {
200
224
  return (
201
- <section>
225
+ <SectionWell>
202
226
  <SectionHeader title="Recent notes" description="Pinned notes surface first." />
203
227
  <EmptyOr isEmpty={notes.length === 0} empty="No notes yet.">
204
- <ul className="divide-y divide-border border-y border-border">
228
+ <ul className={LIST_DIVIDE}>
205
229
  {notes.map((note) => (
206
230
  <li key={note.id} className="py-3">
207
231
  <div className="flex items-start justify-between gap-2">
@@ -227,7 +251,7 @@ export function NotesList({
227
251
  ))}
228
252
  </ul>
229
253
  </EmptyOr>
230
- </section>
254
+ </SectionWell>
231
255
  )
232
256
  }
233
257
 
@@ -241,7 +265,7 @@ export function DecisionsList({
241
265
  readonly timezone: string
242
266
  }): React.JSX.Element {
243
267
  return (
244
- <section>
268
+ <SectionWell>
245
269
  <div className="mb-3 flex items-start justify-between gap-2">
246
270
  <div className="min-w-0">
247
271
  <h2 className="text-[13px] font-semibold text-ink">Recent decisions</h2>
@@ -254,7 +278,7 @@ export function DecisionsList({
254
278
  </Link>
255
279
  </div>
256
280
  <EmptyOr isEmpty={decisions.length === 0} empty="No decisions yet.">
257
- <ul className="divide-y divide-border border-y border-border">
281
+ <ul className={LIST_DIVIDE}>
258
282
  {decisions.map((decision) => (
259
283
  <li key={decision.id} className="py-3">
260
284
  <p className="text-[13px] font-medium text-ink">{decision.body}</p>
@@ -276,6 +300,6 @@ export function DecisionsList({
276
300
  ))}
277
301
  </ul>
278
302
  </EmptyOr>
279
- </section>
303
+ </SectionWell>
280
304
  )
281
305
  }