@burdenoff/fe-libs 2026.1021.13 → 2026.1021.15

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 (56) hide show
  1. package/dist/admin-overview/AdminOverviewActionsContext.d.ts +11 -0
  2. package/dist/admin-overview/AdminOverviewActionsContext.js +17 -0
  3. package/dist/admin-overview/AdminOverviewPage.d.ts +4 -0
  4. package/dist/admin-overview/AdminOverviewPage.js +524 -0
  5. package/dist/admin-overview/buildHierarchyGraph.d.ts +36 -0
  6. package/dist/admin-overview/buildHierarchyGraph.js +172 -0
  7. package/dist/admin-overview/index.d.ts +10 -0
  8. package/dist/admin-overview/nodes/OrganizationNode.d.ts +9 -0
  9. package/dist/admin-overview/nodes/OrganizationNode.js +85 -0
  10. package/dist/admin-overview/nodes/ProjectNode.d.ts +9 -0
  11. package/dist/admin-overview/nodes/ProjectNode.js +69 -0
  12. package/dist/admin-overview/nodes/TenantNode.d.ts +9 -0
  13. package/dist/admin-overview/nodes/TenantNode.js +78 -0
  14. package/dist/admin-overview/nodes/WorkspaceNode.d.ts +9 -0
  15. package/dist/admin-overview/nodes/WorkspaceNode.js +136 -0
  16. package/dist/admin-overview/nodes/nodeStyles.d.ts +7 -0
  17. package/dist/admin-overview/nodes/nodeStyles.js +10 -0
  18. package/dist/admin-overview/operations.d.ts +45 -0
  19. package/dist/admin-overview/operations.js +42 -0
  20. package/dist/admin-overview.d.ts +2 -0
  21. package/dist/admin-overview.js +3 -0
  22. package/dist/chrome/GlobalSearch.js +9 -9
  23. package/dist/chrome/HeaderThemeSwitcher.js +7 -7
  24. package/dist/chrome.js +44 -44
  25. package/dist/platform-pages/AcceptShareRoute.d.ts +33 -0
  26. package/dist/platform-pages/AcceptShareRoute.js +72 -0
  27. package/dist/platform-pages/AffiliatesPage.d.ts +16 -0
  28. package/dist/platform-pages/AffiliatesPage.js +583 -0
  29. package/dist/platform-pages/AppearanceSettingsPage.d.ts +14 -0
  30. package/dist/platform-pages/AppearanceSettingsPage.js +14 -0
  31. package/dist/platform-pages/index.d.ts +20 -0
  32. package/dist/platform-pages.d.ts +2 -0
  33. package/dist/platform-pages.js +4 -0
  34. package/dist/shared/components/DocsLink.d.ts +56 -0
  35. package/dist/shared/components/DocsLink.js +97 -0
  36. package/dist/shared/components/index.d.ts +2 -0
  37. package/dist/shared/config/docsUrls.d.ts +91 -0
  38. package/dist/shared/config/docsUrls.js +70 -0
  39. package/dist/shared/config/index.d.ts +2 -0
  40. package/dist/shared/config/shellRoutes.js +7 -0
  41. package/dist/shared/feature-flags/FeatureFlagProvider.d.ts +10 -0
  42. package/dist/shared/feature-flags/FeatureFlagProvider.js +4 -1
  43. package/dist/shared/feature-flags/index.d.ts +2 -2
  44. package/dist/shared/feature-flags/useFeatureFlag.d.ts +26 -1
  45. package/dist/shared/feature-flags/useFeatureFlag.js +25 -12
  46. package/dist/shared/hooks/usePushDeviceRegistration.js +1 -1
  47. package/dist/shared/providers/AppShellProvider.js +6 -6
  48. package/dist/shared-components.js +7 -6
  49. package/dist/shared-config.js +10 -9
  50. package/dist/shared-feature-flags.js +4 -4
  51. package/dist/shared-hooks.js +25 -25
  52. package/dist/shared-native.js +15 -15
  53. package/dist/shared-providers-shell.js +12 -12
  54. package/dist/shared.js +132 -130
  55. package/dist/shell-native/push-optin.js +4 -4
  56. package/package.json +16 -3
