@agent-native/core 0.138.0 → 0.140.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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/emails.ts +51 -0
- package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
- package/corpus/templates/calendar/server/lib/emails.ts +167 -0
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
- package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/clips/actions/invite-member.ts +39 -15
- package/corpus/templates/clips/server/lib/emails.ts +256 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
- package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
- package/corpus/templates/content/server/lib/emails.ts +70 -0
- package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +44 -1
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +265 -1
- package/corpus/templates/design/actions/create-design-system.ts +9 -10
- package/corpus/templates/design/actions/get-design-system.ts +53 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +5 -71
- package/corpus/templates/design/actions/index-design-tokens.ts +61 -80
- package/corpus/templates/design/actions/update-design-system.ts +7 -10
- package/corpus/templates/design/app/components/design/EditPanel.tsx +45 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +12 -0
- package/corpus/templates/design/app/components/design/edit-panel/design-system-swatches.ts +215 -0
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +10 -6
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +19 -3
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +36 -10
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +15 -0
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +19 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +6 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +53 -10
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +142 -4
- package/corpus/templates/design/app/components/design/types.ts +6 -0
- package/corpus/templates/design/app/i18n-data.ts +20 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/design/app/pages/DesignSystems.tsx +78 -1
- package/corpus/templates/design/app/pages/design-editor/html-layer-positioning.ts +6 -1
- package/corpus/templates/design/changelog/2026-08-04-design-system-tokens-show-by-name-in-the-editor.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +17 -0
- package/corpus/templates/design/server/lib/design-system-tokens.ts +35 -0
- package/corpus/templates/design/shared/authored-color-styles.ts +401 -0
- package/corpus/templates/design/shared/resolve-tweaks.ts +10 -18
- package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
- package/corpus/templates/forms/server/lib/emails.ts +52 -0
- package/corpus/templates/forms/server/lib/response-email.ts +2 -0
- package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
- package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
- package/corpus/templates/plan/server/lib/emails.ts +67 -0
- package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
- package/corpus/templates/slides/server/lib/emails.ts +40 -0
- package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
- package/dist/brand-kit/index.d.ts +1 -0
- package/dist/brand-kit/index.js +1 -0
- package/dist/brand-kit/tokens.d.ts +92 -0
- package/dist/brand-kit/tokens.js +280 -0
- package/dist/brand-kit/types.d.ts +25 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +2 -2
- package/dist/email-catalog/actions/list-email-activity.d.ts +6 -0
- package/dist/email-catalog/actions/list-email-activity.js +15 -0
- package/dist/email-catalog/actions/list-email-engagement.d.ts +6 -0
- package/dist/email-catalog/actions/list-email-engagement.js +15 -0
- package/dist/email-catalog/actions/list-email-log.d.ts +8 -0
- package/dist/email-catalog/actions/list-email-log.js +22 -0
- package/dist/email-catalog/actions/list-transactional-emails.d.ts +23 -0
- package/dist/email-catalog/actions/list-transactional-emails.js +61 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +10 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.js +24 -0
- package/dist/email-catalog/authorize.d.ts +2 -0
- package/dist/email-catalog/authorize.js +10 -0
- package/dist/email-catalog/log.d.ts +57 -0
- package/dist/email-catalog/log.js +117 -0
- package/dist/email-catalog/provider-metrics.d.ts +34 -0
- package/dist/email-catalog/provider-metrics.js +165 -0
- package/dist/email-catalog/registry.d.ts +79 -0
- package/dist/email-catalog/registry.js +71 -0
- package/dist/email-catalog/schema.d.ts +212 -0
- package/dist/email-catalog/schema.js +49 -0
- package/dist/email-catalog/system-emails.d.ts +14 -0
- package/dist/email-catalog/system-emails.js +68 -0
- package/dist/localization/default-messages.d.ts +45 -0
- package/dist/localization/default-messages.js +45 -0
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/org/handlers.js +8 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.js +22 -0
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/email.d.ts +9 -0
- package/dist/server/email.js +44 -3
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/package.json +3 -1
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
import type { PlanBundle, PlanComment } from "../../shared/types.js";
|
|
15
15
|
import { getDb, schema } from "../db/index.js";
|
|
16
16
|
|
|
17
|
+
export const PLAN_COMMENT_EMAIL_ID = "plan.plan-comment";
|
|
18
|
+
|
|
17
19
|
type CommentNotificationInput = {
|
|
18
20
|
bundle: PlanBundle;
|
|
19
21
|
insertedCommentIds: string[];
|
|
@@ -205,40 +207,64 @@ export function planCommentNotificationRecipients(input: {
|
|
|
205
207
|
return Array.from(recipients.values());
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
export function renderPlanCommentEmail(input: {
|
|
211
|
+
actor: string;
|
|
212
|
+
app: string;
|
|
211
213
|
planTitle: string;
|
|
212
|
-
|
|
214
|
+
planUrl: string;
|
|
215
|
+
message: string;
|
|
216
|
+
isReply: boolean;
|
|
217
|
+
reason: NotificationRecipient["reason"];
|
|
213
218
|
}) {
|
|
214
|
-
const actor = actorName(input.comment);
|
|
215
|
-
const app = appName();
|
|
216
|
-
const isReply = Boolean(input.comment.parentCommentId);
|
|
217
|
-
const subject = isReply
|
|
218
|
-
? `${actor} replied to a comment on "${input.planTitle}"`
|
|
219
|
-
: `${actor} commented on "${input.planTitle}"`;
|
|
220
219
|
const actionText =
|
|
221
|
-
input.
|
|
220
|
+
input.reason === "mention"
|
|
222
221
|
? "mentioned you in a comment on"
|
|
223
|
-
: input.
|
|
222
|
+
: input.reason === "plan-owner"
|
|
224
223
|
? "left a comment on your plan"
|
|
225
224
|
: "replied in a comment thread you participated in";
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
: input.
|
|
238
|
-
|
|
239
|
-
|
|
225
|
+
return {
|
|
226
|
+
subject: input.isReply
|
|
227
|
+
? `${input.actor} replied to a comment on "${input.planTitle}"`
|
|
228
|
+
: `${input.actor} commented on "${input.planTitle}"`,
|
|
229
|
+
...renderEmail({
|
|
230
|
+
preheader: `${input.actor} ${actionText} on ${input.app}.`,
|
|
231
|
+
heading: input.isReply
|
|
232
|
+
? "New reply on your plan"
|
|
233
|
+
: "New comment on your plan",
|
|
234
|
+
paragraphs: [
|
|
235
|
+
`${emailStrong(input.actor)} ${actionText} ${emailStrong(input.planTitle)}.`,
|
|
236
|
+
`Comment: "${commentExcerpt(input.message)}"`,
|
|
237
|
+
],
|
|
238
|
+
cta: { label: "Open plan", url: input.planUrl },
|
|
239
|
+
footer:
|
|
240
|
+
input.reason === "plan-owner"
|
|
241
|
+
? "You received this because you own this plan."
|
|
242
|
+
: input.reason === "mention"
|
|
243
|
+
? "You received this because you were mentioned in this comment."
|
|
244
|
+
: "You received this because you participated in this comment thread.",
|
|
245
|
+
}),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async function sendPlanCommentNotification(input: {
|
|
250
|
+
recipient: NotificationRecipient;
|
|
251
|
+
comment: PlanComment;
|
|
252
|
+
planTitle: string;
|
|
253
|
+
planId: string;
|
|
254
|
+
}) {
|
|
255
|
+
await sendEmail({
|
|
256
|
+
...renderPlanCommentEmail({
|
|
257
|
+
actor: actorName(input.comment),
|
|
258
|
+
app: appName(),
|
|
259
|
+
planTitle: input.planTitle,
|
|
260
|
+
planUrl: planUrl(input.planId),
|
|
261
|
+
message: input.comment.message,
|
|
262
|
+
isReply: Boolean(input.comment.parentCommentId),
|
|
263
|
+
reason: input.recipient.reason,
|
|
264
|
+
}),
|
|
265
|
+
to: input.recipient.email,
|
|
266
|
+
templateId: PLAN_COMMENT_EMAIL_ID,
|
|
240
267
|
});
|
|
241
|
-
await sendEmail({ to: input.recipient.email, subject, html, text });
|
|
242
268
|
}
|
|
243
269
|
|
|
244
270
|
export async function notifyPlanCommentRecipients({
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog entries for the transactional emails Plan sends.
|
|
3
|
+
*
|
|
4
|
+
* Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
|
|
5
|
+
* and preview them without the app having sent anything yet.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
PLAN_ACCESS_REQUEST_EMAIL_ID,
|
|
12
|
+
renderPlanAccessRequestEmail,
|
|
13
|
+
} from "../../actions/request-plan-access.js";
|
|
14
|
+
import {
|
|
15
|
+
PLAN_COMMENT_EMAIL_ID,
|
|
16
|
+
renderPlanCommentEmail,
|
|
17
|
+
} from "./comment-notifications.js";
|
|
18
|
+
|
|
19
|
+
let registered = false;
|
|
20
|
+
|
|
21
|
+
export function registerPlanEmails(): void {
|
|
22
|
+
if (registered) return;
|
|
23
|
+
registered = true;
|
|
24
|
+
|
|
25
|
+
defineTransactionalEmail({
|
|
26
|
+
id: PLAN_COMMENT_EMAIL_ID,
|
|
27
|
+
name: "Plan comment",
|
|
28
|
+
trigger:
|
|
29
|
+
"A human (never the agent) posts a comment or reply on a plan or recap. The subject changes for a reply and the body changes with why the recipient was picked; all variants send under this id.",
|
|
30
|
+
recipientLabel: "Owner, mentions, authors",
|
|
31
|
+
recipient:
|
|
32
|
+
"The plan owner, everyone mentioned in the comment, and — for a reply — every other human author in the same thread. The comment's own author, synthetic QA addresses, and the owner when the comment mentions the source author are all dropped. One email per remaining address.",
|
|
33
|
+
senderLabel: "Default sender",
|
|
34
|
+
sender:
|
|
35
|
+
"The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
|
|
36
|
+
preview: () =>
|
|
37
|
+
renderPlanCommentEmail({
|
|
38
|
+
actor: "Sam Rivera",
|
|
39
|
+
app: "Agent-Native Plan",
|
|
40
|
+
planTitle: "Checkout rewrite",
|
|
41
|
+
planUrl: "https://example.com/plans/plan_sample",
|
|
42
|
+
message: "Can we split the migration into two deploys?",
|
|
43
|
+
isReply: false,
|
|
44
|
+
reason: "plan-owner",
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
defineTransactionalEmail({
|
|
49
|
+
id: PLAN_ACCESS_REQUEST_EMAIL_ID,
|
|
50
|
+
name: "Plan access request",
|
|
51
|
+
trigger:
|
|
52
|
+
"A signed-in user who cannot resolve access calls `request-plan-access` on a private plan URL. Skipped when email is not configured or the requester is the owner.",
|
|
53
|
+
recipientLabel: "Plan owner",
|
|
54
|
+
recipient:
|
|
55
|
+
"The plan's `ownerEmail` column. Anonymous public viewers and guest author identities cannot reach this path.",
|
|
56
|
+
senderLabel: "Default sender",
|
|
57
|
+
sender:
|
|
58
|
+
"The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`, so the owner cannot reply straight to the requester.",
|
|
59
|
+
preview: () =>
|
|
60
|
+
renderPlanAccessRequestEmail({
|
|
61
|
+
requesterName: "Sam Rivera",
|
|
62
|
+
requesterEmail: "sam.rivera@example.com",
|
|
63
|
+
planTitle: "Checkout rewrite",
|
|
64
|
+
url: "https://example.com/plans/plan_sample",
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -21,6 +21,7 @@ import { and, eq } from "drizzle-orm";
|
|
|
21
21
|
import { getDeckUrl } from "../../actions/_app-url.js";
|
|
22
22
|
import { SLIDES_USER_PREFS_KEY } from "../../shared/slides-user-prefs.js";
|
|
23
23
|
import { getDb, schema } from "../db/index.js";
|
|
24
|
+
import { SLIDES_DECK_COMMENT_EMAIL_ID } from "./emails.js";
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* `deck-missing` stays distinct from `no-recipients`: one means the deck could
|
|
@@ -99,6 +100,41 @@ async function threadParticipants(
|
|
|
99
100
|
return rows.map((row) => row.authorEmail);
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
export function renderDeckCommentEmail({
|
|
104
|
+
actor,
|
|
105
|
+
title,
|
|
106
|
+
url,
|
|
107
|
+
content,
|
|
108
|
+
isReply,
|
|
109
|
+
}: {
|
|
110
|
+
actor: string;
|
|
111
|
+
title: string;
|
|
112
|
+
url: string;
|
|
113
|
+
content: string;
|
|
114
|
+
isReply: boolean;
|
|
115
|
+
}) {
|
|
116
|
+
return {
|
|
117
|
+
subject: isReply
|
|
118
|
+
? `${actor} replied to a comment on "${title}"`
|
|
119
|
+
: `${actor} commented on "${title}"`,
|
|
120
|
+
...renderEmail({
|
|
121
|
+
preheader: isReply
|
|
122
|
+
? `${actor} replied to a comment on ${title}.`
|
|
123
|
+
: `${actor} commented on ${title}.`,
|
|
124
|
+
heading: isReply ? "New reply on your deck" : "New comment",
|
|
125
|
+
paragraphs: [
|
|
126
|
+
isReply
|
|
127
|
+
? `${emailStrong(actor)} replied in a comment thread on ${emailStrong(title)}.`
|
|
128
|
+
: `${emailStrong(actor)} commented on ${emailStrong(title)}.`,
|
|
129
|
+
`"${excerpt(content)}"`,
|
|
130
|
+
],
|
|
131
|
+
cta: { label: "Open deck", url },
|
|
132
|
+
footer:
|
|
133
|
+
"You received this because you own or participated in this thread. Turn these off in Slides settings.",
|
|
134
|
+
}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
102
138
|
export async function notifyDeckComment(input: {
|
|
103
139
|
deckId: string;
|
|
104
140
|
slideId: string;
|
|
@@ -153,29 +189,16 @@ async function deliverDeckCommentEmails(input: {
|
|
|
153
189
|
preferenceKey: SLIDES_USER_PREFS_KEY,
|
|
154
190
|
logLabel: LOG_LABEL,
|
|
155
191
|
send: async (to) => {
|
|
156
|
-
const { html, text } = renderEmail({
|
|
157
|
-
preheader: input.isReply
|
|
158
|
-
? `${actor} replied to a comment on ${deck.title}.`
|
|
159
|
-
: `${actor} commented on ${deck.title}.`,
|
|
160
|
-
heading: input.isReply ? "New reply on your deck" : "New comment",
|
|
161
|
-
paragraphs: [
|
|
162
|
-
input.isReply
|
|
163
|
-
? `${emailStrong(actor)} replied in a comment thread on ${emailStrong(deck.title)}.`
|
|
164
|
-
: `${emailStrong(actor)} commented on ${emailStrong(deck.title)}.`,
|
|
165
|
-
`"${excerpt(input.content)}"`,
|
|
166
|
-
],
|
|
167
|
-
cta: { label: "Open deck", url },
|
|
168
|
-
footer:
|
|
169
|
-
"You received this because you own or participated in this thread. Turn these off in Slides settings.",
|
|
170
|
-
});
|
|
171
|
-
|
|
172
192
|
await sendEmail({
|
|
193
|
+
...renderDeckCommentEmail({
|
|
194
|
+
actor,
|
|
195
|
+
title: deck.title,
|
|
196
|
+
url,
|
|
197
|
+
content: input.content,
|
|
198
|
+
isReply: input.isReply,
|
|
199
|
+
}),
|
|
173
200
|
to,
|
|
174
|
-
|
|
175
|
-
? `${actor} replied to a comment on "${deck.title}"`
|
|
176
|
-
: `${actor} commented on "${deck.title}"`,
|
|
177
|
-
html,
|
|
178
|
-
text,
|
|
201
|
+
templateId: SLIDES_DECK_COMMENT_EMAIL_ID,
|
|
179
202
|
});
|
|
180
203
|
},
|
|
181
204
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog entries for the transactional emails Slides sends.
|
|
3
|
+
*
|
|
4
|
+
* Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
|
|
5
|
+
* and preview them without the app having sent anything yet.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
|
|
9
|
+
|
|
10
|
+
import { renderDeckCommentEmail } from "./comment-notifications.js";
|
|
11
|
+
|
|
12
|
+
export const SLIDES_DECK_COMMENT_EMAIL_ID = "slides.deck-comment";
|
|
13
|
+
|
|
14
|
+
let registered = false;
|
|
15
|
+
|
|
16
|
+
export function registerSlidesEmails(): void {
|
|
17
|
+
if (registered) return;
|
|
18
|
+
registered = true;
|
|
19
|
+
|
|
20
|
+
defineTransactionalEmail({
|
|
21
|
+
id: SLIDES_DECK_COMMENT_EMAIL_ID,
|
|
22
|
+
name: "Deck comment",
|
|
23
|
+
trigger:
|
|
24
|
+
"Someone posts a comment or a thread reply on a slide. Subject and copy differ slightly for a reply; both send under this id.",
|
|
25
|
+
recipientLabel: "Deck owner and authors",
|
|
26
|
+
recipient:
|
|
27
|
+
"The deck owner, plus every prior author in the thread when the new comment is a reply. The list is re-checked against the deck's live ACL and filtered by each user's `emailNotifications` preference; the comment's own author never receives it.",
|
|
28
|
+
senderLabel: "Default sender",
|
|
29
|
+
sender:
|
|
30
|
+
"The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
|
|
31
|
+
preview: () =>
|
|
32
|
+
renderDeckCommentEmail({
|
|
33
|
+
actor: "Sam Rivera",
|
|
34
|
+
title: "Series A narrative",
|
|
35
|
+
url: "https://example.com/decks/deck_sample?slide=3",
|
|
36
|
+
content: "Slide 3 needs the updated revenue chart before Thursday.",
|
|
37
|
+
isReply: false,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export * from "./types.js";
|
|
18
18
|
export * from "./brand-signals.js";
|
|
19
|
+
export * from "./tokens.js";
|
|
19
20
|
export { extractDesignTokensFromUrl, validateUrl, parseOwnerRepo, fetchGitHubJson, fetchGitHubJsonResult, fetchGitHubRaw, parseTailwindConfig, parseCss, detectStylingFramework, createCodeAnalysisState, analyzeCodeFile, analyzeCssFile, analyzeTailwindConfig, analyzeJsonTheme, analyzePackageJson, analyzeThemeSourceFile, addFont, extractCssVars, extractCodeColors, extractCodeFonts, extractDocumentColors, extractDocumentFonts, classifyFile, suggestionsForType, unique, MAX_FILES, MAX_FILE_SIZE, FETCH_TIMEOUT, ROOT_PATTERNS, SECONDARY_PATHS, CODE_MAX_FILES, CODE_MAX_TOTAL_BYTES, } from "../server/design-token-utils.js";
|
|
20
21
|
export type { ContentType, ParsedCss, ParsedTailwindConfig, CodeAnalysisState, UrlExtractionResult, GitHubFetchOptions, GitHubJsonResult, } from "../server/design-token-utils.js";
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/brand-kit/index.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export * from "./types.js";
|
|
18
18
|
export * from "./brand-signals.js";
|
|
19
|
+
export * from "./tokens.js";
|
|
19
20
|
// Import-source parsing + token extraction (Tailwind/CSS/GitHub/URL/document/
|
|
20
21
|
// code analysis). These already power the import-* actions across templates.
|
|
21
22
|
export {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@agent-native/core/brand-kit/tokens`
|
|
3
|
+
*
|
|
4
|
+
* Pure helpers for the named-token vocabulary a Brand Kit stores alongside its
|
|
5
|
+
* seven color roles. Kept on its own subpath (no `design-token-utils` re-export)
|
|
6
|
+
* so browser code can import the CSS-safety predicates without pulling the
|
|
7
|
+
* server-side extraction stack into the bundle.
|
|
8
|
+
*/
|
|
9
|
+
import type { BrandKitToken, BrandKitTokenType } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Upper bound on a single kit's stored vocabulary. Large systems legitimately
|
|
12
|
+
* define hundreds of tokens; this only stops an unbounded scrape landing in SQL.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MAX_BRAND_KIT_TOKENS = 500;
|
|
15
|
+
export declare function isSafeCssVarName(value: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Token values are spliced raw into `:root { … }` declarations, so anything that
|
|
18
|
+
* could terminate a declaration or break out of a `<style>` element is unsafe.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isSafeCssTokenValue(value: string): boolean;
|
|
21
|
+
export declare function isColorTokenValue(value: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Bucket a token, trusting the value's shape over the name's keywords.
|
|
24
|
+
*
|
|
25
|
+
* Name-first classification called Primer's `--text-body-size-medium: 1rem` a
|
|
26
|
+
* color because the name contains "text", which then rendered a swatch with
|
|
27
|
+
* `background: 1rem`. A dimension is never a color however the token is named.
|
|
28
|
+
*/
|
|
29
|
+
export declare function classifyBrandKitToken(name: string, value: string): BrandKitTokenType;
|
|
30
|
+
/** Title-case display name derived from a CSS var, e.g. `--primary-color`. */
|
|
31
|
+
export declare function friendlyTokenName(cssVar: string): string;
|
|
32
|
+
export type BrandKitTokenRejectionReason = "malformed" | "unsafe-css-var" | "unsafe-value" | "over-limit";
|
|
33
|
+
export interface BrandKitTokenRejection {
|
|
34
|
+
reason: BrandKitTokenRejectionReason;
|
|
35
|
+
/** Best-effort identifier for the offending entry, for error messages. */
|
|
36
|
+
label: string;
|
|
37
|
+
}
|
|
38
|
+
export interface NormalizedBrandKitTokens {
|
|
39
|
+
tokens: BrandKitToken[];
|
|
40
|
+
/**
|
|
41
|
+
* Entries that could not be stored. Callers must surface these — a kit that
|
|
42
|
+
* silently kept 4 of 40 tokens reads downstream as a 4-token design system.
|
|
43
|
+
*/
|
|
44
|
+
rejected: BrandKitTokenRejection[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Coerce untrusted token JSON into storable tokens, reporting every entry it
|
|
48
|
+
* could not accept. Later duplicates of a `cssVar` win, matching the overlay
|
|
49
|
+
* order importers use.
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeBrandKitTokens(input: unknown): NormalizedBrandKitTokens;
|
|
52
|
+
/** Human-readable summary of why tokens were refused, for thrown errors. */
|
|
53
|
+
export declare function describeBrandKitTokenRejections(rejected: readonly BrandKitTokenRejection[]): string;
|
|
54
|
+
/**
|
|
55
|
+
* The seven colour roles plus radius/spacing, as tokens. Derived from a kit's
|
|
56
|
+
* summary fields rather than named by the source system, so they carry no
|
|
57
|
+
* `group`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function brandKitRoleTokens(data: {
|
|
60
|
+
colors?: object | null;
|
|
61
|
+
borders?: {
|
|
62
|
+
radius?: string;
|
|
63
|
+
} | null;
|
|
64
|
+
spacing?: object | null;
|
|
65
|
+
} | null | undefined, source?: string): BrandKitToken[];
|
|
66
|
+
/**
|
|
67
|
+
* Read a kit's named tokens out of a raw CSS block. A kit's `customCSS` already
|
|
68
|
+
* spells out the source system's real token names. Declaration order wins on
|
|
69
|
+
* duplicates, matching the cascade.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseBrandKitTokensFromCss(css: string, source?: string): BrandKitToken[];
|
|
72
|
+
/**
|
|
73
|
+
* The kit's named vocabulary: its stored `tokens` when it has them, else the
|
|
74
|
+
* names its `customCSS` declares. Kits predating `tokens` still carry real names
|
|
75
|
+
* in CSS, so reading only `tokens` would report them as having none.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveBrandKitTokens(data: {
|
|
78
|
+
tokens?: unknown;
|
|
79
|
+
customCSS?: unknown;
|
|
80
|
+
} | null | undefined, cssSource?: string): BrandKitToken[];
|
|
81
|
+
export interface BrandKitTokenGroup {
|
|
82
|
+
/** The source's own group path when it has one, else the token type. */
|
|
83
|
+
label: string;
|
|
84
|
+
type: BrandKitTokenType;
|
|
85
|
+
tokens: BrandKitToken[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Group tokens for display, preserving the source's collection paths. Groups sort
|
|
89
|
+
* by token type so colors lead, then alphabetically within a type.
|
|
90
|
+
*/
|
|
91
|
+
export declare function groupBrandKitTokens(tokens: readonly BrandKitToken[]): BrandKitTokenGroup[];
|
|
92
|
+
//# sourceMappingURL=tokens.d.ts.map
|