@agent-native/core 0.84.16 → 0.84.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/session-replay.ts +2 -2
- package/corpus/templates/analytics/changelog/2026-07-01-session-replay-recordings-upload-reliably-in-production.md +6 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +46 -5
- package/corpus/templates/calendar/app/components/booking/TimeSlotPicker.tsx +10 -0
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +15 -6
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +22 -0
- package/corpus/templates/calendar/app/hooks/use-bookings.ts +6 -2
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/calendar/app/i18n-data.ts +107 -0
- package/corpus/templates/calendar/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +9 -1
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +40 -26
- package/corpus/templates/calendar/app/pages/Settings.tsx +3 -1
- package/corpus/templates/calendar/changelog/2026-07-01-booking-links-now-show-an-error-when-calendar-availability-c.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +78 -13
- package/corpus/templates/calendar/server/handlers/google-auth.ts +3 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +16 -2
- package/corpus/templates/design/app/lib/design-system-preview.ts +69 -0
- package/corpus/templates/design/app/pages/DesignSystems.tsx +71 -50
- package/corpus/templates/design/changelog/2026-07-01-design-systems-no-longer-crash-on-responsive-tokens.md +6 -0
- package/dist/client/session-replay.js +2 -2
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
|
@@ -163,6 +163,7 @@ type ConflictItem = { start: string; end: string };
|
|
|
163
163
|
type ConflictResult = { items: ConflictItem[]; unavailableReason?: string };
|
|
164
164
|
type BookingLinkRow = typeof schema.bookingLinks.$inferSelect;
|
|
165
165
|
type ConflictDb = Pick<ReturnType<typeof getDb>, "select">;
|
|
166
|
+
const BOOKING_SLOT_STEP_MINUTES = 30;
|
|
166
167
|
|
|
167
168
|
type LocalDateTimeParts = {
|
|
168
169
|
year: number;
|
|
@@ -341,6 +342,27 @@ function dateEndIso(date: string, timezone: string): string {
|
|
|
341
342
|
).toISOString();
|
|
342
343
|
}
|
|
343
344
|
|
|
345
|
+
function formatAvailabilityUnavailableReason(email?: string): string {
|
|
346
|
+
return email
|
|
347
|
+
? `Calendar availability unavailable for ${email}`
|
|
348
|
+
: "Calendar availability unavailable";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function unavailableAvailabilityResponse(event: H3Event) {
|
|
352
|
+
setResponseStatus(event, 503);
|
|
353
|
+
return {
|
|
354
|
+
error:
|
|
355
|
+
"The host's calendar availability could not be checked. Please try again later.",
|
|
356
|
+
code: "calendar_availability_unavailable",
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function formatLocalTime(totalMinutes: number): string {
|
|
361
|
+
const hour = Math.floor(totalMinutes / 60);
|
|
362
|
+
const minute = totalMinutes % 60;
|
|
363
|
+
return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
|
|
364
|
+
}
|
|
365
|
+
|
|
344
366
|
async function resolveAvailabilityContext({
|
|
345
367
|
slug,
|
|
346
368
|
db = getDb(),
|
|
@@ -397,7 +419,7 @@ async function resolveAvailabilityContext({
|
|
|
397
419
|
};
|
|
398
420
|
}
|
|
399
421
|
|
|
400
|
-
async function getConflictItems({
|
|
422
|
+
export async function getConflictItems({
|
|
401
423
|
db = getDb(),
|
|
402
424
|
ownerEmail,
|
|
403
425
|
hostEmails,
|
|
@@ -424,7 +446,18 @@ async function getConflictItems({
|
|
|
424
446
|
);
|
|
425
447
|
const freeBusyResolvedHosts = new Set<string>();
|
|
426
448
|
|
|
427
|
-
|
|
449
|
+
const ownerConnected = ownerEmail
|
|
450
|
+
? await googleCalendar.isConnected(ownerEmail)
|
|
451
|
+
: false;
|
|
452
|
+
|
|
453
|
+
if (ownerEmail && !ownerConnected) {
|
|
454
|
+
return {
|
|
455
|
+
items: [],
|
|
456
|
+
unavailableReason: formatAvailabilityUnavailableReason(ownerEmail),
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (ownerConnected) {
|
|
428
461
|
try {
|
|
429
462
|
if (requiredHosts.length > 0) {
|
|
430
463
|
const freeBusy = await googleCalendar.getFreeBusy(
|
|
@@ -434,6 +467,14 @@ async function getConflictItems({
|
|
|
434
467
|
ownerEmail,
|
|
435
468
|
timezone,
|
|
436
469
|
);
|
|
470
|
+
if (freeBusy.errors.length > 0) {
|
|
471
|
+
return {
|
|
472
|
+
items: [],
|
|
473
|
+
unavailableReason: formatAvailabilityUnavailableReason(
|
|
474
|
+
freeBusy.errors[0]?.email || ownerEmail,
|
|
475
|
+
),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
437
478
|
for (const [email, calendar] of Object.entries(freeBusy.calendars)) {
|
|
438
479
|
const normalizedEmail = email.toLowerCase();
|
|
439
480
|
if (!calendar.errors || calendar.errors.length === 0) {
|
|
@@ -448,11 +489,16 @@ async function getConflictItems({
|
|
|
448
489
|
}
|
|
449
490
|
}
|
|
450
491
|
|
|
451
|
-
const { events: googleEvents } =
|
|
452
|
-
rangeStartIso,
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
492
|
+
const { events: googleEvents, errors: googleEventErrors } =
|
|
493
|
+
await googleCalendar.listEvents(rangeStartIso, rangeEndIso, ownerEmail);
|
|
494
|
+
if (googleEventErrors.length > 0) {
|
|
495
|
+
return {
|
|
496
|
+
items: [],
|
|
497
|
+
unavailableReason: formatAvailabilityUnavailableReason(
|
|
498
|
+
googleEventErrors[0]?.email || ownerEmail,
|
|
499
|
+
),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
456
502
|
conflictItems.push(
|
|
457
503
|
...googleEvents.filter(eventBlocksAvailability).map((event) => ({
|
|
458
504
|
start: event.start,
|
|
@@ -460,7 +506,10 @@ async function getConflictItems({
|
|
|
460
506
|
})),
|
|
461
507
|
);
|
|
462
508
|
} catch {
|
|
463
|
-
|
|
509
|
+
return {
|
|
510
|
+
items: [],
|
|
511
|
+
unavailableReason: formatAvailabilityUnavailableReason(ownerEmail),
|
|
512
|
+
};
|
|
464
513
|
}
|
|
465
514
|
}
|
|
466
515
|
|
|
@@ -501,7 +550,7 @@ async function getConflictItems({
|
|
|
501
550
|
return { items: conflictItems };
|
|
502
551
|
}
|
|
503
552
|
|
|
504
|
-
function generateAvailableSlotsForDate({
|
|
553
|
+
export function generateAvailableSlotsForDate({
|
|
505
554
|
date,
|
|
506
555
|
duration,
|
|
507
556
|
config,
|
|
@@ -571,7 +620,17 @@ function generateAvailableSlotsForDate({
|
|
|
571
620
|
const slotEnd = zonedTimeToUtc(date, scheduleSlot.end, timezone);
|
|
572
621
|
if (slotEnd <= slotStart) continue;
|
|
573
622
|
|
|
574
|
-
|
|
623
|
+
const scheduleStartMinutes = startHour * 60 + startMin;
|
|
624
|
+
const firstSlotStartMinutes =
|
|
625
|
+
Math.ceil(scheduleStartMinutes / BOOKING_SLOT_STEP_MINUTES) *
|
|
626
|
+
BOOKING_SLOT_STEP_MINUTES;
|
|
627
|
+
if (firstSlotStartMinutes >= 24 * 60) continue;
|
|
628
|
+
|
|
629
|
+
let current = zonedTimeToUtc(
|
|
630
|
+
date,
|
|
631
|
+
formatLocalTime(firstSlotStartMinutes),
|
|
632
|
+
timezone,
|
|
633
|
+
);
|
|
575
634
|
|
|
576
635
|
while (current.getTime() + slotDuration * 60 * 1000 <= slotEnd.getTime()) {
|
|
577
636
|
const candidateStart = new Date(current);
|
|
@@ -598,7 +657,9 @@ function generateAvailableSlotsForDate({
|
|
|
598
657
|
});
|
|
599
658
|
}
|
|
600
659
|
|
|
601
|
-
current = new Date(
|
|
660
|
+
current = new Date(
|
|
661
|
+
current.getTime() + BOOKING_SLOT_STEP_MINUTES * 60 * 1000,
|
|
662
|
+
);
|
|
602
663
|
}
|
|
603
664
|
}
|
|
604
665
|
|
|
@@ -1147,7 +1208,9 @@ export const getAvailableSlots = defineEventHandler(async (event: H3Event) => {
|
|
|
1147
1208
|
rangeEndIso: dateEndIso(rangeEnd, timezone),
|
|
1148
1209
|
timezone,
|
|
1149
1210
|
});
|
|
1150
|
-
if (conflictResult.unavailableReason)
|
|
1211
|
+
if (conflictResult.unavailableReason) {
|
|
1212
|
+
return unavailableAvailabilityResponse(event);
|
|
1213
|
+
}
|
|
1151
1214
|
const dates: string[] = [];
|
|
1152
1215
|
for (
|
|
1153
1216
|
let cursor = new Date(from!);
|
|
@@ -1177,7 +1240,9 @@ export const getAvailableSlots = defineEventHandler(async (event: H3Event) => {
|
|
|
1177
1240
|
rangeEndIso: dateEndIso(date, timezone),
|
|
1178
1241
|
timezone,
|
|
1179
1242
|
});
|
|
1180
|
-
if (conflictResult.unavailableReason)
|
|
1243
|
+
if (conflictResult.unavailableReason) {
|
|
1244
|
+
return unavailableAvailabilityResponse(event);
|
|
1245
|
+
}
|
|
1181
1246
|
const availableSlots = generateAvailableSlotsForDate({
|
|
1182
1247
|
date,
|
|
1183
1248
|
duration,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
isElectron,
|
|
6
6
|
getAppUrl,
|
|
7
7
|
resolveGoogleSignInCredentials,
|
|
8
|
+
resolveGoogleProviderCredentials,
|
|
8
9
|
resolveOAuthRedirectUri,
|
|
9
10
|
encodeOAuthState,
|
|
10
11
|
decodeOAuthState,
|
|
@@ -74,8 +75,8 @@ async function resolveCalendarOAuthCredentials(event: H3Event) {
|
|
|
74
75
|
clientSecret: await resolveSecret("GOOGLE_CLIENT_SECRET"),
|
|
75
76
|
}),
|
|
76
77
|
);
|
|
77
|
-
if (
|
|
78
|
-
return
|
|
78
|
+
if (clientId && clientSecret) return { clientId, clientSecret };
|
|
79
|
+
return resolveGoogleProviderCredentials();
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
function isCalendarConnectRequest(
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
getRequestOrgId,
|
|
11
11
|
resolveSecret,
|
|
12
12
|
runWithRequestContext,
|
|
13
|
+
resolveGoogleProviderCredentials,
|
|
14
|
+
resolveGoogleLegacyProviderCredentials,
|
|
13
15
|
} from "@agent-native/core/server";
|
|
14
16
|
|
|
15
17
|
import type {
|
|
@@ -95,8 +97,20 @@ async function readCredentialPair(
|
|
|
95
97
|
resolveSecret(clientIdKey),
|
|
96
98
|
resolveSecret(clientSecretKey),
|
|
97
99
|
]);
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
+
if (clientId && clientSecret) return { clientId, clientSecret };
|
|
101
|
+
if (
|
|
102
|
+
clientIdKey === "GOOGLE_CLIENT_ID" &&
|
|
103
|
+
clientSecretKey === "GOOGLE_CLIENT_SECRET"
|
|
104
|
+
) {
|
|
105
|
+
return resolveGoogleProviderCredentials();
|
|
106
|
+
}
|
|
107
|
+
if (
|
|
108
|
+
clientIdKey === "GOOGLE_LEGACY_CLIENT_ID" &&
|
|
109
|
+
clientSecretKey === "GOOGLE_LEGACY_CLIENT_SECRET"
|
|
110
|
+
) {
|
|
111
|
+
return resolveGoogleLegacyProviderCredentials();
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
async function resolveGoogleProviderCredentialCandidates(
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const DEFAULT_OBJECT_ENTRY_LIMIT = 8;
|
|
2
|
+
|
|
3
|
+
export function formatDesignTokenValue(value: unknown): string | undefined {
|
|
4
|
+
return formatTokenValue(value, new Set());
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getCssColorToken(value: unknown): string | undefined {
|
|
8
|
+
if (typeof value === "string") {
|
|
9
|
+
const trimmed = value.trim();
|
|
10
|
+
return trimmed || undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
for (const nested of Object.values(value)) {
|
|
18
|
+
const candidate = getCssColorToken(nested);
|
|
19
|
+
if (candidate) return candidate;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function formatTokenValue(
|
|
26
|
+
value: unknown,
|
|
27
|
+
seenObjects: Set<object>,
|
|
28
|
+
): string | undefined {
|
|
29
|
+
if (value === null || value === undefined) return undefined;
|
|
30
|
+
|
|
31
|
+
if (typeof value === "string") {
|
|
32
|
+
const trimmed = value.trim();
|
|
33
|
+
return trimmed || undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
37
|
+
return String(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (Array.isArray(value)) {
|
|
41
|
+
const parts = value
|
|
42
|
+
.map((item) => formatTokenValue(item, seenObjects))
|
|
43
|
+
.filter((item): item is string => Boolean(item));
|
|
44
|
+
return parts.length > 0 ? parts.join(", ") : undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof value !== "object") return undefined;
|
|
48
|
+
|
|
49
|
+
if (seenObjects.has(value)) return undefined;
|
|
50
|
+
seenObjects.add(value);
|
|
51
|
+
|
|
52
|
+
const entries = Object.entries(value)
|
|
53
|
+
.map(([key, nestedValue]) => {
|
|
54
|
+
const formatted = formatTokenValue(nestedValue, seenObjects);
|
|
55
|
+
return formatted ? `${labelizeDesignTokenKey(key)}: ${formatted}` : null;
|
|
56
|
+
})
|
|
57
|
+
.filter((entry): entry is string => Boolean(entry))
|
|
58
|
+
.slice(0, DEFAULT_OBJECT_ENTRY_LIMIT);
|
|
59
|
+
|
|
60
|
+
seenObjects.delete(value);
|
|
61
|
+
return entries.length > 0 ? entries.join(", ") : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function labelizeDesignTokenKey(key: string) {
|
|
65
|
+
return key
|
|
66
|
+
.replace(/([A-Z])/g, " $1")
|
|
67
|
+
.replace(/[-_]/g, " ")
|
|
68
|
+
.replace(/^./, (char) => char.toUpperCase());
|
|
69
|
+
}
|
|
@@ -65,6 +65,10 @@ import {
|
|
|
65
65
|
TooltipContent,
|
|
66
66
|
TooltipTrigger,
|
|
67
67
|
} from "@/components/ui/tooltip";
|
|
68
|
+
import {
|
|
69
|
+
formatDesignTokenValue,
|
|
70
|
+
getCssColorToken,
|
|
71
|
+
} from "@/lib/design-system-preview";
|
|
68
72
|
|
|
69
73
|
interface DesignSystem {
|
|
70
74
|
id: string;
|
|
@@ -83,25 +87,25 @@ interface DesignSystem {
|
|
|
83
87
|
|
|
84
88
|
interface DesignSystemData {
|
|
85
89
|
colors?: {
|
|
86
|
-
primary?:
|
|
87
|
-
secondary?:
|
|
88
|
-
accent?:
|
|
89
|
-
background?:
|
|
90
|
-
surface?:
|
|
91
|
-
text?:
|
|
92
|
-
textMuted?:
|
|
90
|
+
primary?: unknown;
|
|
91
|
+
secondary?: unknown;
|
|
92
|
+
accent?: unknown;
|
|
93
|
+
background?: unknown;
|
|
94
|
+
surface?: unknown;
|
|
95
|
+
text?: unknown;
|
|
96
|
+
textMuted?: unknown;
|
|
93
97
|
};
|
|
94
98
|
typography?: {
|
|
95
|
-
headingFont?:
|
|
96
|
-
bodyFont?:
|
|
97
|
-
headingWeight?:
|
|
98
|
-
bodyWeight?:
|
|
99
|
+
headingFont?: unknown;
|
|
100
|
+
bodyFont?: unknown;
|
|
101
|
+
headingWeight?: unknown;
|
|
102
|
+
bodyWeight?: unknown;
|
|
99
103
|
};
|
|
100
|
-
spacing?: Record<string,
|
|
101
|
-
borders?: Record<string,
|
|
104
|
+
spacing?: Record<string, unknown>;
|
|
105
|
+
borders?: Record<string, unknown>;
|
|
102
106
|
logos?: Array<{ url?: string; name?: string; variant?: string }>;
|
|
103
|
-
defaults?: Record<string,
|
|
104
|
-
notes?:
|
|
107
|
+
defaults?: Record<string, unknown>;
|
|
108
|
+
notes?: unknown;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
export default function DesignSystems() {
|
|
@@ -474,6 +478,12 @@ export default function DesignSystems() {
|
|
|
474
478
|
{designSystems.map((ds) => {
|
|
475
479
|
const parsed = parseData(ds.data);
|
|
476
480
|
const colors = parsed?.colors;
|
|
481
|
+
const primaryColor = getCssColorToken(colors?.primary);
|
|
482
|
+
const secondaryColor = getCssColorToken(colors?.secondary);
|
|
483
|
+
const accentColor = getCssColorToken(colors?.accent);
|
|
484
|
+
const headingFont = formatDesignTokenValue(
|
|
485
|
+
parsed?.typography?.headingFont,
|
|
486
|
+
);
|
|
477
487
|
const isSelected = selectedSystemIds.has(ds.id);
|
|
478
488
|
return (
|
|
479
489
|
<div
|
|
@@ -498,29 +508,27 @@ export default function DesignSystems() {
|
|
|
498
508
|
>
|
|
499
509
|
{/* Color preview */}
|
|
500
510
|
<div className="aspect-video bg-muted/50 flex items-center justify-center gap-2 p-4">
|
|
501
|
-
{
|
|
511
|
+
{primaryColor && (
|
|
502
512
|
<div
|
|
503
513
|
className="w-10 h-10 rounded-lg"
|
|
504
|
-
style={{ backgroundColor:
|
|
514
|
+
style={{ backgroundColor: primaryColor }}
|
|
505
515
|
/>
|
|
506
516
|
)}
|
|
507
|
-
{
|
|
517
|
+
{secondaryColor && (
|
|
508
518
|
<div
|
|
509
519
|
className="w-10 h-10 rounded-lg"
|
|
510
|
-
style={{ backgroundColor:
|
|
520
|
+
style={{ backgroundColor: secondaryColor }}
|
|
511
521
|
/>
|
|
512
522
|
)}
|
|
513
|
-
{
|
|
523
|
+
{accentColor && (
|
|
514
524
|
<div
|
|
515
525
|
className="w-10 h-10 rounded-lg"
|
|
516
|
-
style={{ backgroundColor:
|
|
526
|
+
style={{ backgroundColor: accentColor }}
|
|
517
527
|
/>
|
|
518
528
|
)}
|
|
519
|
-
{!
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
<IconPalette className="w-8 h-8 text-muted-foreground/40" />
|
|
523
|
-
)}
|
|
529
|
+
{!primaryColor && !secondaryColor && !accentColor && (
|
|
530
|
+
<IconPalette className="w-8 h-8 text-muted-foreground/40" />
|
|
531
|
+
)}
|
|
524
532
|
</div>
|
|
525
533
|
<div className="p-4 pb-3">
|
|
526
534
|
<div className="flex items-center gap-2 mb-1">
|
|
@@ -533,9 +541,9 @@ export default function DesignSystems() {
|
|
|
533
541
|
</span>
|
|
534
542
|
)}
|
|
535
543
|
</div>
|
|
536
|
-
{
|
|
544
|
+
{headingFont && (
|
|
537
545
|
<div className="text-xs text-muted-foreground/70">
|
|
538
|
-
{
|
|
546
|
+
{headingFont}
|
|
539
547
|
</div>
|
|
540
548
|
)}
|
|
541
549
|
</div>
|
|
@@ -885,10 +893,12 @@ function TokenPreview({
|
|
|
885
893
|
key={color.label}
|
|
886
894
|
className="flex min-w-0 items-center gap-3 rounded-lg border border-border bg-muted/30 p-2"
|
|
887
895
|
>
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
896
|
+
{color.swatch ? (
|
|
897
|
+
<div
|
|
898
|
+
className="h-9 w-9 shrink-0 rounded-md border border-border"
|
|
899
|
+
style={{ backgroundColor: color.swatch }}
|
|
900
|
+
/>
|
|
901
|
+
) : null}
|
|
892
902
|
<div className="min-w-0">
|
|
893
903
|
<div className="text-xs font-medium text-foreground">
|
|
894
904
|
{color.label}
|
|
@@ -1001,34 +1011,47 @@ function getColorTokens(data: DesignSystemData | null, t: DesignT) {
|
|
|
1001
1011
|
return [
|
|
1002
1012
|
{
|
|
1003
1013
|
label: t("designSystems.tokenPreview.colorLabels.primary"),
|
|
1004
|
-
value: colors.primary,
|
|
1014
|
+
value: formatDesignTokenValue(colors.primary),
|
|
1015
|
+
swatch: getCssColorToken(colors.primary),
|
|
1005
1016
|
},
|
|
1006
1017
|
{
|
|
1007
1018
|
label: t("designSystems.tokenPreview.colorLabels.secondary"),
|
|
1008
|
-
value: colors.secondary,
|
|
1019
|
+
value: formatDesignTokenValue(colors.secondary),
|
|
1020
|
+
swatch: getCssColorToken(colors.secondary),
|
|
1009
1021
|
},
|
|
1010
1022
|
{
|
|
1011
1023
|
label: t("designSystems.tokenPreview.colorLabels.accent"),
|
|
1012
|
-
value: colors.accent,
|
|
1024
|
+
value: formatDesignTokenValue(colors.accent),
|
|
1025
|
+
swatch: getCssColorToken(colors.accent),
|
|
1013
1026
|
},
|
|
1014
1027
|
{
|
|
1015
1028
|
label: t("designSystems.tokenPreview.colorLabels.background"),
|
|
1016
|
-
value: colors.background,
|
|
1029
|
+
value: formatDesignTokenValue(colors.background),
|
|
1030
|
+
swatch: getCssColorToken(colors.background),
|
|
1017
1031
|
},
|
|
1018
1032
|
{
|
|
1019
1033
|
label: t("designSystems.tokenPreview.colorLabels.surface"),
|
|
1020
|
-
value: colors.surface,
|
|
1034
|
+
value: formatDesignTokenValue(colors.surface),
|
|
1035
|
+
swatch: getCssColorToken(colors.surface),
|
|
1021
1036
|
},
|
|
1022
1037
|
{
|
|
1023
1038
|
label: t("designSystems.tokenPreview.colorLabels.text"),
|
|
1024
|
-
value: colors.text,
|
|
1039
|
+
value: formatDesignTokenValue(colors.text),
|
|
1040
|
+
swatch: getCssColorToken(colors.text),
|
|
1025
1041
|
},
|
|
1026
1042
|
{
|
|
1027
1043
|
label: t("designSystems.tokenPreview.colorLabels.mutedText"),
|
|
1028
|
-
value: colors.textMuted,
|
|
1044
|
+
value: formatDesignTokenValue(colors.textMuted),
|
|
1045
|
+
swatch: getCssColorToken(colors.textMuted),
|
|
1029
1046
|
},
|
|
1030
|
-
].filter(
|
|
1031
|
-
|
|
1047
|
+
].filter(
|
|
1048
|
+
(
|
|
1049
|
+
item,
|
|
1050
|
+
): item is {
|
|
1051
|
+
label: string;
|
|
1052
|
+
value: string;
|
|
1053
|
+
swatch: string | undefined;
|
|
1054
|
+
} => Boolean(item.value),
|
|
1032
1055
|
);
|
|
1033
1056
|
}
|
|
1034
1057
|
|
|
@@ -1038,19 +1061,19 @@ function getTypographyTokens(data: DesignSystemData | null, t: DesignT) {
|
|
|
1038
1061
|
return [
|
|
1039
1062
|
{
|
|
1040
1063
|
label: t("designSystems.tokenPreview.typeLabels.headingFont"),
|
|
1041
|
-
value: typography.headingFont,
|
|
1064
|
+
value: formatDesignTokenValue(typography.headingFont),
|
|
1042
1065
|
},
|
|
1043
1066
|
{
|
|
1044
1067
|
label: t("designSystems.tokenPreview.typeLabels.bodyFont"),
|
|
1045
|
-
value: typography.bodyFont,
|
|
1068
|
+
value: formatDesignTokenValue(typography.bodyFont),
|
|
1046
1069
|
},
|
|
1047
1070
|
{
|
|
1048
1071
|
label: t("designSystems.tokenPreview.typeLabels.headingWeight"),
|
|
1049
|
-
value: typography.headingWeight,
|
|
1072
|
+
value: formatDesignTokenValue(typography.headingWeight),
|
|
1050
1073
|
},
|
|
1051
1074
|
{
|
|
1052
1075
|
label: t("designSystems.tokenPreview.typeLabels.bodyWeight"),
|
|
1053
|
-
value: typography.bodyWeight,
|
|
1076
|
+
value: formatDesignTokenValue(typography.bodyWeight),
|
|
1054
1077
|
},
|
|
1055
1078
|
].filter((item): item is { label: string; value: string } =>
|
|
1056
1079
|
Boolean(item.value),
|
|
@@ -1089,12 +1112,10 @@ function getDetailTokens(
|
|
|
1089
1112
|
].filter((item): item is { label: string; value: string } => Boolean(item));
|
|
1090
1113
|
}
|
|
1091
1114
|
|
|
1092
|
-
function objectPreviewItems(
|
|
1093
|
-
prefix: string,
|
|
1094
|
-
values: Record<string, string | undefined>,
|
|
1095
|
-
) {
|
|
1115
|
+
function objectPreviewItems(prefix: string, values: Record<string, unknown>) {
|
|
1096
1116
|
return Object.entries(values)
|
|
1097
|
-
.
|
|
1117
|
+
.map(([key, value]) => [key, formatDesignTokenValue(value)] as const)
|
|
1118
|
+
.filter((entry): entry is readonly [string, string] => Boolean(entry[1]))
|
|
1098
1119
|
.slice(0, 4)
|
|
1099
1120
|
.map(([key, value]) => ({
|
|
1100
1121
|
label: `${prefix}: ${labelizeKey(key)}`,
|
|
@@ -516,7 +516,7 @@ async function gzipReplayBody(body) {
|
|
|
516
516
|
.stream()
|
|
517
517
|
.pipeThrough(new CompressionStream("gzip"));
|
|
518
518
|
const compressed = await new Response(stream).arrayBuffer();
|
|
519
|
-
return new Blob([compressed], { type: "application/
|
|
519
|
+
return new Blob([compressed], { type: "application/octet-stream" });
|
|
520
520
|
}
|
|
521
521
|
catch {
|
|
522
522
|
return null;
|
|
@@ -529,7 +529,7 @@ async function buildReplayUploadBody(body) {
|
|
|
529
529
|
body: compressed,
|
|
530
530
|
compressed: true,
|
|
531
531
|
headers: {
|
|
532
|
-
"Content-Type": "application/
|
|
532
|
+
"Content-Type": "application/octet-stream",
|
|
533
533
|
"Content-Encoding": "gzip",
|
|
534
534
|
},
|
|
535
535
|
};
|