@@ -0,0 +1,583 @@
1
+ import { resolveGatewayUrls as e } from "../shared/config/gatewayUrls.js";
2
+ import "../shared-config.js";
3
+ import { useAuth as t } from "../shared/providers/shell/AuthProvider.js";
4
+ import { useAuthToken as n } from "../shared/providers/shell/AuthTokenProvider.js";
5
+ import { useCallback as r, useEffect as i, useMemo as a, useReducer as o, useState as s } from "react";
6
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
+ //#region src/platform-pages/AffiliatesPage.tsx
8
+ function u(e) {
9
+ return {
10
+ label: "",
11
+ productSlug: e,
12
+ destinationUrl: ""
13
+ };
14
+ }
15
+ var d = {
16
+ codes: [],
17
+ loading: !0,
18
+ error: null
19
+ };
20
+ function f(e, t) {
21
+ switch (t.type) {
22
+ case "load:start": return {
23
+ ...e,
24
+ loading: !0,
25
+ error: null
26
+ };
27
+ case "load:success": return {
28
+ ...e,
29
+ loading: !1,
30
+ codes: t.codes
31
+ };
32
+ case "error": return {
33
+ ...e,
34
+ loading: !1,
35
+ error: t.message
36
+ };
37
+ case "error:clear": return {
38
+ ...e,
39
+ error: null
40
+ };
41
+ }
42
+ }
43
+ var p = {
44
+ selectedCodeId: null,
45
+ analytics: null,
46
+ notes: []
47
+ };
48
+ function m(e, t) {
49
+ switch (t.type) {
50
+ case "select": return e.selectedCodeId === t.id ? e : {
51
+ selectedCodeId: t.id,
52
+ analytics: null,
53
+ notes: []
54
+ };
55
+ case "detail:loaded": return {
56
+ ...e,
57
+ analytics: t.analytics,
58
+ notes: t.notes
59
+ };
60
+ case "notes:set": return {
61
+ ...e,
62
+ notes: t.notes
63
+ };
64
+ }
65
+ }
66
+ async function h(e) {
67
+ let t = await fetch(e.url, {
68
+ method: "POST",
69
+ headers: {
70
+ "content-type": "application/json",
71
+ ...e.authToken ? { authorization: `Bearer ${e.authToken}` } : {},
72
+ ...e.actorId ? {
73
+ "x-actor-id": e.actorId,
74
+ "x-actor-type": "user"
75
+ } : {}
76
+ },
77
+ body: JSON.stringify({
78
+ query: e.query,
79
+ variables: e.variables ?? {}
80
+ })
81
+ }), n = await t.json();
82
+ if (!t.ok || n.errors?.length || !n.data) throw Error(n.errors?.[0]?.message ?? "Request failed");
83
+ return n.data;
84
+ }
85
+ function g({ productSlug: g }) {
86
+ let { user: x } = t(), { accessToken: S } = n(), C = S ?? "", w = `${a(() => e(), []).globalBaseUrl}/global/graphql`, [T, E] = o(f, d), [D, O] = o(m, p), [k, A] = s(""), [j, M] = s(() => u(g)), { codes: N, loading: P, error: F } = T, { selectedCodeId: I, analytics: L, notes: R } = D, z = x?.id ?? "", B = r(async () => {
87
+ if (z) {
88
+ E({ type: "load:start" });
89
+ try {
90
+ E({
91
+ type: "load:success",
92
+ codes: (await h({
93
+ url: w,
94
+ authToken: C,
95
+ actorId: z,
96
+ query: "query MyAffiliateCodes {\n myAffiliateCodes(limit: 50, offset: 0) {\n items {\n id code ownerUserId productSlug label description destinationUrl\n isActive visits signups paidConversions storePurchases\n revenueAmount rewardAmount createdAt\n }\n totalCount\n }\n }"
97
+ })).myAffiliateCodes.items
98
+ });
99
+ } catch (e) {
100
+ E({
101
+ type: "error",
102
+ message: e instanceof Error ? e.message : String(e)
103
+ });
104
+ }
105
+ }
106
+ }, [
107
+ w,
108
+ C,
109
+ z
110
+ ]);
111
+ i(() => {
112
+ Promise.resolve().then(() => B());
113
+ }, [B]), i(() => {
114
+ !I || !z || Promise.all([h({
115
+ url: w,
116
+ authToken: C,
117
+ actorId: z,
118
+ query: "query CodeAnalytics($id: ID!) {\n affiliateCodeAnalytics(id: $id) {\n visits uniqueJourneys signups paidConversions storePurchases\n revenueAmount rewardAmount conversionRate\n topCountries { country visits conversions }\n topModes { mode visits conversions }\n }\n }",
119
+ variables: { id: I }
120
+ }), h({
121
+ url: w,
122
+ authToken: C,
123
+ actorId: z,
124
+ query: "query CodeNotes($id: ID!) {\n affiliateCode(id: $id) {\n id\n notes { id body authorType createdAt }\n }\n }",
125
+ variables: { id: I }
126
+ })]).then(([e, t]) => {
127
+ O({
128
+ type: "detail:loaded",
129
+ analytics: e.affiliateCodeAnalytics,
130
+ notes: t.affiliateCode?.notes ?? []
131
+ });
132
+ }).catch((e) => E({
133
+ type: "error",
134
+ message: e instanceof Error ? e.message : String(e)
135
+ }));
136
+ }, [
137
+ I,
138
+ w,
139
+ C,
140
+ z
141
+ ]);
142
+ let V = r(async () => {
143
+ if (z) try {
144
+ await h({
145
+ url: w,
146
+ authToken: C,
147
+ actorId: z,
148
+ query: "mutation CreateCode($input: CreateAffiliateCodeInput!) {\n createAffiliateCode(input: $input) { id code }\n }",
149
+ variables: { input: j }
150
+ }), M(u(g)), await B();
151
+ } catch (e) {
152
+ E({
153
+ type: "error",
154
+ message: e instanceof Error ? e.message : String(e)
155
+ });
156
+ }
157
+ }, [
158
+ w,
159
+ C,
160
+ z,
161
+ j,
162
+ B,
163
+ g
164
+ ]), H = r(async (e) => {
165
+ if (z) try {
166
+ await h({
167
+ url: w,
168
+ authToken: C,
169
+ actorId: z,
170
+ query: "mutation Regen($id: ID!) {\n regenerateAffiliateCode(id: $id) { id code }\n }",
171
+ variables: { id: e }
172
+ }), await B();
173
+ } catch (e) {
174
+ E({
175
+ type: "error",
176
+ message: e instanceof Error ? e.message : String(e)
177
+ });
178
+ }
179
+ }, [
180
+ w,
181
+ C,
182
+ z,
183
+ B
184
+ ]), U = r(async (e) => {
185
+ if (z) try {
186
+ await h({
187
+ url: w,
188
+ authToken: C,
189
+ actorId: z,
190
+ query: "mutation Deactivate($id: ID!) {\n deactivateAffiliateCode(id: $id) { id isActive }\n }",
191
+ variables: { id: e }
192
+ }), await B();
193
+ } catch (e) {
194
+ E({
195
+ type: "error",
196
+ message: e instanceof Error ? e.message : String(e)
197
+ });
198
+ }
199
+ }, [
200
+ w,
201
+ C,
202
+ z,
203
+ B
204
+ ]), W = r(async () => {
205
+ if (!(!z || !I || !k.trim())) try {
206
+ await h({
207
+ url: w,
208
+ authToken: C,
209
+ actorId: z,
210
+ query: "mutation AddNote($input: AddAffiliateCodeNoteInput!) {\n addAffiliateCodeNote(input: $input) { id body createdAt }\n }",
211
+ variables: { input: {
212
+ codeId: I,
213
+ body: k.trim()
214
+ } }
215
+ }), A(""), O({
216
+ type: "notes:set",
217
+ notes: (await h({
218
+ url: w,
219
+ authToken: C,
220
+ actorId: z,
221
+ query: "query CodeNotes($id: ID!) {\n affiliateCode(id: $id) {\n notes { id body authorType createdAt }\n }\n }",
222
+ variables: { id: I }
223
+ })).affiliateCode?.notes ?? []
224
+ });
225
+ } catch (e) {
226
+ E({
227
+ type: "error",
228
+ message: e instanceof Error ? e.message : String(e)
229
+ });
230
+ }
231
+ }, [
232
+ w,
233
+ C,
234
+ z,
235
+ I,
236
+ k
237
+ ]), G = r((e) => {
238
+ O({
239
+ type: "select",
240
+ id: e
241
+ });
242
+ }, []);
243
+ return /* @__PURE__ */ l("div", {
244
+ className: "p-6 space-y-6",
245
+ children: [
246
+ /* @__PURE__ */ l("header", {
247
+ className: "flex items-center justify-between",
248
+ children: [/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h1", {
249
+ className: "text-2xl font-semibold text-foreground",
250
+ children: "Affiliates"
251
+ }), /* @__PURE__ */ c("p", {
252
+ className: "text-sm text-muted-foreground",
253
+ children: "Manage your referral codes, see clicks/conversions/earnings, add internal notes."
254
+ })] }), /* @__PURE__ */ c("button", {
255
+ type: "button",
256
+ onClick: () => void B(),
257
+ className: "rounded-md border border-border bg-card px-3 py-2 text-sm font-medium text-foreground",
258
+ children: "Refresh"
259
+ })]
260
+ }),
261
+ F ? /* @__PURE__ */ c("div", {
262
+ className: "rounded-lg border border-destructive bg-card p-3 text-sm text-destructive",
263
+ children: F
264
+ }) : null,
265
+ /* @__PURE__ */ c(_, {
266
+ form: j,
267
+ onChange: M,
268
+ onSubmit: () => void V()
269
+ }),
270
+ /* @__PURE__ */ c(v, {
271
+ loading: P,
272
+ codes: N,
273
+ selectedCodeId: I,
274
+ onSelect: G,
275
+ onRegenerate: (e) => void H(e),
276
+ onDeactivate: (e) => void U(e)
277
+ }),
278
+ I && L ? /* @__PURE__ */ c(y, { analytics: L }) : null,
279
+ I ? /* @__PURE__ */ c(b, {
280
+ notes: R,
281
+ newNote: k,
282
+ onNewNoteChange: A,
283
+ onSubmit: () => void W()
284
+ }) : null
285
+ ]
286
+ });
287
+ }
288
+ function _(e) {
289
+ let { form: t, onChange: n, onSubmit: r } = e;
290
+ return /* @__PURE__ */ l("section", {
291
+ className: "rounded-lg border border-border bg-card p-4",
292
+ children: [
293
+ /* @__PURE__ */ c("h2", {
294
+ className: "mb-3 text-lg font-semibold text-foreground",
295
+ children: "Create new code"
296
+ }),
297
+ /* @__PURE__ */ l("div", {
298
+ className: "grid gap-3 md:grid-cols-3",
299
+ children: [
300
+ /* @__PURE__ */ c("input", {
301
+ "aria-label": "Label (e.g. Summer launch)",
302
+ value: t.label,
303
+ onChange: (e) => n({
304
+ ...t,
305
+ label: e.target.value
306
+ }),
307
+ placeholder: "Label (e.g. Summer launch)",
308
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm"
309
+ }),
310
+ /* @__PURE__ */ c("input", {
311
+ "aria-label": "Product slug",
312
+ value: t.productSlug,
313
+ onChange: (e) => n({
314
+ ...t,
315
+ productSlug: e.target.value
316
+ }),
317
+ placeholder: "Product slug",
318
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm"
319
+ }),
320
+ /* @__PURE__ */ c("input", {
321
+ "aria-label": "Destination URL",
322
+ value: t.destinationUrl,
323
+ onChange: (e) => n({
324
+ ...t,
325
+ destinationUrl: e.target.value
326
+ }),
327
+ placeholder: "Destination URL",
328
+ className: "rounded-md border border-border bg-background px-3 py-2 text-sm"
329
+ })
330
+ ]
331
+ }),
332
+ /* @__PURE__ */ c("button", {
333
+ type: "button",
334
+ onClick: r,
335
+ className: "mt-3 rounded-md border border-border bg-primary px-3 py-2 text-sm font-medium text-primary-foreground",
336
+ children: "Create code"
337
+ })
338
+ ]
339
+ });
340
+ }
341
+ function v(e) {
342
+ let { loading: t, codes: n, selectedCodeId: r, onSelect: i, onRegenerate: a, onDeactivate: o } = e;
343
+ return /* @__PURE__ */ l("section", {
344
+ className: "rounded-lg border border-border bg-card p-4",
345
+ children: [/* @__PURE__ */ c("h2", {
346
+ className: "mb-3 text-lg font-semibold text-foreground",
347
+ children: "My codes"
348
+ }), t ? /* @__PURE__ */ c("p", {
349
+ className: "text-sm text-muted-foreground",
350
+ children: "Loading…"
351
+ }) : n.length === 0 ? /* @__PURE__ */ c("p", {
352
+ className: "text-sm text-muted-foreground",
353
+ children: "No codes yet. Create one above."
354
+ }) : /* @__PURE__ */ l("table", {
355
+ className: "min-w-full text-sm",
356
+ children: [/* @__PURE__ */ c("thead", {
357
+ className: "text-left text-muted-foreground",
358
+ children: /* @__PURE__ */ l("tr", {
359
+ className: "border-b border-border",
360
+ children: [
361
+ /* @__PURE__ */ c("th", {
362
+ className: "px-3 py-2",
363
+ children: "Code"
364
+ }),
365
+ /* @__PURE__ */ c("th", {
366
+ className: "px-3 py-2",
367
+ children: "Label"
368
+ }),
369
+ /* @__PURE__ */ c("th", {
370
+ className: "px-3 py-2",
371
+ children: "Product"
372
+ }),
373
+ /* @__PURE__ */ c("th", {
374
+ className: "px-3 py-2",
375
+ children: "Visits"
376
+ }),
377
+ /* @__PURE__ */ c("th", {
378
+ className: "px-3 py-2",
379
+ children: "Conversions"
380
+ }),
381
+ /* @__PURE__ */ c("th", {
382
+ className: "px-3 py-2",
383
+ children: "Reward"
384
+ }),
385
+ /* @__PURE__ */ c("th", {
386
+ className: "px-3 py-2",
387
+ children: "Status"
388
+ }),
389
+ /* @__PURE__ */ c("th", {
390
+ className: "px-3 py-2",
391
+ children: "Actions"
392
+ })
393
+ ]
394
+ })
395
+ }), /* @__PURE__ */ c("tbody", { children: n.map((e) => /* @__PURE__ */ l("tr", {
396
+ className: `cursor-pointer border-b border-border/70 ${r === e.id ? "bg-muted/40" : ""}`,
397
+ onClick: () => i(e.id),
398
+ children: [
399
+ /* @__PURE__ */ c("td", {
400
+ className: "px-3 py-2 font-mono text-foreground",
401
+ children: e.code
402
+ }),
403
+ /* @__PURE__ */ c("td", {
404
+ className: "px-3 py-2",
405
+ children: e.label ?? "—"
406
+ }),
407
+ /* @__PURE__ */ c("td", {
408
+ className: "px-3 py-2",
409
+ children: e.productSlug ?? "—"
410
+ }),
411
+ /* @__PURE__ */ c("td", {
412
+ className: "px-3 py-2",
413
+ children: e.visits
414
+ }),
415
+ /* @__PURE__ */ c("td", {
416
+ className: "px-3 py-2",
417
+ children: e.paidConversions + e.storePurchases
418
+ }),
419
+ /* @__PURE__ */ c("td", {
420
+ className: "px-3 py-2",
421
+ children: e.rewardAmount.toFixed(2)
422
+ }),
423
+ /* @__PURE__ */ c("td", {
424
+ className: "px-3 py-2",
425
+ children: e.isActive ? "Active" : "Inactive"
426
+ }),
427
+ /* @__PURE__ */ l("td", {
428
+ className: "px-3 py-2",
429
+ children: [/* @__PURE__ */ c("button", {
430
+ type: "button",
431
+ onClick: (t) => {
432
+ t.stopPropagation(), a(e.id);
433
+ },
434
+ className: "mr-2 rounded border border-border px-2 py-1 text-xs",
435
+ children: "Regenerate"
436
+ }), e.isActive ? /* @__PURE__ */ c("button", {
437
+ type: "button",
438
+ onClick: (t) => {
439
+ t.stopPropagation(), o(e.id);
440
+ },
441
+ className: "rounded border border-border px-2 py-1 text-xs",
442
+ children: "Deactivate"
443
+ }) : null]
444
+ })
445
+ ]
446
+ }, e.id)) })]
447
+ })]
448
+ });
449
+ }
450
+ function y({ analytics: e }) {
451
+ return /* @__PURE__ */ l("section", {
452
+ className: "rounded-lg border border-border bg-card p-4",
453
+ children: [
454
+ /* @__PURE__ */ c("h2", {
455
+ className: "mb-3 text-lg font-semibold text-foreground",
456
+ children: "Analytics"
457
+ }),
458
+ /* @__PURE__ */ l("div", {
459
+ className: "grid gap-3 md:grid-cols-4",
460
+ children: [
461
+ /* @__PURE__ */ c(x, {
462
+ label: "Visits",
463
+ value: e.visits
464
+ }),
465
+ /* @__PURE__ */ c(x, {
466
+ label: "Unique journeys",
467
+ value: e.uniqueJourneys
468
+ }),
469
+ /* @__PURE__ */ c(x, {
470
+ label: "Signups",
471
+ value: e.signups
472
+ }),
473
+ /* @__PURE__ */ c(x, {
474
+ label: "Conversion rate",
475
+ value: `${(e.conversionRate * 100).toFixed(1)}%`
476
+ }),
477
+ /* @__PURE__ */ c(x, {
478
+ label: "Paid",
479
+ value: e.paidConversions
480
+ }),
481
+ /* @__PURE__ */ c(x, {
482
+ label: "Store",
483
+ value: e.storePurchases
484
+ }),
485
+ /* @__PURE__ */ c(x, {
486
+ label: "Revenue",
487
+ value: e.revenueAmount.toFixed(2)
488
+ }),
489
+ /* @__PURE__ */ c(x, {
490
+ label: "Reward",
491
+ value: e.rewardAmount.toFixed(2)
492
+ })
493
+ ]
494
+ }),
495
+ /* @__PURE__ */ l("div", {
496
+ className: "mt-4 grid gap-3 md:grid-cols-2",
497
+ children: [/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h3", {
498
+ className: "mb-2 text-sm font-medium text-foreground",
499
+ children: "Top countries"
500
+ }), e.topCountries.length ? /* @__PURE__ */ c("ul", {
501
+ className: "space-y-1 text-sm",
502
+ children: e.topCountries.map((e) => /* @__PURE__ */ l("li", {
503
+ className: "flex justify-between",
504
+ children: [/* @__PURE__ */ c("span", { children: e.country }), /* @__PURE__ */ c("span", { children: e.visits })]
505
+ }, e.country))
506
+ }) : /* @__PURE__ */ c("p", {
507
+ className: "text-sm text-muted-foreground",
508
+ children: "No data"
509
+ })] }), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h3", {
510
+ className: "mb-2 text-sm font-medium text-foreground",
511
+ children: "Top modes"
512
+ }), e.topModes.length ? /* @__PURE__ */ c("ul", {
513
+ className: "space-y-1 text-sm",
514
+ children: e.topModes.map((e) => /* @__PURE__ */ l("li", {
515
+ className: "flex justify-between",
516
+ children: [/* @__PURE__ */ c("span", { children: e.mode }), /* @__PURE__ */ c("span", { children: e.visits })]
517
+ }, e.mode))
518
+ }) : /* @__PURE__ */ c("p", {
519
+ className: "text-sm text-muted-foreground",
520
+ children: "No data"
521
+ })] })]
522
+ })
523
+ ]
524
+ });
525
+ }
526
+ function b(e) {
527
+ let { notes: t, newNote: n, onNewNoteChange: r, onSubmit: i } = e;
528
+ return /* @__PURE__ */ l("section", {
529
+ className: "rounded-lg border border-border bg-card p-4",
530
+ children: [
531
+ /* @__PURE__ */ c("h2", {
532
+ className: "mb-3 text-lg font-semibold text-foreground",
533
+ children: "Internal notes"
534
+ }),
535
+ /* @__PURE__ */ l("div", {
536
+ className: "flex items-center gap-2",
537
+ children: [/* @__PURE__ */ c("input", {
538
+ "aria-label": "Note for this code",
539
+ value: n,
540
+ onChange: (e) => r(e.target.value),
541
+ placeholder: "Add a note for this code…",
542
+ className: "flex-1 rounded-md border border-border bg-background px-3 py-2 text-sm"
543
+ }), /* @__PURE__ */ c("button", {
544
+ type: "button",
545
+ onClick: i,
546
+ className: "rounded-md border border-border bg-primary px-3 py-2 text-sm font-medium text-primary-foreground",
547
+ children: "Add"
548
+ })]
549
+ }),
550
+ /* @__PURE__ */ l("ul", {
551
+ className: "mt-4 space-y-2",
552
+ children: [t.map((e) => /* @__PURE__ */ l("li", {
553
+ className: "rounded-md border border-border bg-background p-2 text-sm",
554
+ children: [/* @__PURE__ */ l("div", {
555
+ className: "text-xs text-muted-foreground",
556
+ children: [
557
+ e.authorType,
558
+ " · ",
559
+ new Date(e.createdAt).toLocaleString()
560
+ ]
561
+ }), /* @__PURE__ */ c("div", { children: e.body })]
562
+ }, e.id)), t.length === 0 ? /* @__PURE__ */ c("li", {
563
+ className: "text-sm text-muted-foreground",
564
+ children: "No notes yet."
565
+ }) : null]
566
+ })
567
+ ]
568
+ });
569
+ }
570
+ function x({ label: e, value: t }) {
571
+ return /* @__PURE__ */ l("div", {
572
+ className: "rounded-md border border-border bg-background p-3",
573
+ children: [/* @__PURE__ */ c("p", {
574
+ className: "text-xs text-muted-foreground",
575
+ children: e
576
+ }), /* @__PURE__ */ c("p", {
577
+ className: "text-lg font-semibold text-foreground",
578
+ children: t
579
+ })]
580
+ });
581
+ }
582
+ //#endregion
583
+ export { g as AffiliatesPage };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Appearance / Theme Preferences page.
3
+ *
4
+ * Thin wrapper around the shared Boff UI 2.0 `ThemePreferences` customizer
5
+ * (fe-libs/chrome). It exposes the full system: the six built-in themes,
6
+ * per-product accent, density, typography, glass intensity, reduced motion,
7
+ * and user-designed CUSTOM themes (create / save / apply / delete) — all wired
8
+ * straight to the fe-libs ThemeProvider and persisted, with a live preview.
9
+ *
10
+ * Shared by every app shell (`@burdenoff/fe-libs/platform-pages`); mount it at
11
+ * `/settings/appearance`. It is purely client-side, so it needs no gateway.
12
+ */
13
+ export declare function AppearanceSettingsPage(): import('react/jsx-runtime').JSX.Element;
14
+ export default AppearanceSettingsPage;
@@ -0,0 +1,14 @@
1
+ import { ThemePreferences as e } from "../chrome/ThemePreferences.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/platform-pages/AppearanceSettingsPage.tsx
4
+ function n() {
5
+ return /* @__PURE__ */ t("div", {
6
+ className: "min-h-full bg-bg-canvas",
7
+ children: /* @__PURE__ */ t("div", {
8
+ className: "mx-auto w-full max-w-6xl px-4 py-6 md:px-6 lg:px-8",
9
+ children: /* @__PURE__ */ t(e, {})
10
+ })
11
+ });
12
+ }
13
+ //#endregion
14
+ export { n as default };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @burdenoff/fe-libs/platform-pages
3
+ *
4
+ * Platform pages that every app shell mounts at the same paths. They used to be
5
+ * copied into each shell (vibecontrols-app first), so the copies drifted; the
6
+ * shells now import them from here.
7
+ *
8
+ * | Page | Path | Mount |
9
+ * |--------------------------|--------------------------|--------------------------------|
10
+ * | `AppearanceSettingsPage` | `/settings/appearance` | protected, no gateway |
11
+ * | `AffiliatesPage` | `/affiliates` | protected (global gateway URL) |
12
+ * | `AcceptShareRoute` | `/share/accept/:token` | protected (workspace gateway) |
13
+ *
14
+ * `AdminOverviewPage` (`/admin/overview`) lives in
15
+ * `@burdenoff/fe-libs/admin-overview` because it needs the optional
16
+ * `@xyflow/react` peer.
17
+ */
18
+ export { AppearanceSettingsPage } from './AppearanceSettingsPage';
19
+ export { AffiliatesPage, type AffiliatesPageProps } from './AffiliatesPage';
20
+ export { AcceptShareRoute, resolveAcceptedShareDestination, type AcceptShareRouteProps, } from './AcceptShareRoute';
@@ -0,0 +1,2 @@
1
+ export * from './platform-pages/index.js'
2
+ export {}
@@ -0,0 +1,4 @@
1
+ import e from "./platform-pages/AppearanceSettingsPage.js";
2
+ import { AffiliatesPage as t } from "./platform-pages/AffiliatesPage.js";
3
+ import { AcceptShareRoute as n, resolveAcceptedShareDestination as r } from "./platform-pages/AcceptShareRoute.js";
4
+ export { n as AcceptShareRoute, t as AffiliatesPage, e as AppearanceSettingsPage, r as resolveAcceptedShareDestination };
@@ -0,0 +1,56 @@
1
+ import { AnchorHTMLAttributes, ReactNode } from 'react';
2
+ import { DocsEnvironment } from '../config/docsUrls';
3
+ export declare const PUBLIC_PRODUCT_DOCS_URL_QUERY: import('graphql').DocumentNode;
4
+ /** Minimal client surface the registry lookup needs (an ApolloClient satisfies it). */
5
+ export interface DocsRegistryClient {
6
+ query: (options: {
7
+ query: typeof PUBLIC_PRODUCT_DOCS_URL_QUERY;
8
+ variables: {
9
+ slug: string;
10
+ };
11
+ fetchPolicy: 'cache-first';
12
+ }) => Promise<{
13
+ data?: unknown;
14
+ }>;
15
+ }
16
+ /** Read `publicProduct.docsUrl` out of a query result, trusted origins only. */
17
+ export declare function readRegistryDocsUrl(data: unknown): string | null;
18
+ /** The cached registry docsUrl for a slug: string, `null` (none), or undefined (not fetched). */
19
+ export declare function getCachedRegistryDocsUrl(productSlug: string): string | null | undefined;
20
+ /**
21
+ * Look up the registry docsUrl once per slug. Failures resolve to `null` (the
22
+ * catalog default stays in use) and are not cached, so a later mount retries.
23
+ */
24
+ export declare function fetchRegistryDocsUrl(client: DocsRegistryClient, productSlug: string): Promise<string | null>;
25
+ /** Test seam: forget every cached registry answer. */
26
+ export declare function resetRegistryDocsUrlCache(): void;
27
+ export interface UseProductDocsOptions {
28
+ /** Another product's docs instead of the running shell's. */
29
+ productSlug?: string;
30
+ /** Skip the registry lookup and use the static catalog default only. */
31
+ registry?: boolean;
32
+ /** Override the detected environment (tests, previews). */
33
+ environment?: DocsEnvironment;
34
+ }
35
+ /**
36
+ * The environment-correct docs origin for the running shell's product, e.g.
37
+ * `https://docs.vibecontrols.com` or `https://alphadocs.vibecontrols.com`.
38
+ */
39
+ export declare function useProductDocsOrigin(options?: UseProductDocsOptions): string | undefined;
40
+ /**
41
+ * The environment-correct docs URL for a page of the running shell's product.
42
+ * `path` is site-relative (`/users/workflows`); undefined when it is not, or
43
+ * when the product has no trusted docs host.
44
+ */
45
+ export declare function useProductDocsUrl(path?: string, options?: UseProductDocsOptions): string | undefined;
46
+ export interface DocsLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'target' | 'rel'>, UseProductDocsOptions {
47
+ /** Site-relative docs path, e.g. `/users/workflows`. Defaults to the docs home. */
48
+ path?: string;
49
+ children: ReactNode;
50
+ }
51
+ /**
52
+ * A new-tab link to the product's docs for the current environment. Renders
53
+ * its children without a link when no trusted docs URL resolves, so a page
54
+ * never shows a dead "Learn more".
55
+ */
56
+ export declare function DocsLink({ path, productSlug, registry, environment, children, ...anchorProps }: DocsLinkProps): import('react/jsx-runtime').JSX.Element;