@cellarnode/ui 0.199.1 → 0.201.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.
Files changed (90) hide show
  1. package/dist/invite-confirm/client.d.ts +10 -0
  2. package/dist/invite-confirm/client.d.ts.map +1 -0
  3. package/dist/invite-confirm/client.js +69 -0
  4. package/dist/invite-confirm/client.js.map +1 -0
  5. package/dist/invite-confirm/copy.d.ts +42 -0
  6. package/dist/invite-confirm/copy.d.ts.map +1 -0
  7. package/dist/invite-confirm/copy.js +42 -0
  8. package/dist/invite-confirm/copy.js.map +1 -0
  9. package/dist/invite-confirm/fixtures.d.ts +13 -0
  10. package/dist/invite-confirm/fixtures.d.ts.map +1 -0
  11. package/dist/invite-confirm/fixtures.js +30 -0
  12. package/dist/invite-confirm/fixtures.js.map +1 -0
  13. package/dist/invite-confirm/index.d.ts +8 -0
  14. package/dist/invite-confirm/index.d.ts.map +1 -0
  15. package/dist/invite-confirm/index.js +8 -0
  16. package/dist/invite-confirm/index.js.map +1 -0
  17. package/dist/invite-confirm/invite-confirm-page.d.ts +27 -0
  18. package/dist/invite-confirm/invite-confirm-page.d.ts.map +1 -0
  19. package/dist/invite-confirm/invite-confirm-page.js +152 -0
  20. package/dist/invite-confirm/invite-confirm-page.js.map +1 -0
  21. package/dist/invite-confirm/token.d.ts +20 -0
  22. package/dist/invite-confirm/token.d.ts.map +1 -0
  23. package/dist/invite-confirm/token.js +59 -0
  24. package/dist/invite-confirm/token.js.map +1 -0
  25. package/dist/invite-confirm/types.d.ts +28 -0
  26. package/dist/invite-confirm/types.d.ts.map +1 -0
  27. package/dist/invite-confirm/types.js +11 -0
  28. package/dist/invite-confirm/types.js.map +1 -0
  29. package/dist/invite-confirm/use-invite-confirm.d.ts +33 -0
  30. package/dist/invite-confirm/use-invite-confirm.d.ts.map +1 -0
  31. package/dist/invite-confirm/use-invite-confirm.js +110 -0
  32. package/dist/invite-confirm/use-invite-confirm.js.map +1 -0
  33. package/dist/portfolio/include-in-matching-toggle.d.ts +30 -0
  34. package/dist/portfolio/include-in-matching-toggle.d.ts.map +1 -0
  35. package/dist/portfolio/include-in-matching-toggle.js +39 -0
  36. package/dist/portfolio/include-in-matching-toggle.js.map +1 -0
  37. package/dist/portfolio/index.d.ts +4 -0
  38. package/dist/portfolio/index.d.ts.map +1 -1
  39. package/dist/portfolio/index.js +2 -0
  40. package/dist/portfolio/index.js.map +1 -1
  41. package/dist/portfolio/not-matching-badge.d.ts +15 -0
  42. package/dist/portfolio/not-matching-badge.d.ts.map +1 -0
  43. package/dist/portfolio/not-matching-badge.js +13 -0
  44. package/dist/portfolio/not-matching-badge.js.map +1 -0
  45. package/dist/portfolio/product-grid-section.d.ts.map +1 -1
  46. package/dist/portfolio/product-grid-section.js +6 -4
  47. package/dist/portfolio/product-grid-section.js.map +1 -1
  48. package/dist/portfolio/product-list-section.d.ts.map +1 -1
  49. package/dist/portfolio/product-list-section.js +11 -5
  50. package/dist/portfolio/product-list-section.js.map +1 -1
  51. package/dist/portfolio/types.d.ts +6 -0
  52. package/dist/portfolio/types.d.ts.map +1 -1
  53. package/dist/product-editor/tabs/product-status-tab.d.ts.map +1 -1
  54. package/dist/product-editor/tabs/product-status-tab.js +22 -9
  55. package/dist/product-editor/tabs/product-status-tab.js.map +1 -1
  56. package/dist/product-editor/types.d.ts +14 -0
  57. package/dist/product-editor/types.d.ts.map +1 -1
  58. package/dist/upload-link/client.d.ts +21 -0
  59. package/dist/upload-link/client.d.ts.map +1 -0
  60. package/dist/upload-link/client.js +141 -0
  61. package/dist/upload-link/client.js.map +1 -0
  62. package/dist/upload-link/copy.d.ts +83 -0
  63. package/dist/upload-link/copy.d.ts.map +1 -0
  64. package/dist/upload-link/copy.js +132 -0
  65. package/dist/upload-link/copy.js.map +1 -0
  66. package/dist/upload-link/fixtures.d.ts +17 -0
  67. package/dist/upload-link/fixtures.d.ts.map +1 -0
  68. package/dist/upload-link/fixtures.js +63 -0
  69. package/dist/upload-link/fixtures.js.map +1 -0
  70. package/dist/upload-link/flow.d.ts +79 -0
  71. package/dist/upload-link/flow.d.ts.map +1 -0
  72. package/dist/upload-link/flow.js +107 -0
  73. package/dist/upload-link/flow.js.map +1 -0
  74. package/dist/upload-link/index.d.ts +10 -0
  75. package/dist/upload-link/index.d.ts.map +1 -0
  76. package/dist/upload-link/index.js +10 -0
  77. package/dist/upload-link/index.js.map +1 -0
  78. package/dist/upload-link/types.d.ts +58 -0
  79. package/dist/upload-link/types.d.ts.map +1 -0
  80. package/dist/upload-link/types.js +17 -0
  81. package/dist/upload-link/types.js.map +1 -0
  82. package/dist/upload-link/upload-link-page.d.ts +41 -0
  83. package/dist/upload-link/upload-link-page.d.ts.map +1 -0
  84. package/dist/upload-link/upload-link-page.js +184 -0
  85. package/dist/upload-link/upload-link-page.js.map +1 -0
  86. package/dist/upload-link/use-upload-link.d.ts +28 -0
  87. package/dist/upload-link/use-upload-link.d.ts.map +1 -0
  88. package/dist/upload-link/use-upload-link.js +155 -0
  89. package/dist/upload-link/use-upload-link.js.map +1 -0
  90. package/package.json +9 -1
