@agent-native/core 0.140.0 → 0.141.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/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-stay-complete-and-atomic.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +0 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +8 -18
- package/corpus/templates/analytics/server/plugins/db.ts +174 -0
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +38 -38
- package/corpus/templates/calendar/changelog/2026-08-05-out-of-office-blocks-now-open-from-their-scheduled-time-rang.md +6 -0
- package/corpus/templates/calendar/server/lib/booking-emails.ts +70 -154
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +28 -64
- package/corpus/templates/clips/actions/get-recording-player-data.ts +1 -0
- package/corpus/templates/clips/actions/invite-member.ts +16 -39
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +2 -3
- package/corpus/templates/clips/app/components/player/reaction-emojis.ts +10 -0
- package/corpus/templates/clips/app/components/player/reactions-tray.tsx +2 -2
- package/corpus/templates/clips/app/components/player/video-player.tsx +20 -6
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +33 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +5 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +27 -1
- package/corpus/templates/clips/changelog/2026-08-05-comment-and-video-reaction-pickers-now-include-eyes-and-mind.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-05-fresh-recordings-now-open-with-the-complete-video.md +6 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +0 -24
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +26 -57
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +1 -44
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1 -265
- package/corpus/templates/design/actions/create-design-system.ts +10 -9
- package/corpus/templates/design/actions/get-design-system.ts +0 -53
- package/corpus/templates/design/actions/import-design-tokens.ts +71 -5
- package/corpus/templates/design/actions/index-design-tokens.ts +80 -61
- package/corpus/templates/design/actions/update-design-system.ts +10 -7
- package/corpus/templates/design/app/components/design/EditPanel.tsx +2 -45
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +0 -12
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +6 -10
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +3 -19
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +10 -36
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +0 -15
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +1 -19
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +0 -6
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +23 -53
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +4 -142
- package/corpus/templates/design/app/components/design/types.ts +0 -6
- package/corpus/templates/design/app/i18n-data.ts +0 -20
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/design/app/pages/DesignSystems.tsx +1 -78
- package/corpus/templates/design/app/pages/design-editor/html-layer-positioning.ts +1 -6
- package/corpus/templates/design/e2e/helpers.ts +0 -17
- package/corpus/templates/design/shared/resolve-tweaks.ts +18 -10
- package/corpus/templates/forms/server/lib/response-email.ts +0 -2
- package/corpus/templates/plan/actions/request-plan-access.ts +12 -33
- package/corpus/templates/plan/server/lib/comment-notifications.ts +27 -53
- package/corpus/templates/slides/server/lib/comment-notifications.ts +21 -44
- package/dist/a2a/handlers.js +9 -10
- package/dist/brand-kit/index.d.ts +0 -1
- package/dist/brand-kit/index.js +0 -1
- package/dist/brand-kit/types.d.ts +0 -25
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.js +8 -8
- package/dist/db/migrations.js +39 -19
- package/dist/localization/default-messages.d.ts +0 -45
- package/dist/localization/default-messages.js +0 -45
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.js +1 -8
- 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/secrets/routes.d.ts +9 -9
- package/dist/server/action-discovery.js +0 -22
- package/dist/server/auth.js +3 -1
- package/dist/server/better-auth-instance.js +2 -17
- package/dist/server/email.d.ts +0 -9
- package/dist/server/email.js +3 -44
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +0 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +3 -2
- package/docs/content/authentication.mdx +25 -19
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +3 -2
- package/corpus/templates/analytics/server/lib/emails.ts +0 -51
- package/corpus/templates/analytics/server/plugins/transactional-emails.ts +0 -5
- package/corpus/templates/calendar/server/lib/emails.ts +0 -167
- package/corpus/templates/calendar/server/plugins/transactional-emails.ts +0 -5
- package/corpus/templates/clips/server/lib/emails.ts +0 -256
- package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +0 -5
- package/corpus/templates/content/server/lib/emails.ts +0 -70
- package/corpus/templates/content/server/plugins/transactional-emails.ts +0 -5
- package/corpus/templates/design/app/components/design/edit-panel/design-system-swatches.ts +0 -215
- package/corpus/templates/design/changelog/2026-08-04-design-system-tokens-show-by-name-in-the-editor.md +0 -6
- package/corpus/templates/design/server/lib/design-system-tokens.ts +0 -35
- package/corpus/templates/design/shared/authored-color-styles.ts +0 -401
- package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +0 -4
- package/corpus/templates/dispatch/app/routes/transactional-email.tsx +0 -4
- package/corpus/templates/forms/server/lib/emails.ts +0 -52
- package/corpus/templates/forms/server/plugins/transactional-emails.ts +0 -5
- package/corpus/templates/plan/server/lib/emails.ts +0 -67
- package/corpus/templates/plan/server/plugins/transactional-emails.ts +0 -5
- package/corpus/templates/slides/server/lib/emails.ts +0 -40
- package/corpus/templates/slides/server/plugins/transactional-emails.ts +0 -5
- package/dist/brand-kit/tokens.d.ts +0 -92
- package/dist/brand-kit/tokens.js +0 -280
- package/dist/email-catalog/actions/list-email-activity.d.ts +0 -6
- package/dist/email-catalog/actions/list-email-activity.js +0 -15
- package/dist/email-catalog/actions/list-email-engagement.d.ts +0 -6
- package/dist/email-catalog/actions/list-email-engagement.js +0 -15
- package/dist/email-catalog/actions/list-email-log.d.ts +0 -8
- package/dist/email-catalog/actions/list-email-log.js +0 -22
- package/dist/email-catalog/actions/list-transactional-emails.d.ts +0 -23
- package/dist/email-catalog/actions/list-transactional-emails.js +0 -61
- package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +0 -10
- package/dist/email-catalog/actions/render-transactional-email-preview.js +0 -24
- package/dist/email-catalog/authorize.d.ts +0 -2
- package/dist/email-catalog/authorize.js +0 -10
- package/dist/email-catalog/log.d.ts +0 -57
- package/dist/email-catalog/log.js +0 -117
- package/dist/email-catalog/provider-metrics.d.ts +0 -34
- package/dist/email-catalog/provider-metrics.js +0 -165
- package/dist/email-catalog/registry.d.ts +0 -79
- package/dist/email-catalog/registry.js +0 -71
- package/dist/email-catalog/schema.d.ts +0 -212
- package/dist/email-catalog/schema.js +0 -49
- package/dist/email-catalog/system-emails.d.ts +0 -14
- package/dist/email-catalog/system-emails.js +0 -68
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Read the colour each property was authored with, walking the cascade. A
|
|
3
|
-
* generated design styles through classes, so `el.style` is empty and computed
|
|
4
|
-
* has already flattened `var()`. Dependency-free: bundled into the bridge.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const AUTHORED_COLOR_PROPERTIES = [
|
|
8
|
-
"color",
|
|
9
|
-
"backgroundColor",
|
|
10
|
-
"borderColor",
|
|
11
|
-
"outlineColor",
|
|
12
|
-
// Not colours themselves, but the only place a shadow's colour keeps its name.
|
|
13
|
-
"boxShadow",
|
|
14
|
-
"textShadow",
|
|
15
|
-
] as const;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* A shorthand holding `var()` cannot be expanded, so CSSOM serialises its
|
|
19
|
-
* longhands as "" — indistinguishable from unset.
|
|
20
|
-
*/
|
|
21
|
-
const SHORTHAND_FALLBACK: Record<string, string> = {
|
|
22
|
-
backgroundColor: "background",
|
|
23
|
-
borderColor: "border",
|
|
24
|
-
outlineColor: "outline",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/** Colours these inherit from an ancestor when no rule targets the element. */
|
|
28
|
-
const INHERITED_PROPERTIES = ["color"];
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Expanding a shorthand emits these for the longhands it resets, so treating
|
|
32
|
-
* them as authored would print "initial" in the fill row.
|
|
33
|
-
*/
|
|
34
|
-
const RESET_KEYWORDS = new Set([
|
|
35
|
-
"initial",
|
|
36
|
-
"inherit",
|
|
37
|
-
"unset",
|
|
38
|
-
"revert",
|
|
39
|
-
"revert-layer",
|
|
40
|
-
]);
|
|
41
|
-
|
|
42
|
-
function isAuthoredColor(value: unknown): value is string {
|
|
43
|
-
return (
|
|
44
|
-
typeof value === "string" &&
|
|
45
|
-
value !== "" &&
|
|
46
|
-
!RESET_KEYWORDS.has(value.trim().toLowerCase())
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const LINE_STYLE_KEYWORDS = new Set([
|
|
51
|
-
"none",
|
|
52
|
-
"hidden",
|
|
53
|
-
"solid",
|
|
54
|
-
"dashed",
|
|
55
|
-
"dotted",
|
|
56
|
-
"double",
|
|
57
|
-
"groove",
|
|
58
|
-
"ridge",
|
|
59
|
-
"inset",
|
|
60
|
-
"outset",
|
|
61
|
-
]);
|
|
62
|
-
|
|
63
|
-
const LINE_WIDTH = /^(thin|medium|thick|-?\d*\.?\d+[a-z%]*)$/i;
|
|
64
|
-
|
|
65
|
-
/** Split on spaces outside parentheses, so a `var()` fallback stays intact. */
|
|
66
|
-
function splitTopLevel(value: string): string[] {
|
|
67
|
-
const parts: string[] = [];
|
|
68
|
-
let depth = 0;
|
|
69
|
-
let current = "";
|
|
70
|
-
for (const char of value) {
|
|
71
|
-
if (char === "(") depth += 1;
|
|
72
|
-
else if (char === ")") depth -= 1;
|
|
73
|
-
if (depth === 0 && /\s/.test(char)) {
|
|
74
|
-
if (current) parts.push(current);
|
|
75
|
-
current = "";
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
current += char;
|
|
79
|
-
}
|
|
80
|
-
if (current) parts.push(current);
|
|
81
|
-
return parts;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* The colour component of a `border`/`outline` shorthand. Width and style are
|
|
86
|
-
* a closed keyword set, so whatever single value is left over is the colour —
|
|
87
|
-
* without this, `border: 1px solid var(--x)` loses its token name.
|
|
88
|
-
*/
|
|
89
|
-
function lineShorthandColor(value: string): string | null {
|
|
90
|
-
const rest = splitTopLevel(value).filter((part) => {
|
|
91
|
-
const lower = part.toLowerCase();
|
|
92
|
-
return !LINE_STYLE_KEYWORDS.has(lower) && !LINE_WIDTH.test(part);
|
|
93
|
-
});
|
|
94
|
-
return rest.length === 1 ? rest[0] : null;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* A shorthand only stands in for the colour when it isolates one. Exported for
|
|
99
|
-
* tests: a real engine leaves the longhand empty here, which happy-dom does not
|
|
100
|
-
* reproduce, so the wiring alone cannot exercise this.
|
|
101
|
-
*/
|
|
102
|
-
export function shorthandColorValue(
|
|
103
|
-
shorthand: string,
|
|
104
|
-
value: string,
|
|
105
|
-
): string | null {
|
|
106
|
-
const trimmed = value.trim();
|
|
107
|
-
if (!trimmed) return null;
|
|
108
|
-
if (/url\(|gradient\(/i.test(trimmed)) return null;
|
|
109
|
-
// A single `var()` may contain spaces (its fallback); anything else with a
|
|
110
|
-
// space is a layered shorthand, not a colour.
|
|
111
|
-
if (/^var\(.*\)$/.test(trimmed)) return trimmed;
|
|
112
|
-
if (shorthand === "border" || shorthand === "outline") {
|
|
113
|
-
return lineShorthandColor(trimmed);
|
|
114
|
-
}
|
|
115
|
-
return /\s/.test(trimmed) ? null : trimmed;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
type StyleRuleLike = {
|
|
119
|
-
selectorText?: string;
|
|
120
|
-
style?: Record<string, string> & {
|
|
121
|
-
getPropertyPriority?: (property: string) => string;
|
|
122
|
-
};
|
|
123
|
-
conditionText?: string;
|
|
124
|
-
cssRules?: ArrayLike<unknown>;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Approximate CSS specificity as one comparable number. Approximate is safe:
|
|
129
|
-
* it only orders selectors that already match, and `authoredMatchesPainted`
|
|
130
|
-
* still discards a winner that is not what paints. `:is()`/`:not()` inner
|
|
131
|
-
* specificity is not counted.
|
|
132
|
-
*/
|
|
133
|
-
function selectorSpecificity(selector: string): number {
|
|
134
|
-
const cleaned = selector
|
|
135
|
-
.replace(/\\./g, "")
|
|
136
|
-
.replace(/\[[^\]]*\]/g, " :attr ")
|
|
137
|
-
.replace(/\(([^()]*)\)/g, " ");
|
|
138
|
-
const count = (pattern: RegExp) => (cleaned.match(pattern) ?? []).length;
|
|
139
|
-
const ids = count(/#[\w-]+/g);
|
|
140
|
-
const classes = count(/\.[\w-]+/g) + count(/:(?!:)[\w-]+/g);
|
|
141
|
-
const types = count(/(?:^|[\s>+~])[a-zA-Z][\w-]*/g) + count(/::[\w-]+/g);
|
|
142
|
-
return ids * 10000 + classes * 100 + types;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** Specificity of the selector in a comma list that actually matches. */
|
|
146
|
-
function matchedSpecificity(element: Element, selectorText: string): number {
|
|
147
|
-
let best = -1;
|
|
148
|
-
for (const selector of selectorText.split(",")) {
|
|
149
|
-
const trimmed = selector.trim();
|
|
150
|
-
if (!trimmed) continue;
|
|
151
|
-
try {
|
|
152
|
-
if (!element.matches(trimmed)) continue;
|
|
153
|
-
} catch {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
best = Math.max(best, selectorSpecificity(trimmed));
|
|
157
|
-
}
|
|
158
|
-
return best;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** Above any selector: only importance can outrank an inline declaration. */
|
|
162
|
-
const INLINE_SPECIFICITY = Number.MAX_SAFE_INTEGER;
|
|
163
|
-
|
|
164
|
-
interface Candidate {
|
|
165
|
-
value: string;
|
|
166
|
-
important: boolean;
|
|
167
|
-
specificity: number;
|
|
168
|
-
order: number;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** Cascade order for declarations that all match: important, then specificity. */
|
|
172
|
-
function beats(next: Candidate, current: Candidate | undefined): boolean {
|
|
173
|
-
if (!current) return true;
|
|
174
|
-
if (next.important !== current.important) return next.important;
|
|
175
|
-
if (next.specificity !== current.specificity) {
|
|
176
|
-
return next.specificity > current.specificity;
|
|
177
|
-
}
|
|
178
|
-
return next.order >= current.order;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function readRules(
|
|
182
|
-
element: Element,
|
|
183
|
-
rules: ArrayLike<unknown> | undefined,
|
|
184
|
-
out: Record<string, Candidate>,
|
|
185
|
-
counter: { order: number },
|
|
186
|
-
): void {
|
|
187
|
-
if (!rules) return;
|
|
188
|
-
for (let index = 0; index < rules.length; index += 1) {
|
|
189
|
-
const rule = rules[index] as StyleRuleLike | undefined;
|
|
190
|
-
if (!rule) continue;
|
|
191
|
-
|
|
192
|
-
// Tested before `cssRules`: a style rule carries one too (CSS nesting), so
|
|
193
|
-
// treating anything with `cssRules` as a group skips every declaration.
|
|
194
|
-
const declaresOwnStyles = Boolean(rule.selectorText && rule.style);
|
|
195
|
-
|
|
196
|
-
if (!declaresOwnStyles) {
|
|
197
|
-
if (!rule.cssRules) continue;
|
|
198
|
-
// Any grouping rule, not just conditional ones: an `@layer` block holds
|
|
199
|
-
// cssRules with no conditionText, and Tailwind puts its utilities there.
|
|
200
|
-
// Layer precedence is not modelled, only membership.
|
|
201
|
-
if (rule.conditionText === undefined) {
|
|
202
|
-
readRules(element, rule.cssRules, out, counter);
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
// A conditional group counts only while it applies, so the walk matches
|
|
206
|
-
// what the canvas paints.
|
|
207
|
-
let applies = false;
|
|
208
|
-
try {
|
|
209
|
-
applies =
|
|
210
|
-
typeof window !== "undefined" &&
|
|
211
|
-
typeof window.matchMedia === "function"
|
|
212
|
-
? window.matchMedia(rule.conditionText).matches
|
|
213
|
-
: false;
|
|
214
|
-
} catch {
|
|
215
|
-
applies = false;
|
|
216
|
-
}
|
|
217
|
-
if (applies) readRules(element, rule.cssRules, out, counter);
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (rule.cssRules?.length) {
|
|
222
|
-
readRules(element, rule.cssRules, out, counter);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (!rule.selectorText || !rule.style) continue;
|
|
226
|
-
const specificity = matchedSpecificity(element, rule.selectorText);
|
|
227
|
-
if (specificity < 0) continue;
|
|
228
|
-
const order = counter.order++;
|
|
229
|
-
const style = rule.style;
|
|
230
|
-
const priority = (name: string) =>
|
|
231
|
-
style.getPropertyPriority?.(name) === "important";
|
|
232
|
-
|
|
233
|
-
const offer = (property: string, value: string, cssName: string) => {
|
|
234
|
-
const candidate: Candidate = {
|
|
235
|
-
value,
|
|
236
|
-
important: priority(cssName),
|
|
237
|
-
specificity,
|
|
238
|
-
order,
|
|
239
|
-
};
|
|
240
|
-
if (beats(candidate, out[property])) out[property] = candidate;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
for (const property of AUTHORED_COLOR_PROPERTIES) {
|
|
244
|
-
const declared = style[property];
|
|
245
|
-
if (isAuthoredColor(declared)) {
|
|
246
|
-
offer(property, declared, cssPropertyName(property));
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
const shorthand = SHORTHAND_FALLBACK[property];
|
|
250
|
-
if (!shorthand) continue;
|
|
251
|
-
const shorthandValue = style[shorthand];
|
|
252
|
-
if (typeof shorthandValue !== "string") continue;
|
|
253
|
-
const colorOnly = shorthandColorValue(shorthand, shorthandValue);
|
|
254
|
-
if (colorOnly) offer(property, colorOnly, shorthand);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function cssPropertyName(property: string): string {
|
|
260
|
-
return property.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Whether `authored` actually resolves to the colour the element paints.
|
|
265
|
-
*
|
|
266
|
-
* Without this an ancestor's `color: var(--color-text)` gets reported for a
|
|
267
|
-
* child painted green by its own utility class — a confidently wrong token name,
|
|
268
|
-
* which is worse than showing the hex. Resolved via a probe child so var()
|
|
269
|
-
* chains and shorthands are evaluated in the element's own scope.
|
|
270
|
-
*/
|
|
271
|
-
export function authoredMatchesPainted(
|
|
272
|
-
element: Element,
|
|
273
|
-
property: string,
|
|
274
|
-
authored: string,
|
|
275
|
-
): boolean {
|
|
276
|
-
const view = element.ownerDocument?.defaultView;
|
|
277
|
-
if (!view || typeof view.getComputedStyle !== "function") return true;
|
|
278
|
-
|
|
279
|
-
let painted = "";
|
|
280
|
-
try {
|
|
281
|
-
painted =
|
|
282
|
-
(view.getComputedStyle(element) as unknown as Record<string, string>)[
|
|
283
|
-
property
|
|
284
|
-
] ?? "";
|
|
285
|
-
} catch {
|
|
286
|
-
return true;
|
|
287
|
-
}
|
|
288
|
-
if (!painted) return true;
|
|
289
|
-
|
|
290
|
-
const probe = element.ownerDocument!.createElement("span");
|
|
291
|
-
const name = cssPropertyName(property);
|
|
292
|
-
probe.style.setProperty("display", "none");
|
|
293
|
-
probe.style.setProperty(name, authored);
|
|
294
|
-
// An unparseable value never lands, and the probe would then just inherit the
|
|
295
|
-
// element's own colour and compare equal.
|
|
296
|
-
if (!probe.style.getPropertyValue(name)) return false;
|
|
297
|
-
|
|
298
|
-
element.appendChild(probe);
|
|
299
|
-
let resolved = "";
|
|
300
|
-
try {
|
|
301
|
-
resolved =
|
|
302
|
-
(view.getComputedStyle(probe) as unknown as Record<string, string>)[
|
|
303
|
-
property
|
|
304
|
-
] ?? "";
|
|
305
|
-
} catch {
|
|
306
|
-
resolved = "";
|
|
307
|
-
}
|
|
308
|
-
probe.remove();
|
|
309
|
-
|
|
310
|
-
return resolved === "" || resolved === painted;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function collectForElement(element: Element): Record<string, string> {
|
|
314
|
-
const ranked: Record<string, Candidate> = {};
|
|
315
|
-
const counter = { order: 0 };
|
|
316
|
-
|
|
317
|
-
try {
|
|
318
|
-
const doc = element.ownerDocument;
|
|
319
|
-
// Adopted sheets are not in `styleSheets`, and a runtime CSS injector (the
|
|
320
|
-
// Tailwind CDN) puts every utility rule there.
|
|
321
|
-
const sheets = [
|
|
322
|
-
...Array.from(doc?.styleSheets ?? []),
|
|
323
|
-
...Array.from(
|
|
324
|
-
(doc as unknown as { adoptedStyleSheets?: ArrayLike<CSSStyleSheet> })
|
|
325
|
-
?.adoptedStyleSheets ?? [],
|
|
326
|
-
),
|
|
327
|
-
];
|
|
328
|
-
for (const sheet of sheets) {
|
|
329
|
-
let rules: ArrayLike<unknown> | undefined;
|
|
330
|
-
try {
|
|
331
|
-
rules = sheet.cssRules as unknown as ArrayLike<unknown>;
|
|
332
|
-
} catch {
|
|
333
|
-
// A cross-origin sheet cannot be read; skip it.
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
readRules(element, rules, ranked, counter);
|
|
337
|
-
}
|
|
338
|
-
} catch (error) {
|
|
339
|
-
// Silently losing the walk downgrades every token colour to a hex.
|
|
340
|
-
console.warn(
|
|
341
|
-
"[design] could not read stylesheets for authored colours; token names will fall back to resolved values",
|
|
342
|
-
error,
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Inline outranks any selector, but a normal inline declaration still loses
|
|
347
|
-
// to an `!important` stylesheet one — so it competes rather than overwrites.
|
|
348
|
-
const inline = (element as HTMLElement).style;
|
|
349
|
-
if (inline) {
|
|
350
|
-
const order = counter.order++;
|
|
351
|
-
for (const property of AUTHORED_COLOR_PROPERTIES) {
|
|
352
|
-
const value = inline[property as never] as unknown as string;
|
|
353
|
-
if (!isAuthoredColor(value)) continue;
|
|
354
|
-
const candidate: Candidate = {
|
|
355
|
-
value,
|
|
356
|
-
important:
|
|
357
|
-
inline.getPropertyPriority?.(cssPropertyName(property)) ===
|
|
358
|
-
"important",
|
|
359
|
-
specificity: INLINE_SPECIFICITY,
|
|
360
|
-
order,
|
|
361
|
-
};
|
|
362
|
-
if (beats(candidate, ranked[property])) ranked[property] = candidate;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const out: Record<string, string> = {};
|
|
367
|
-
for (const [property, candidate] of Object.entries(ranked)) {
|
|
368
|
-
out[property] = candidate.value;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return out;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
export function collectAuthoredColorStyles(
|
|
375
|
-
element: Element,
|
|
376
|
-
): Record<string, string> {
|
|
377
|
-
const out = collectForElement(element);
|
|
378
|
-
for (const property of Object.keys(out)) {
|
|
379
|
-
if (!authoredMatchesPainted(element, property, out[property])) {
|
|
380
|
-
delete out[property];
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// `color` is inherited: a heading with no rule of its own still has a token.
|
|
385
|
-
for (const property of INHERITED_PROPERTIES) {
|
|
386
|
-
if (out[property]) continue;
|
|
387
|
-
let ancestor = element.parentElement;
|
|
388
|
-
while (ancestor) {
|
|
389
|
-
const inherited = collectForElement(ancestor)[property];
|
|
390
|
-
if (inherited) {
|
|
391
|
-
if (authoredMatchesPainted(element, property, inherited)) {
|
|
392
|
-
out[property] = inherited;
|
|
393
|
-
}
|
|
394
|
-
break;
|
|
395
|
-
}
|
|
396
|
-
ancestor = ancestor.parentElement;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
return out;
|
|
401
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Catalog entries for the transactional emails Forms 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 { renderNewResponseEmail } from "./response-email.js";
|
|
11
|
-
|
|
12
|
-
export const FORMS_NEW_RESPONSE_EMAIL_ID = "forms.new-response";
|
|
13
|
-
|
|
14
|
-
let registered = false;
|
|
15
|
-
|
|
16
|
-
export function registerFormsEmails(): void {
|
|
17
|
-
if (registered) return;
|
|
18
|
-
registered = true;
|
|
19
|
-
|
|
20
|
-
defineTransactionalEmail({
|
|
21
|
-
id: FORMS_NEW_RESPONSE_EMAIL_ID,
|
|
22
|
-
name: "New form response",
|
|
23
|
-
trigger:
|
|
24
|
-
"A response is submitted and persisted for a form whose settings have `emailOnNewResponses` enabled. Delivery is best-effort: a send failure never rejects the submission.",
|
|
25
|
-
recipientLabel: "Form owner",
|
|
26
|
-
recipient:
|
|
27
|
-
"The form's `ownerEmail`, and only that address — the respondent is never emailed. Skipped when the form has no owner address.",
|
|
28
|
-
senderLabel: "Default sender",
|
|
29
|
-
sender:
|
|
30
|
-
"The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`, so a reply goes to the sending mailbox rather than to the respondent.",
|
|
31
|
-
preview: () =>
|
|
32
|
-
renderNewResponseEmail({
|
|
33
|
-
formTitle: "Beta feedback",
|
|
34
|
-
fields: [
|
|
35
|
-
{ id: "name", type: "text", label: "Name", required: true },
|
|
36
|
-
{ id: "email", type: "email", label: "Email", required: true },
|
|
37
|
-
{
|
|
38
|
-
id: "notes",
|
|
39
|
-
type: "textarea",
|
|
40
|
-
label: "What should we fix first?",
|
|
41
|
-
required: false,
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
data: {
|
|
45
|
-
name: "Sam Rivera",
|
|
46
|
-
email: "sam.rivera@example.com",
|
|
47
|
-
notes: "The export button is hard to find on mobile.",
|
|
48
|
-
},
|
|
49
|
-
submittedAt: "2025-03-04T17:20:00.000Z",
|
|
50
|
-
}),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
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
|