@linktr.ee/arbor-mcp 0.5.0 → 0.7.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/dist/index.js +243 -27
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,7 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
10
14
|
};
|
|
11
15
|
var __export = (target, all) => {
|
|
12
16
|
for (var name in all)
|
|
@@ -5532,7 +5536,7 @@ ZodNaN.create = (params) => {
|
|
|
5532
5536
|
...processCreateParams(params)
|
|
5533
5537
|
});
|
|
5534
5538
|
};
|
|
5535
|
-
var BRAND = Symbol("zod_brand");
|
|
5539
|
+
var BRAND = /* @__PURE__ */ Symbol("zod_brand");
|
|
5536
5540
|
var ZodBranded = class extends ZodType {
|
|
5537
5541
|
_parse(input) {
|
|
5538
5542
|
const { ctx } = this._processInputParams(input);
|
|
@@ -6130,6 +6134,69 @@ async function resolveVersionId(version, deps = {}) {
|
|
|
6130
6134
|
return { ok: true, versionId, versionName };
|
|
6131
6135
|
}
|
|
6132
6136
|
|
|
6137
|
+
// src/lib/intentions.ts
|
|
6138
|
+
var INTENTIONS_ARTIFACT = "component-intentions.json";
|
|
6139
|
+
var INTENTION_STATUSES = [
|
|
6140
|
+
"shipped",
|
|
6141
|
+
"in-progress",
|
|
6142
|
+
"design-only",
|
|
6143
|
+
"deprecated",
|
|
6144
|
+
"researched-not-shipped"
|
|
6145
|
+
];
|
|
6146
|
+
var STATUS_SET = new Set(INTENTION_STATUSES);
|
|
6147
|
+
function normalizeComponentKey(name) {
|
|
6148
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
6149
|
+
}
|
|
6150
|
+
function asStringArray(v) {
|
|
6151
|
+
return Array.isArray(v) ? v.filter((s) => typeof s === "string") : [];
|
|
6152
|
+
}
|
|
6153
|
+
function asDisambiguations(v) {
|
|
6154
|
+
if (!Array.isArray(v)) return [];
|
|
6155
|
+
const out = [];
|
|
6156
|
+
for (const d of v) {
|
|
6157
|
+
if (d && typeof d === "object") {
|
|
6158
|
+
const component = d.component;
|
|
6159
|
+
const distinction = d.distinction;
|
|
6160
|
+
if (typeof component === "string" && typeof distinction === "string") {
|
|
6161
|
+
out.push({ component, distinction });
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
return out;
|
|
6166
|
+
}
|
|
6167
|
+
function coerceEntry(raw) {
|
|
6168
|
+
if (!raw || typeof raw !== "object") return null;
|
|
6169
|
+
const r = raw;
|
|
6170
|
+
const name = typeof r.name === "string" ? r.name.trim() : "";
|
|
6171
|
+
const status = typeof r.status === "string" ? r.status : "";
|
|
6172
|
+
if (!name || !STATUS_SET.has(status)) return null;
|
|
6173
|
+
return {
|
|
6174
|
+
name,
|
|
6175
|
+
status,
|
|
6176
|
+
shippedVersion: typeof r.shippedVersion === "string" ? r.shippedVersion : null,
|
|
6177
|
+
useWhen: asStringArray(r.useWhen),
|
|
6178
|
+
notWhen: asStringArray(r.notWhen),
|
|
6179
|
+
disambiguateFrom: asDisambiguations(r.disambiguateFrom),
|
|
6180
|
+
guideline: typeof r.guideline === "string" ? r.guideline : null,
|
|
6181
|
+
implementation: typeof r.implementation === "string" ? r.implementation : null,
|
|
6182
|
+
decisions: asStringArray(r.decisions)
|
|
6183
|
+
};
|
|
6184
|
+
}
|
|
6185
|
+
async function loadIntentions(load = loadPublishedJson) {
|
|
6186
|
+
const res = await load(INTENTIONS_ARTIFACT);
|
|
6187
|
+
if (!res.ok) return { ok: false, reason: res.reason };
|
|
6188
|
+
const data = res.data;
|
|
6189
|
+
if (data.degraded === true || !Array.isArray(data.components)) {
|
|
6190
|
+
return { ok: false, reason: "degraded" };
|
|
6191
|
+
}
|
|
6192
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
6193
|
+
for (const raw of data.components) {
|
|
6194
|
+
const entry = coerceEntry(raw);
|
|
6195
|
+
if (entry) byKey.set(normalizeComponentKey(entry.name), entry);
|
|
6196
|
+
}
|
|
6197
|
+
return { ok: true, byKey, generatedAt: typeof data.generatedAt === "string" ? data.generatedAt : null };
|
|
6198
|
+
}
|
|
6199
|
+
|
|
6133
6200
|
// src/tools/list-components.ts
|
|
6134
6201
|
var TOOL_NAME3 = "arbor_list_components";
|
|
6135
6202
|
var TOOL_TITLE3 = "List Arbor components";
|
|
@@ -6146,7 +6213,16 @@ var inputSchema3 = external_exports.object({
|
|
|
6146
6213
|
var outputSchema3 = external_exports.object({
|
|
6147
6214
|
source: external_exports.enum(["remote", "unavailable"]),
|
|
6148
6215
|
total: external_exports.number(),
|
|
6149
|
-
components: external_exports.array(
|
|
6216
|
+
components: external_exports.array(
|
|
6217
|
+
external_exports.object({
|
|
6218
|
+
id: external_exports.string(),
|
|
6219
|
+
name: external_exports.string(),
|
|
6220
|
+
description: external_exports.string().nullable(),
|
|
6221
|
+
// Lifecycle status merged from the component-intentions manifest (DNG-726).
|
|
6222
|
+
// null when the manifest has no entry for this component or could not be loaded.
|
|
6223
|
+
status: external_exports.enum(INTENTION_STATUSES).nullable()
|
|
6224
|
+
})
|
|
6225
|
+
),
|
|
6150
6226
|
detail: external_exports.string().nullable()
|
|
6151
6227
|
});
|
|
6152
6228
|
var annotations3 = { readOnlyHint: true, idempotentHint: true, openWorldHint: true, destructiveHint: false };
|
|
@@ -6196,7 +6272,13 @@ async function handleListComponents(args, deps = {}) {
|
|
|
6196
6272
|
(c) => c.name.toLowerCase().includes(q) || (c.description ? c.description.toLowerCase().includes(q) : false)
|
|
6197
6273
|
);
|
|
6198
6274
|
}
|
|
6199
|
-
|
|
6275
|
+
const intentionsRes = await (deps.loadIntentions ?? (() => loadIntentions()))();
|
|
6276
|
+
const byKey = intentionsRes.ok ? intentionsRes.byKey : null;
|
|
6277
|
+
const withStatus = components.map((c) => ({
|
|
6278
|
+
...c,
|
|
6279
|
+
status: byKey ? byKey.get(normalizeComponentKey(c.name))?.status ?? null : null
|
|
6280
|
+
}));
|
|
6281
|
+
out = { source: "remote", total: withStatus.length, components: withStatus, detail: null };
|
|
6200
6282
|
}
|
|
6201
6283
|
const summary = out.source === "unavailable" ? `Could not load components (${out.detail}). Treat as unavailable \u2014 do not assume there are none.` : `${out.total} component${out.total === 1 ? "" : "s"}${args.query ? ` matching "${args.query}"` : ""}.`;
|
|
6202
6284
|
return { content: [{ type: "text", text: summary }], structuredContent: out };
|
|
@@ -6210,7 +6292,7 @@ var listComponentsTool = {
|
|
|
6210
6292
|
// src/tools/get-component.ts
|
|
6211
6293
|
var TOOL_NAME4 = "arbor_get_component";
|
|
6212
6294
|
var TOOL_TITLE4 = "Get one Arbor component";
|
|
6213
|
-
var TOOL_DESCRIPTION4 = "Get a single Arbor component's metadata by name (case-insensitive) or id
|
|
6295
|
+
var TOOL_DESCRIPTION4 = "Get a single Arbor component's metadata by name (case-insensitive) or id (name, id, description) PLUS its intention overlay \u2014 lifecycle status (shipped | in-progress | design-only | deprecated | researched-not-shipped), when to use it, when NOT to (and what to use instead), what it is commonly confused with, and repo paths to its guideline and (when present) agent implementation guidance. Intention comes from Arbor's source of truth, so a design-only component absent from the live design data still resolves. Read-only; matches top-level components, not Figma variants. Does NOT return token values or rendered source \u2014 use the shadcn registry / Storybook for implementation and arbor_open_in_playroom for a runnable snippet. Does NOT change anything.";
|
|
6214
6296
|
var inputSchema4 = external_exports.object({
|
|
6215
6297
|
name: external_exports.string().trim().min(1).max(100).optional().describe('Component name (case-insensitive), e.g. "Button"'),
|
|
6216
6298
|
id: external_exports.string().trim().min(1).max(100).optional().describe("Supernova component id"),
|
|
@@ -6221,53 +6303,116 @@ var inputSchema4 = external_exports.object({
|
|
|
6221
6303
|
'Read a specific released version, e.g. "15.1.0" \u2014 resolves to that frozen Supernova version and reads the component there ("what shipped in 15.1.0"). Takes precedence over versionSelector. See arbor_list_versions for the versions that have been cut.'
|
|
6222
6304
|
)
|
|
6223
6305
|
}).strict();
|
|
6306
|
+
var disambiguationSchema = external_exports.object({
|
|
6307
|
+
component: external_exports.string().describe("The thing to disambiguate from \u2014 an Arbor component or an external concept (chip, snackbar, \u2026)"),
|
|
6308
|
+
distinction: external_exports.string().describe("How they differ and which to pick when")
|
|
6309
|
+
});
|
|
6310
|
+
var intentionSchema = external_exports.object({
|
|
6311
|
+
status: external_exports.enum(["shipped", "in-progress", "design-only", "deprecated", "researched-not-shipped"]).describe("Lifecycle/availability in the @linktr.ee/arbor package"),
|
|
6312
|
+
shippedVersion: external_exports.string().nullable().describe("The arbor version where this became available, when known"),
|
|
6313
|
+
useWhen: external_exports.array(external_exports.string()).describe("Situations this is the right choice for"),
|
|
6314
|
+
notWhen: external_exports.array(external_exports.string()).describe("When NOT to reach for it, ideally naming the better alternative"),
|
|
6315
|
+
disambiguateFrom: external_exports.array(disambiguationSchema).describe("Things this is commonly confused with"),
|
|
6316
|
+
guideline: external_exports.string().nullable().describe("Repo-relative path to the long-form guideline, when one exists"),
|
|
6317
|
+
implementation: external_exports.string().nullable().describe("Repo-relative path to the agent-facing implementation guidance (code-correctness + a11y rules), when one exists"),
|
|
6318
|
+
decisions: external_exports.array(external_exports.string()).describe("Decision-log ids (DL-NN) that explain this intention")
|
|
6319
|
+
});
|
|
6224
6320
|
var outputSchema4 = external_exports.object({
|
|
6225
|
-
source: external_exports.enum(["remote", "unavailable"]),
|
|
6226
|
-
found: external_exports.boolean(),
|
|
6321
|
+
source: external_exports.enum(["remote", "unavailable"]).describe("Live design-data (Supernova) availability"),
|
|
6322
|
+
found: external_exports.boolean().describe("True when a component OR an intention entry matched"),
|
|
6227
6323
|
component: external_exports.object({ id: external_exports.string(), name: external_exports.string(), description: external_exports.string().nullable() }).nullable(),
|
|
6324
|
+
intention: intentionSchema.nullable().describe("Intention overlay from the source-of-truth manifest; null when no entry matched or it could not be loaded"),
|
|
6325
|
+
intentionSource: external_exports.enum(["remote", "absent", "unavailable"]).describe("'remote' = matched, 'absent' = manifest loaded but no entry, 'unavailable' = manifest could not be loaded"),
|
|
6228
6326
|
detail: external_exports.string().nullable()
|
|
6229
6327
|
});
|
|
6230
6328
|
var annotations4 = { readOnlyHint: true, idempotentHint: true, openWorldHint: true, destructiveHint: false };
|
|
6329
|
+
async function resolveIntention(lookupName, load) {
|
|
6330
|
+
const res = await load();
|
|
6331
|
+
if (!res.ok) return { intention: null, intentionSource: "unavailable" };
|
|
6332
|
+
if (!lookupName) return { intention: null, intentionSource: "absent" };
|
|
6333
|
+
const match = res.byKey.get(normalizeComponentKey(lookupName));
|
|
6334
|
+
if (!match) return { intention: null, intentionSource: "absent" };
|
|
6335
|
+
const intention = {
|
|
6336
|
+
status: match.status,
|
|
6337
|
+
shippedVersion: match.shippedVersion,
|
|
6338
|
+
useWhen: match.useWhen,
|
|
6339
|
+
notWhen: match.notWhen,
|
|
6340
|
+
disambiguateFrom: match.disambiguateFrom.map((d) => ({ component: d.component, distinction: d.distinction })),
|
|
6341
|
+
guideline: match.guideline,
|
|
6342
|
+
implementation: match.implementation,
|
|
6343
|
+
decisions: match.decisions
|
|
6344
|
+
};
|
|
6345
|
+
return { intention, intentionSource: "remote" };
|
|
6346
|
+
}
|
|
6231
6347
|
async function handleGetComponent(args, deps = {}) {
|
|
6232
6348
|
const name = args.name?.trim();
|
|
6233
6349
|
const id = args.id?.trim();
|
|
6350
|
+
const loadIntentionsFn = deps.loadIntentions ?? (() => loadIntentions());
|
|
6234
6351
|
if (!name && !id) {
|
|
6235
|
-
const out2 = {
|
|
6352
|
+
const out2 = {
|
|
6353
|
+
source: "remote",
|
|
6354
|
+
found: false,
|
|
6355
|
+
component: null,
|
|
6356
|
+
intention: null,
|
|
6357
|
+
intentionSource: "absent",
|
|
6358
|
+
detail: "provide name or id"
|
|
6359
|
+
};
|
|
6236
6360
|
return {
|
|
6237
6361
|
content: [{ type: "text", text: 'Provide a component name or id \u2014 e.g. {"name":"Button"} or {"id":"35988997"}.' }],
|
|
6238
6362
|
structuredContent: out2
|
|
6239
6363
|
};
|
|
6240
6364
|
}
|
|
6241
6365
|
const query = deps.query ?? ((r, opts) => querySupernova(r, opts));
|
|
6242
|
-
let
|
|
6366
|
+
let supernovaSource = "remote";
|
|
6367
|
+
let component = null;
|
|
6368
|
+
let supernovaDetail = null;
|
|
6369
|
+
let queryOpts = null;
|
|
6243
6370
|
if (args.version) {
|
|
6244
6371
|
const resolveVersion = deps.resolveVersion ?? ((v) => resolveVersionId(v));
|
|
6245
6372
|
const resolved = await resolveVersion(args.version);
|
|
6246
|
-
if (
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
};
|
|
6373
|
+
if (resolved.ok) {
|
|
6374
|
+
queryOpts = { versionId: resolved.versionId };
|
|
6375
|
+
} else {
|
|
6376
|
+
supernovaSource = "unavailable";
|
|
6377
|
+
supernovaDetail = resolved.detail;
|
|
6252
6378
|
}
|
|
6253
|
-
queryOpts = { versionId: resolved.versionId };
|
|
6254
6379
|
} else {
|
|
6255
6380
|
queryOpts = { versionSelector: args.versionSelector };
|
|
6256
6381
|
}
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
const components = extractComponents(result.data);
|
|
6263
|
-
if (components === null) {
|
|
6264
|
-
out = { source: "unavailable", found: false, component: null, detail: "proxy returned an unrecognized components payload" };
|
|
6382
|
+
if (queryOpts) {
|
|
6383
|
+
const result = await query("components", queryOpts);
|
|
6384
|
+
if (!result.ok) {
|
|
6385
|
+
supernovaSource = "unavailable";
|
|
6386
|
+
supernovaDetail = `could not load components (${result.reason})`;
|
|
6265
6387
|
} else {
|
|
6266
|
-
const
|
|
6267
|
-
|
|
6388
|
+
const components = extractComponents(result.data);
|
|
6389
|
+
if (components === null) {
|
|
6390
|
+
supernovaSource = "unavailable";
|
|
6391
|
+
supernovaDetail = "proxy returned an unrecognized components payload";
|
|
6392
|
+
} else {
|
|
6393
|
+
const target = name ? normalizeComponentKey(name) : null;
|
|
6394
|
+
const match = id ? components.find((c) => c.id === id) : components.find((c) => normalizeComponentKey(c.name) === target);
|
|
6395
|
+
if (match) component = match;
|
|
6396
|
+
else supernovaDetail = `no component ${id ? `with id ${id}` : `named "${name}"`}`;
|
|
6397
|
+
}
|
|
6268
6398
|
}
|
|
6269
6399
|
}
|
|
6270
|
-
const
|
|
6400
|
+
const lookupName = component?.name ?? name ?? null;
|
|
6401
|
+
const { intention, intentionSource } = await resolveIntention(lookupName, loadIntentionsFn);
|
|
6402
|
+
const found = component !== null || intention !== null;
|
|
6403
|
+
let detail = supernovaDetail;
|
|
6404
|
+
if (!component && intention) {
|
|
6405
|
+
detail = supernovaSource === "unavailable" ? `live design data unavailable (${supernovaDetail}); intention found \u2014 status "${intention.status}"` : `not in the live design data, but tracked as "${intention.status}" in Arbor's component intentions`;
|
|
6406
|
+
}
|
|
6407
|
+
const out = { source: supernovaSource, found, component, intention, intentionSource, detail };
|
|
6408
|
+
let summary;
|
|
6409
|
+
if (!found) {
|
|
6410
|
+
summary = supernovaSource === "unavailable" ? `Could not load components (${supernovaDetail}). Treat as unavailable.` : `No Arbor component ${id ? `with id ${id}` : `named "${name}"`} exists.`;
|
|
6411
|
+
} else {
|
|
6412
|
+
const head = component ? `${component.name}${component.description ? ` \u2014 ${component.description}` : " (no description)"}.` : `${lookupName} \u2014 ${detail}.`;
|
|
6413
|
+
const intentionLine = intention ? ` Status: ${intention.status}.${intention.useWhen.length ? ` Use when: ${intention.useWhen[0]}` : ""}` : intentionSource === "unavailable" ? " (intention overlay unavailable)" : "";
|
|
6414
|
+
summary = `${head}${intentionLine}`;
|
|
6415
|
+
}
|
|
6271
6416
|
return { content: [{ type: "text", text: summary }], structuredContent: out };
|
|
6272
6417
|
}
|
|
6273
6418
|
var getComponentTool = {
|
|
@@ -6790,6 +6935,22 @@ var compositions_default = [
|
|
|
6790
6935
|
name: "NotificationBadge",
|
|
6791
6936
|
code: "<NotificationBadge count={3} />"
|
|
6792
6937
|
},
|
|
6938
|
+
// ── IndicatorBadge ──
|
|
6939
|
+
{
|
|
6940
|
+
group: "IndicatorBadge",
|
|
6941
|
+
name: "IndicatorBadge (count)",
|
|
6942
|
+
code: "<IndicatorBadge count={5} />"
|
|
6943
|
+
},
|
|
6944
|
+
{
|
|
6945
|
+
group: "IndicatorBadge",
|
|
6946
|
+
name: "IndicatorBadge (dot)",
|
|
6947
|
+
code: '<IndicatorBadge dot aria-label="Unread" />'
|
|
6948
|
+
},
|
|
6949
|
+
{
|
|
6950
|
+
group: "IndicatorBadge",
|
|
6951
|
+
name: "IndicatorBadge (custom color)",
|
|
6952
|
+
code: '<IndicatorBadge count={5} color="#7B61FF" />'
|
|
6953
|
+
},
|
|
6793
6954
|
// ── Button ──
|
|
6794
6955
|
{
|
|
6795
6956
|
group: "Button",
|
|
@@ -6823,6 +6984,31 @@ var compositions_default = [
|
|
|
6823
6984
|
<Button variant="secondary">Cancel</Button>
|
|
6824
6985
|
<Button>Save changes</Button>
|
|
6825
6986
|
</div>`
|
|
6987
|
+
},
|
|
6988
|
+
// ── ButtonGroup ──
|
|
6989
|
+
{
|
|
6990
|
+
group: "ButtonGroup",
|
|
6991
|
+
name: "ButtonGroup (confirm / cancel)",
|
|
6992
|
+
code: `<ButtonGroup aria-label="Save changes">
|
|
6993
|
+
<Button variant="secondary">Cancel</Button>
|
|
6994
|
+
<Button>Save changes</Button>
|
|
6995
|
+
</ButtonGroup>`
|
|
6996
|
+
},
|
|
6997
|
+
{
|
|
6998
|
+
group: "ButtonGroup",
|
|
6999
|
+
name: "ButtonGroup (stacked)",
|
|
7000
|
+
code: `<ButtonGroup stacked aria-label="Start trial or decide later">
|
|
7001
|
+
<Button variant="accent">Start 7-day free trial</Button>
|
|
7002
|
+
<Button variant="ghost">Decide later</Button>
|
|
7003
|
+
</ButtonGroup>`
|
|
7004
|
+
},
|
|
7005
|
+
{
|
|
7006
|
+
group: "ButtonGroup",
|
|
7007
|
+
name: "ButtonGroup (auto width)",
|
|
7008
|
+
code: `<ButtonGroup fullWidth={false} aria-label="Discard or update">
|
|
7009
|
+
<Button variant="ghost">Discard changes</Button>
|
|
7010
|
+
<Button>Update everywhere</Button>
|
|
7011
|
+
</ButtonGroup>`
|
|
6826
7012
|
},
|
|
6827
7013
|
// ── CardSelect ──
|
|
6828
7014
|
{
|
|
@@ -7053,6 +7239,12 @@ var compositions_default = [
|
|
|
7053
7239
|
</RadioGroup>
|
|
7054
7240
|
</Fieldset>`
|
|
7055
7241
|
},
|
|
7242
|
+
// ── FileUpload ──
|
|
7243
|
+
{
|
|
7244
|
+
group: "FileUpload",
|
|
7245
|
+
name: "FileUpload",
|
|
7246
|
+
code: '<div className="w-full max-w-md"><FileUpload label="Select files to upload" supportingText="PDF, PNG, or JPG \u2014 up to 100MB each" /></div>'
|
|
7247
|
+
},
|
|
7056
7248
|
// ── HeaderBar ──
|
|
7057
7249
|
// Maps to figma-mappings `HeaderBar` (node 5223-5837). Title + back-button
|
|
7058
7250
|
// is the canonical small variant; HeaderBar.stories.tsx covers the full
|
|
@@ -7177,6 +7369,30 @@ var compositions_default = [
|
|
|
7177
7369
|
code: `<RadioGroup defaultValue="option-1">
|
|
7178
7370
|
<RadioButton value="option-1" variant="pill">Option 1</RadioButton>
|
|
7179
7371
|
<RadioButton value="option-2" variant="pill">Option 2</RadioButton>
|
|
7372
|
+
</RadioGroup>`
|
|
7373
|
+
},
|
|
7374
|
+
// ── Radio ──
|
|
7375
|
+
// Maps to figma-mappings `Radio` (canonical control, node 9232-27291). The bare
|
|
7376
|
+
// 20px control must render inside a RadioGroup; pair each with an accessible
|
|
7377
|
+
// name (aria-label here, or a sibling <label htmlFor> in real usage).
|
|
7378
|
+
{
|
|
7379
|
+
group: "Radio",
|
|
7380
|
+
name: "Radio",
|
|
7381
|
+
code: `<RadioGroup defaultValue="email" aria-label="Notifications">
|
|
7382
|
+
<Radio value="email" aria-label="Email" />
|
|
7383
|
+
<Radio value="sms" aria-label="SMS" />
|
|
7384
|
+
<Radio value="push" aria-label="Push notification" />
|
|
7385
|
+
</RadioGroup>`
|
|
7386
|
+
},
|
|
7387
|
+
// ── RadioItem ──
|
|
7388
|
+
// Maps to figma-mappings `RadioItem` (canonical control + label, node 12360-58265).
|
|
7389
|
+
{
|
|
7390
|
+
group: "RadioItem",
|
|
7391
|
+
name: "RadioItem",
|
|
7392
|
+
code: `<RadioGroup defaultValue="email" aria-label="Notifications">
|
|
7393
|
+
<RadioItem value="email" description="We'll send a confirmation">Email</RadioItem>
|
|
7394
|
+
<RadioItem value="sms">SMS</RadioItem>
|
|
7395
|
+
<RadioItem value="push" disabled>Push notification</RadioItem>
|
|
7180
7396
|
</RadioGroup>`
|
|
7181
7397
|
},
|
|
7182
7398
|
// ── SearchInput ──
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/arbor-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Model Context Protocol server exposing Arbor design system tools: Playroom snippets, Figma→code sync health, UX-writing checks, decision-log lookup, and federated component/version metadata.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arbor",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"esbuild": "^0.
|
|
48
|
+
"esbuild": "^0.28.1",
|
|
49
49
|
"tsx": "^4.7.0",
|
|
50
50
|
"typescript": "^5.7.0",
|
|
51
51
|
"zod": "3.25.76"
|