@@ -0,0 +1,10 @@
1
+ import { type InviteConfirmClient } from "./types.js";
2
+ export interface CreateInviteConfirmClientOptions {
3
+ /** The main API origin. */
4
+ baseUrl: string;
5
+ /** The host's authenticated `fetch` (it adds the signed-in session). */
6
+ fetch?: typeof fetch;
7
+ }
8
+ /** The backend's owner-confirmation routes. The token travels in the BODY, never the URL. */
9
+ export declare function createInviteConfirmClient(options: CreateInviteConfirmClientOptions): InviteConfirmClient;
10
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EAGzB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,gCAAgC;IAC/C,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAkBD,6FAA6F;AAC7F,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,mBAAmB,CA+CrB"}
@@ -0,0 +1,69 @@
1
+ import { InviteConfirmApiError, } from "./types.js";
2
+ async function readError(res) {
3
+ let code = null;
4
+ let message = `Request failed (${res.status})`;
5
+ try {
6
+ const body = (await res.json());
7
+ if (typeof body.code === "string")
8
+ code = body.code;
9
+ if (typeof body.error === "string")
10
+ message = body.error;
11
+ }
12
+ catch {
13
+ /* not JSON */
14
+ }
15
+ return new InviteConfirmApiError(res.status, code, message);
16
+ }
17
+ const mismatch = () => new InviteConfirmApiError(502, "CONTRACT_MISMATCH", "Unexpected response from the server.");
18
+ /** The backend's owner-confirmation routes. The token travels in the BODY, never the URL. */
19
+ export function createInviteConfirmClient(options) {
20
+ const base = options.baseUrl.replace(/\/+$/, "");
21
+ const doFetch = options.fetch ?? ((input, init) => fetch(input, init));
22
+ const post = async (path, token, signal) => {
23
+ let res;
24
+ try {
25
+ res = await doFetch(`${base}/organizations/members/invite-confirmations/${path}`, {
26
+ method: "POST",
27
+ headers: { "content-type": "application/json" },
28
+ body: JSON.stringify({ token }),
29
+ ...(signal ? { signal } : {}),
30
+ });
31
+ }
32
+ catch (e) {
33
+ if (e instanceof DOMException && e.name === "AbortError")
34
+ throw e;
35
+ throw new InviteConfirmApiError(0, "NETWORK", "The connection failed.");
36
+ }
37
+ if (!res.ok)
38
+ throw await readError(res);
39
+ return res.json().catch(() => {
40
+ throw mismatch();
41
+ });
42
+ };
43
+ return {
44
+ async preview(token, signal) {
45
+ const o = (await post("preview", token, signal));
46
+ if (!o ||
47
+ typeof o.inviteeEmail !== "string" ||
48
+ typeof o.orgName !== "string" ||
49
+ typeof o.expiresAt !== "string") {
50
+ throw mismatch();
51
+ }
52
+ return {
53
+ status: typeof o.status === "string" ? o.status : "pending",
54
+ inviteeEmail: o.inviteeEmail,
55
+ orgName: o.orgName,
56
+ requestedAt: typeof o.requestedAt === "string" ? o.requestedAt : "",
57
+ expiresAt: o.expiresAt,
58
+ channel: typeof o.channel === "string" ? o.channel : "",
59
+ };
60
+ },
61
+ async confirm(token, signal) {
62
+ const o = (await post("confirm", token, signal));
63
+ if (!o || (o.status !== "active" && o.status !== "pending"))
64
+ throw mismatch();
65
+ return { status: o.status };
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/invite-confirm/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /** Every visible string, English by default and overridable per key. `{name}` tokens are filled by `fmt`. */
2
+ export interface InviteConfirmCopy {
3
+ title: string;
4
+ checking: string;
5
+ signInTitle: string;
6
+ signInBody: string;
7
+ signInAction: string;
8
+ missingTitle: string;
9
+ missingBody: string;
10
+ readyIntro: string;
11
+ readyLine: string;
12
+ nothingSentYet: string;
13
+ seatNote: string;
14
+ expiresLine: string;
15
+ confirm: string;
16
+ confirming: string;
17
+ ignoreHint: string;
18
+ doneActiveTitle: string;
19
+ doneActiveBody: string;
20
+ donePendingTitle: string;
21
+ donePendingBody: string;
22
+ wrongAccountTitle: string;
23
+ wrongAccountBody: string;
24
+ expiredTitle: string;
25
+ expiredBody: string;
26
+ usedTitle: string;
27
+ usedBody: string;
28
+ notFoundTitle: string;
29
+ notFoundBody: string;
30
+ seatLimitTitle: string;
31
+ seatLimitBody: string;
32
+ duplicateTitle: string;
33
+ duplicateBody: string;
34
+ networkTitle: string;
35
+ networkBody: string;
36
+ retry: string;
37
+ errorTitle: string;
38
+ errorBody: string;
39
+ }
40
+ export declare const DEFAULT_COPY: InviteConfirmCopy;
41
+ export declare function fmt(template: string, vars: Record<string, string | number>): string;
42
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/copy.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,EAAE,iBA2C1B,CAAC;AAEF,wBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAEnF"}
@@ -0,0 +1,42 @@
1
+ export const DEFAULT_COPY = {
2
+ title: "Confirm an invitation",
3
+ checking: "Checking your request",
4
+ signInTitle: "Sign in to review this invitation",
5
+ signInBody: "Only the organisation owner who was emailed can confirm it. Sign in to continue.",
6
+ signInAction: "Sign in",
7
+ missingTitle: "This link is incomplete",
8
+ missingBody: "Open the link from the email exactly as it was sent, or ask your assistant to make the request again.",
9
+ readyIntro: "An AI assistant asked to invite someone to {org}.",
10
+ readyLine: "Invite {email}?",
11
+ nothingSentYet: "Nothing has been sent to them yet.",
12
+ seatNote: "Confirming sends the invitation and uses one of your team seats.",
13
+ expiresLine: "This request expires {when}.",
14
+ confirm: "Send the invitation",
15
+ confirming: "Sending",
16
+ ignoreHint: "If you do not recognise this address, close this page. The request expires on its own and nothing is sent.",
17
+ doneActiveTitle: "They are now part of your team",
18
+ doneActiveBody: "They already had an account, so they joined {org} at once.",
19
+ donePendingTitle: "Invitation sent",
20
+ donePendingBody: "We emailed the invitation. They join {org} when they accept it.",
21
+ wrongAccountTitle: "This request belongs to a different account",
22
+ wrongAccountBody: "Sign in with the owner account that received the email, or ask your assistant to make the request again.",
23
+ expiredTitle: "This request has expired",
24
+ expiredBody: "Nothing was sent. Ask your assistant to make the request again.",
25
+ usedTitle: "This invitation was already confirmed",
26
+ usedBody: "There is nothing more to do here.",
27
+ notFoundTitle: "We could not find this request",
28
+ notFoundBody: "The link may be incomplete or already replaced. Ask your assistant to make the request again.",
29
+ seatLimitTitle: "Your plan has no free seat",
30
+ seatLimitBody: "Nothing was sent. Free a seat or upgrade, then open this link again before it expires.",
31
+ duplicateTitle: "They are already on your team",
32
+ duplicateBody: "That person is a member, has a pending invitation, or belongs to another organisation. Nothing was sent.",
33
+ networkTitle: "We could not reach CellarNode",
34
+ networkBody: "Check your connection and try again. Nothing was sent.",
35
+ retry: "Try again",
36
+ errorTitle: "Something went wrong",
37
+ errorBody: "The invitation was not sent. Try again, or invite from the team page.",
38
+ };
39
+ export function fmt(template, vars) {
40
+ return template.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? ""));
41
+ }
42
+ //# sourceMappingURL=copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/invite-confirm/copy.ts"],"names":[],"mappings":"AAwCA,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,uBAAuB;IACjC,WAAW,EAAE,mCAAmC;IAChD,UAAU,EAAE,kFAAkF;IAC9F,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,yBAAyB;IACvC,WAAW,EACT,uGAAuG;IACzG,UAAU,EAAE,mDAAmD;IAC/D,SAAS,EAAE,iBAAiB;IAC5B,cAAc,EAAE,oCAAoC;IACpD,QAAQ,EAAE,kEAAkE;IAC5E,WAAW,EAAE,8BAA8B;IAC3C,OAAO,EAAE,qBAAqB;IAC9B,UAAU,EAAE,SAAS;IACrB,UAAU,EACR,4GAA4G;IAC9G,eAAe,EAAE,gCAAgC;IACjD,cAAc,EAAE,4DAA4D;IAC5E,gBAAgB,EAAE,iBAAiB;IACnC,eAAe,EAAE,iEAAiE;IAClF,iBAAiB,EAAE,6CAA6C;IAChE,gBAAgB,EACd,0GAA0G;IAC5G,YAAY,EAAE,0BAA0B;IACxC,WAAW,EAAE,iEAAiE;IAC9E,SAAS,EAAE,uCAAuC;IAClD,QAAQ,EAAE,mCAAmC;IAC7C,aAAa,EAAE,gCAAgC;IAC/C,YAAY,EACV,+FAA+F;IACjG,cAAc,EAAE,4BAA4B;IAC5C,aAAa,EACX,wFAAwF;IAC1F,cAAc,EAAE,+BAA+B;IAC/C,aAAa,EACX,0GAA0G;IAC5G,YAAY,EAAE,+BAA+B;IAC7C,WAAW,EAAE,wDAAwD;IACrE,KAAK,EAAE,WAAW;IAClB,UAAU,EAAE,sBAAsB;IAClC,SAAS,EAAE,uEAAuE;CACnF,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,QAAgB,EAAE,IAAqC;IACzE,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { InviteConfirmApiError, type InviteConfirmClient, type InviteConfirmPreview, type InviteConfirmResult } from "./types.js";
2
+ export declare const preview: (over?: Partial<InviteConfirmPreview>) => InviteConfirmPreview;
3
+ export interface FakeScript {
4
+ preview?: InviteConfirmPreview | InviteConfirmApiError;
5
+ confirm?: InviteConfirmResult | InviteConfirmApiError;
6
+ /** Hold the confirm answer this long (the sending state). */
7
+ confirmDelay?: number;
8
+ }
9
+ /** In-memory client for stories and tests. */
10
+ export declare function fakeClient(script?: FakeScript): InviteConfirmClient & {
11
+ calls: string[];
12
+ };
13
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACzB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,OAAO,GAAI,OAAM,OAAO,CAAC,oBAAoB,CAAM,KAAG,oBAQjE,CAAC;AAEH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,oBAAoB,GAAG,qBAAqB,CAAC;IACvD,OAAO,CAAC,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IACtD,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,MAAM,GAAE,UAAe,GAAG,mBAAmB,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAkB7F"}
@@ -0,0 +1,30 @@
1
+ import { InviteConfirmApiError, } from "./types.js";
2
+ export const preview = (over = {}) => ({
3
+ status: "pending",
4
+ inviteeEmail: "new.person@example.com",
5
+ orgName: "Nordic Wines AB",
6
+ requestedAt: "2026-10-12T08:00:00.000Z",
7
+ expiresAt: "2026-10-13T08:00:00.000Z",
8
+ channel: "mcp-oauth-v1",
9
+ ...over,
10
+ });
11
+ /** In-memory client for stories and tests. */
12
+ export function fakeClient(script = {}) {
13
+ const calls = [];
14
+ const settle = (v) => v instanceof InviteConfirmApiError ? Promise.reject(v) : Promise.resolve(v);
15
+ return {
16
+ calls,
17
+ preview: (token) => {
18
+ calls.push(`preview:${token}`);
19
+ return settle(script.preview ?? preview());
20
+ },
21
+ confirm: (token, _signal) => {
22
+ calls.push(`confirm:${token}`);
23
+ const answer = settle(script.confirm ?? { status: "pending" });
24
+ return script.confirmDelay
25
+ ? new Promise((r, j) => setTimeout(() => answer.then(r, j), script.confirmDelay))
26
+ : answer;
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/invite-confirm/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAItB,MAAM,SAAS,CAAC;AAEjB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAsC,EAAE,EAAwB,EAAE,CAAC,CAAC;IAC1F,MAAM,EAAE,SAAS;IACjB,YAAY,EAAE,wBAAwB;IACtC,OAAO,EAAE,iBAAiB;IAC1B,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,0BAA0B;IACrC,OAAO,EAAE,cAAc;IACvB,GAAG,IAAI;CACR,CAAC,CAAC;AASH,8CAA8C;AAC9C,MAAM,UAAU,UAAU,CAAC,SAAqB,EAAE;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,CAAI,CAA4B,EAAc,EAAE,CAC7D,CAAC,YAAY,qBAAqB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO;QACL,KAAK;QACL,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;YAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1B,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,CAAsB,MAAM,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YACpF,OAAO,MAAM,CAAC,YAAY;gBACxB,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;gBACjF,CAAC,CAAC,MAAM,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** `@cellarnode/ui/invite-confirm`: the owner's confirm page for an assistant-requested invitation (CEL-2467, backend CEL-2434). */
2
+ export { createInviteConfirmClient, type CreateInviteConfirmClientOptions } from "./client.js";
3
+ export { DEFAULT_COPY, type InviteConfirmCopy } from "./copy.js";
4
+ export { InviteConfirmPage, type InviteConfirmPageProps } from "./invite-confirm-page.js";
5
+ export { clearInviteToken, consumeInviteToken, readTokenFromHash, stashInviteToken } from "./token.js";
6
+ export { InviteConfirmApiError, type InviteConfirmAuthState, type InviteConfirmClient, type InviteConfirmPreview, type InviteConfirmResult, } from "./types.js";
7
+ export { failureOf, type FailureKind, useInviteConfirm } from "./use-invite-confirm.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/index.ts"],"names":[],"mappings":"AAAA,oIAAoI;AACpI,OAAO,EAAE,yBAAyB,EAAE,KAAK,gCAAgC,EAAE,MAAM,UAAU,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /** `@cellarnode/ui/invite-confirm`: the owner's confirm page for an assistant-requested invitation (CEL-2467, backend CEL-2434). */
2
+ export { createInviteConfirmClient } from "./client.js";
3
+ export { DEFAULT_COPY } from "./copy.js";
4
+ export { InviteConfirmPage } from "./invite-confirm-page.js";
5
+ export { clearInviteToken, consumeInviteToken, readTokenFromHash, stashInviteToken } from "./token.js";
6
+ export { InviteConfirmApiError, } from "./types.js";
7
+ export { failureOf, useInviteConfirm } from "./use-invite-confirm.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/invite-confirm/index.ts"],"names":[],"mappings":"AAAA,oIAAoI;AACpI,OAAO,EAAE,yBAAyB,EAAyC,MAAM,UAAU,CAAC;AAC5F,OAAO,EAAE,YAAY,EAA0B,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAA+B,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EACL,qBAAqB,GAKtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAoB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { type InviteConfirmCopy } from "./copy.js";
2
+ import type { InviteConfirmAuthState, InviteConfirmClient } from "./types.js";
3
+ import { type Phase } from "./use-invite-confirm.js";
4
+ export interface InviteConfirmPageProps {
5
+ /** The single-use token, held in memory: from {@link consumeInviteToken} (the URL fragment, or the stash after sign-in), or null when missing. */
6
+ token: string | null;
7
+ /** The backend client: `createInviteConfirmClient({ baseUrl, fetch })`. */
8
+ client: InviteConfirmClient;
9
+ /** Whether the person is signed in. The host owns sign-in. */
10
+ auth: InviteConfirmAuthState;
11
+ /**
12
+ * Called when the person presses Sign in, AFTER the page has stashed the token for this tab. Redirect to sign-in with the PLAIN path
13
+ * only (`?redirect=/organisation/confirm-invite`), never the fragment: the token must not enter a URL again.
14
+ */
15
+ onSignIn: () => void;
16
+ copy?: Partial<InviteConfirmCopy>;
17
+ className?: string;
18
+ }
19
+ /** The announcement for a phase, for the one small live region. */
20
+ export declare function statusLine(phase: Phase, copy: InviteConfirmCopy): string;
21
+ /**
22
+ * The page an organisation owner lands on from the confirmation email (CEL-2434 / CEL-2467): an AI assistant asked to invite
23
+ * someone, nothing has been sent, and only the owner pressing the button sends it. The host passes the token it read from the URL
24
+ * fragment, the signed-in state and a client; mount it in the host's `<main>`.
25
+ */
26
+ export declare function InviteConfirmPage({ token, client, auth, onSignIn, copy: override, className, }: InviteConfirmPageProps): import("react/jsx-runtime").JSX.Element;
27
+ //# sourceMappingURL=invite-confirm-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-confirm-page.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/invite-confirm-page.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAEnE,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAoB,KAAK,KAAK,EAAoB,MAAM,sBAAsB,CAAC;AAEtF,MAAM,WAAW,sBAAsB;IACrC,kJAAkJ;IAClJ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2EAA2E;IAC3E,MAAM,EAAE,mBAAmB,CAAC;IAC5B,8DAA8D;IAC9D,IAAI,EAAE,sBAAsB,CAAC;IAC7B;;;OAGG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmHD,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAmBxE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,SAAS,GACV,EAAE,sBAAsB,2CAgKxB"}
@@ -0,0 +1,152 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { AlertTriangle, CheckCircle2, Clock, Loader2, LogIn, MailCheck, PlugZap, SearchX, UserX, } from "lucide-react";
4
+ import { cn } from "../lib/utils.js";
5
+ import { DEFAULT_COPY, fmt } from "./copy.js";
6
+ import { clearInviteToken, stashInviteToken } from "./token.js";
7
+ import { useInviteConfirm } from "./use-invite-confirm.js";
8
+ const focusRing = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
9
+ const button = "inline-flex min-h-10 items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm/5 font-medium text-primary-foreground transition-colors duration-[var(--duration-micro)] hover:bg-primary/90 disabled:opacity-50";
10
+ const halo = {
11
+ brand: "bg-[var(--tone-brand-soft)] text-[var(--tone-brand-fg)]",
12
+ success: "bg-[var(--tone-success-soft)] text-[var(--tone-success-fg)]",
13
+ warning: "bg-[var(--tone-warning-soft)] text-[var(--tone-warning-fg)]",
14
+ danger: "bg-[var(--tone-danger-soft)] text-[var(--tone-danger-fg)]",
15
+ info: "bg-[var(--tone-info-soft)] text-[var(--tone-info-fg)]",
16
+ neutral: "bg-[var(--tone-neutral-soft)] text-[var(--tone-neutral-fg)]",
17
+ };
18
+ const headingClass = "text-lg/7 font-semibold text-foreground outline-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
19
+ function Message({ tone, icon, title, children, actions, }) {
20
+ return (_jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [_jsx("span", { className: cn("flex size-12 items-center justify-center rounded-full", halo[tone]), "aria-hidden": true, children: icon }), _jsx("h2", { tabIndex: -1, "data-focus-target": true, className: headingClass, children: title }), children ? _jsx("p", { className: "max-w-prose text-sm/6 text-muted-foreground", children: children }) : null, actions ? _jsx("div", { className: "mt-1 flex flex-wrap justify-center gap-2", children: actions }) : null] }));
21
+ }
22
+ const FAILURES = {
23
+ "signed-out": {
24
+ tone: "brand",
25
+ icon: _jsx(LogIn, { className: "size-5" }),
26
+ title: "signInTitle",
27
+ body: "signInBody",
28
+ },
29
+ "wrong-account": {
30
+ tone: "warning",
31
+ icon: _jsx(UserX, { className: "size-5" }),
32
+ title: "wrongAccountTitle",
33
+ body: "wrongAccountBody",
34
+ },
35
+ expired: {
36
+ tone: "neutral",
37
+ icon: _jsx(Clock, { className: "size-5" }),
38
+ title: "expiredTitle",
39
+ body: "expiredBody",
40
+ },
41
+ used: {
42
+ tone: "info",
43
+ icon: _jsx(MailCheck, { className: "size-5" }),
44
+ title: "usedTitle",
45
+ body: "usedBody",
46
+ },
47
+ "not-found": {
48
+ tone: "warning",
49
+ icon: _jsx(SearchX, { className: "size-5" }),
50
+ title: "notFoundTitle",
51
+ body: "notFoundBody",
52
+ },
53
+ "seat-limit": {
54
+ tone: "warning",
55
+ icon: _jsx(AlertTriangle, { className: "size-5" }),
56
+ title: "seatLimitTitle",
57
+ body: "seatLimitBody",
58
+ },
59
+ duplicate: {
60
+ tone: "info",
61
+ icon: _jsx(UserX, { className: "size-5" }),
62
+ title: "duplicateTitle",
63
+ body: "duplicateBody",
64
+ },
65
+ network: {
66
+ tone: "warning",
67
+ icon: _jsx(PlugZap, { className: "size-5" }),
68
+ title: "networkTitle",
69
+ body: "networkBody",
70
+ },
71
+ other: {
72
+ tone: "danger",
73
+ icon: _jsx(AlertTriangle, { className: "size-5" }),
74
+ title: "errorTitle",
75
+ body: "errorBody",
76
+ },
77
+ };
78
+ /** The announcement for a phase, for the one small live region. */
79
+ export function statusLine(phase, copy) {
80
+ switch (phase.kind) {
81
+ case "loading":
82
+ return copy.checking;
83
+ case "sign-in":
84
+ return copy.signInTitle;
85
+ case "missing":
86
+ return copy.missingTitle;
87
+ case "ready":
88
+ return phase.sending
89
+ ? copy.confirming
90
+ : phase.error
91
+ ? String(copy[FAILURES[phase.error].title])
92
+ : "";
93
+ case "done":
94
+ return phase.result.status === "active" ? copy.doneActiveTitle : copy.donePendingTitle;
95
+ case "failed":
96
+ return String(copy[FAILURES[phase.reason].title]);
97
+ }
98
+ }
99
+ /**
100
+ * The page an organisation owner lands on from the confirmation email (CEL-2434 / CEL-2467): an AI assistant asked to invite
101
+ * someone, nothing has been sent, and only the owner pressing the button sends it. The host passes the token it read from the URL
102
+ * fragment, the signed-in state and a client; mount it in the host's `<main>`.
103
+ */
104
+ export function InviteConfirmPage({ token, client, auth, onSignIn, copy: override, className, }) {
105
+ const copy = React.useMemo(() => ({ ...DEFAULT_COPY, ...override }), [override]);
106
+ const titleId = React.useId();
107
+ const { phase, confirm, retry } = useInviteConfirm({ token, client, auth });
108
+ const signIn = React.useCallback(() => {
109
+ // The token must not enter a URL again: keep it for this tab; the host redirects with the plain path only.
110
+ if (token)
111
+ stashInviteToken(token);
112
+ onSignIn();
113
+ }, [token, onSignIn]);
114
+ // Once the request reached a final answer there is nothing left to keep.
115
+ const terminal = phase.kind === "done" ||
116
+ (phase.kind === "failed" && !["signed-out", "network", "other"].includes(phase.reason));
117
+ React.useEffect(() => {
118
+ if (terminal)
119
+ clearInviteToken();
120
+ }, [terminal]);
121
+ const bodyRef = React.useRef(null);
122
+ const previous = React.useRef(null);
123
+ React.useEffect(() => {
124
+ const before = previous.current;
125
+ previous.current = phase.kind;
126
+ if (before === null || before === phase.kind)
127
+ return;
128
+ bodyRef.current?.querySelector("[data-focus-target]")?.focus();
129
+ }, [phase.kind]);
130
+ const body = ((p) => {
131
+ switch (p.kind) {
132
+ case "loading":
133
+ return (_jsx(Message, { tone: "neutral", icon: _jsx(Loader2, { className: "size-5 animate-spin motion-reduce:animate-none" }), title: copy.checking }));
134
+ case "sign-in":
135
+ return (_jsx(Message, { tone: "brand", icon: _jsx(LogIn, { className: "size-5" }), title: copy.signInTitle, actions: _jsx("button", { type: "button", onClick: signIn, className: cn(button, focusRing), children: copy.signInAction }), children: copy.signInBody }));
136
+ case "missing":
137
+ return (_jsx(Message, { tone: "warning", icon: _jsx(SearchX, { className: "size-5" }), title: copy.missingTitle, children: copy.missingBody }));
138
+ case "ready":
139
+ return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("p", { className: "text-sm/6 text-muted-foreground", children: fmt(copy.readyIntro, { org: p.preview.orgName }) }), _jsx("h2", { tabIndex: -1, "data-focus-target": true, className: headingClass, children: fmt(copy.readyLine, { email: p.preview.inviteeEmail }) }), _jsxs("ul", { className: "flex flex-col gap-1 text-sm/6 text-muted-foreground", children: [_jsx("li", { className: "font-medium text-foreground", children: copy.nothingSentYet }), _jsx("li", { children: copy.seatNote }), _jsx("li", { children: fmt(copy.expiresLine, { when: new Date(p.preview.expiresAt).toLocaleString() }) })] }), p.error ? (_jsxs("p", { role: "alert", className: "flex items-start gap-2 rounded-lg bg-[var(--tone-danger-soft)] px-3 py-2 text-sm/5 text-[var(--tone-danger-fg)]", children: [_jsx(AlertTriangle, { "aria-hidden": true, className: "mt-0.5 size-4 shrink-0" }), _jsxs("span", { children: [_jsxs("span", { className: "font-medium", children: [String(copy[FAILURES[p.error].title]), ". "] }), String(copy[FAILURES[p.error].body])] })] })) : null, _jsx("div", { className: "flex flex-wrap items-center gap-3", children: _jsxs("button", { type: "button", onClick: () => void confirm(), disabled: p.sending, "aria-disabled": p.sending, className: cn(button, focusRing), children: [p.sending ? (_jsx(Loader2, { "aria-hidden": true, className: "size-4 animate-spin motion-reduce:animate-none" })) : null, p.sending ? copy.confirming : copy.confirm] }) }), _jsx("p", { className: "text-xs/5 text-muted-foreground", children: copy.ignoreHint })] }));
140
+ case "done": {
141
+ const active = p.result.status === "active";
142
+ return (_jsx(Message, { tone: "success", icon: _jsx(CheckCircle2, { className: "size-5" }), title: active ? copy.doneActiveTitle : copy.donePendingTitle, children: fmt(active ? copy.doneActiveBody : copy.donePendingBody, { org: p.preview.orgName }) }));
143
+ }
144
+ case "failed": {
145
+ const f = FAILURES[p.reason];
146
+ return (_jsx(Message, { tone: f.tone, icon: f.icon, title: String(copy[f.title]), actions: p.reason === "signed-out" ? (_jsx("button", { type: "button", onClick: signIn, className: cn(button, focusRing), children: copy.signInAction })) : p.reason === "network" || p.reason === "other" ? (_jsx("button", { type: "button", onClick: retry, className: cn(button, focusRing), children: copy.retry })) : undefined, children: String(copy[f.body]) }));
147
+ }
148
+ }
149
+ })(phase);
150
+ return (_jsxs("section", { "aria-labelledby": titleId, className: cn("mx-auto flex w-full max-w-lg flex-col gap-6 px-4 py-10", className), children: [_jsx("header", { children: _jsx("h1", { id: titleId, className: "text-2xl/8 font-semibold text-foreground", children: copy.title }) }), _jsx("p", { role: "status", "aria-live": "polite", className: "sr-only", children: statusLine(phase, copy) }), _jsx("div", { ref: bodyRef, className: "rounded-2xl bg-card p-6 shadow-[var(--shadow-soft)] ring-1 ring-border/60", children: body })] }));
151
+ }
152
+ //# sourceMappingURL=invite-confirm-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-confirm-page.js","sourceRoot":"","sources":["../../src/invite-confirm/invite-confirm-page.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The confirm token's journey (CEL-2467). It arrives in the URL FRAGMENT (`#t=...`), which no server ever receives. A host's sign-in
3
+ * guard must NOT carry it onward: TanStack's `location.href` includes the hash, so a guard redirect would turn `#t=TOKEN` into
4
+ * `?redirect=...%23t%3DTOKEN`, which lands in CDN and Envoy logs, history and the referer. So the token never goes into a URL
5
+ * again: before sign-in it is stashed in `sessionStorage` (this tab only), the redirect carries the plain path, and after sign-in
6
+ * the page picks the token up from the stash.
7
+ */
8
+ /** Read `t` from a URL fragment such as `#t=cnic_abc`. */
9
+ export declare function readTokenFromHash(hash: string): string | null;
10
+ /** Keep the token for this tab across the sign-in round trip. Never throws. */
11
+ export declare function stashInviteToken(token: string): void;
12
+ /** Forget the stash (the page does this once the request reached a terminal state). Never throws. */
13
+ export declare function clearInviteToken(): void;
14
+ /**
15
+ * Take the token into memory: from the fragment, else from the stash (after sign-in). When it came from the fragment the address bar
16
+ * is cleaned (`#t=` removed, path and query kept; the router's own history state, e.g. TanStack's `__TSR_index` / `key`, is preserved) so it does not sit in history or a copied link. Call it ONCE per page load, for
17
+ * example in a `useState` initialiser, and keep the result in memory.
18
+ */
19
+ export declare function consumeInviteToken(where?: Pick<Location, "hash" | "pathname" | "search">, replaceState?: (url: string) => void): string | null;
20
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7D;AAUD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,qGAAqG;AACrG,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,GAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAmB,EACvE,YAAY,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAC6B,GAC3D,MAAM,GAAG,IAAI,CAYf"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The confirm token's journey (CEL-2467). It arrives in the URL FRAGMENT (`#t=...`), which no server ever receives. A host's sign-in
3
+ * guard must NOT carry it onward: TanStack's `location.href` includes the hash, so a guard redirect would turn `#t=TOKEN` into
4
+ * `?redirect=...%23t%3DTOKEN`, which lands in CDN and Envoy logs, history and the referer. So the token never goes into a URL
5
+ * again: before sign-in it is stashed in `sessionStorage` (this tab only), the redirect carries the plain path, and after sign-in
6
+ * the page picks the token up from the stash.
7
+ */
8
+ const STASH_KEY = "cn.inviteConfirm.token";
9
+ /** Read `t` from a URL fragment such as `#t=cnic_abc`. */
10
+ export function readTokenFromHash(hash) {
11
+ const value = new URLSearchParams(hash.replace(/^#/, "")).get("t");
12
+ return value && value.length > 0 ? value : null;
13
+ }
14
+ const store = () => {
15
+ try {
16
+ return typeof sessionStorage === "undefined" ? null : sessionStorage;
17
+ }
18
+ catch {
19
+ return null; // blocked site data
20
+ }
21
+ };
22
+ /** Keep the token for this tab across the sign-in round trip. Never throws. */
23
+ export function stashInviteToken(token) {
24
+ try {
25
+ store()?.setItem(STASH_KEY, token);
26
+ }
27
+ catch {
28
+ /* private mode: the owner just opens the email link again after signing in */
29
+ }
30
+ }
31
+ /** Forget the stash (the page does this once the request reached a terminal state). Never throws. */
32
+ export function clearInviteToken() {
33
+ try {
34
+ store()?.removeItem(STASH_KEY);
35
+ }
36
+ catch {
37
+ /* ignore */
38
+ }
39
+ }
40
+ /**
41
+ * Take the token into memory: from the fragment, else from the stash (after sign-in). When it came from the fragment the address bar
42
+ * is cleaned (`#t=` removed, path and query kept; the router's own history state, e.g. TanStack's `__TSR_index` / `key`, is preserved) so it does not sit in history or a copied link. Call it ONCE per page load, for
43
+ * example in a `useState` initialiser, and keep the result in memory.
44
+ */
45
+ export function consumeInviteToken(where = window.location, replaceState = (url) => window.history.replaceState(window.history.state, "", url)) {
46
+ const fromHash = readTokenFromHash(where.hash);
47
+ if (fromHash !== null) {
48
+ replaceState(`${where.pathname}${where.search}`);
49
+ return fromHash;
50
+ }
51
+ try {
52
+ const stashed = store()?.getItem(STASH_KEY);
53
+ return stashed && stashed.length > 0 ? stashed : null;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/invite-confirm/token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,SAAS,GAAG,wBAAwB,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnE,OAAO,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,KAAK,GAAG,GAAmB,EAAE;IACjC,IAAI,CAAC;QACH,OAAO,OAAO,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,oBAAoB;IACnC,CAAC;AACH,CAAC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC;QACH,KAAK,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;IAChF,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,KAAK,EAAE,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAwD,MAAM,CAAC,QAAQ,EACvE,eAAsC,CAAC,GAAG,EAAE,EAAE,CAC5C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,CAAC;IAE5D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,KAAK,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,OAAO,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * CEL-2467: the owner's confirm page for an invitation an AI assistant asked for (backend CEL-2434). The email link carries a
3
+ * single-use token in the URL FRAGMENT; this composite takes it as a prop and POSTs it in a body, so it never sits in a request line.
4
+ */
5
+ export interface InviteConfirmPreview {
6
+ status: string;
7
+ inviteeEmail: string;
8
+ orgName: string;
9
+ requestedAt: string;
10
+ expiresAt: string;
11
+ /** The agent channel that asked (`mcp-oauth-v1`, ...), for context only. */
12
+ channel: string;
13
+ }
14
+ export interface InviteConfirmResult {
15
+ /** `active`: the person already had an account and joined; `pending`: they were emailed and must accept. */
16
+ status: "active" | "pending";
17
+ }
18
+ export declare class InviteConfirmApiError extends Error {
19
+ readonly status: number;
20
+ readonly code: string | null;
21
+ constructor(status: number, code: string | null, message: string);
22
+ }
23
+ export interface InviteConfirmClient {
24
+ preview(token: string, signal?: AbortSignal): Promise<InviteConfirmPreview>;
25
+ confirm(token: string, signal?: AbortSignal): Promise<InviteConfirmResult>;
26
+ }
27
+ export type InviteConfirmAuthState = "checking" | "signed-out" | "signed-in";
28
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,4GAA4G;IAC5G,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC9B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBACjB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM;CAMjE;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC5E,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC5E;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC"}
@@ -0,0 +1,11 @@
1
+ export class InviteConfirmApiError extends Error {
2
+ status;
3
+ code;
4
+ constructor(status, code, message) {
5
+ super(message);
6
+ this.name = "InviteConfirmApiError";
7
+ this.status = status;
8
+ this.code = code;
9
+ }
10
+ }
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/invite-confirm/types.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,MAAM,CAAS;IACf,IAAI,CAAgB;IAC7B,YAAY,MAAc,EAAE,IAAmB,EAAE,OAAe;QAC9D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}