@bridge-ds/core 0.6.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.
@@ -558,6 +558,99 @@ function visualImpactProblems(raw) {
558
558
  }
559
559
  return out;
560
560
  }
561
+ const DEFAULT_PRODUCTS = [
562
+ { key: "admin", name: "Admin demo", path: "apps/admin", framework: "react" },
563
+ { key: "library", name: "Library", default: true }
564
+ ];
565
+ const PRODUCT_LABEL_PREFIX = "product: ";
566
+ const productLabel = (key) => `${PRODUCT_LABEL_PREFIX}${key}`;
567
+ function productsOf(config) {
568
+ const list2 = config?.products;
569
+ return Array.isArray(list2) && list2.length ? list2 : DEFAULT_PRODUCTS;
570
+ }
571
+ function defaultProduct(products) {
572
+ const list2 = products.length ? products : DEFAULT_PRODUCTS;
573
+ return list2.find((p) => p.default) ?? list2[list2.length - 1];
574
+ }
575
+ function findProduct(products, keyOrName) {
576
+ const k = (keyOrName ?? "").trim().toLowerCase();
577
+ if (!k) return void 0;
578
+ return products.find((p) => p.key.toLowerCase() === k) ?? products.find((p) => p.name.toLowerCase() === k);
579
+ }
580
+ const cleanPath = (p) => p.trim().replace(/^\.?\/+|\/+$/g, "");
581
+ function productOfBranch(products, branch) {
582
+ const fallback = defaultProduct(products);
583
+ for (const l of branch.labels ?? []) {
584
+ const name = typeof l === "string" ? l : l?.name;
585
+ if (typeof name !== "string" || !name.toLowerCase().startsWith(PRODUCT_LABEL_PREFIX)) continue;
586
+ const hit = findProduct(products, name.slice(PRODUCT_LABEL_PREFIX.length));
587
+ if (hit) return hit;
588
+ }
589
+ const files = branch.files ?? [];
590
+ for (const p of products) {
591
+ if (p === fallback || !p.path) continue;
592
+ const prefix = `${cleanPath(p.path)}/`;
593
+ if (prefix !== "/" && files.some((f) => f.startsWith(prefix))) return p;
594
+ }
595
+ return fallback;
596
+ }
597
+ function productForPlace(products, place) {
598
+ const repo = place.repo?.trim().toLowerCase();
599
+ if (repo && repo !== place.designSystemRepo?.trim().toLowerCase()) {
600
+ const hit = products.find((p) => p.repo?.toLowerCase() === repo);
601
+ if (hit) return { product: hit, how: "repo" };
602
+ }
603
+ const rel = cleanPath(place.relPath ?? "");
604
+ if (rel && rel !== ".") {
605
+ let best;
606
+ for (const p of products) {
607
+ if (!p.path) continue;
608
+ const dir = cleanPath(p.path);
609
+ if (dir && (rel === dir || rel.startsWith(`${dir}/`)) && (!best || dir.length > cleanPath(best.path).length)) best = p;
610
+ }
611
+ if (best) return { product: best, how: "path" };
612
+ }
613
+ return { product: defaultProduct(products), how: "default" };
614
+ }
615
+ const KEY = /^[a-z0-9][a-z0-9-]*$/;
616
+ const REPO = /^[\w.-]+\/[\w.-]+$/;
617
+ const FIELDS = ["key", "name", "repo", "path", "preview", "framework", "default"];
618
+ function productProblems(raw) {
619
+ if (raw === void 0) return [];
620
+ if (!Array.isArray(raw)) return ['"products" must be a list of { "key", "name" } objects'];
621
+ if (!raw.length) return ['"products" must list at least one product, or be left out to use the defaults'];
622
+ const problems = [];
623
+ const seen = /* @__PURE__ */ new Set();
624
+ let defaults = 0;
625
+ raw.forEach((p, i) => {
626
+ const at = `"products[${i}]`;
627
+ if (!p || typeof p !== "object" || Array.isArray(p)) {
628
+ problems.push(`${at}" must be an object with a "key" and a "name"`);
629
+ return;
630
+ }
631
+ const o = p;
632
+ for (const k of Object.keys(o)) if (!FIELDS.includes(k)) problems.push(`${at}.${k}" is not a known field (${FIELDS.join(", ")})`);
633
+ if (typeof o.key !== "string" || !KEY.test(o.key)) problems.push(`${at}.key" must be lowercase letters, digits and dashes, such as "admin"`);
634
+ else if (seen.has(o.key)) problems.push(`${at}.key" ("${o.key}") is used twice: give each product its own key`);
635
+ else seen.add(o.key);
636
+ if (typeof o.name !== "string" || !o.name.trim()) problems.push(`${at}.name" must be the name people read, such as "Admin demo"`);
637
+ if (o.repo !== void 0 && (typeof o.repo !== "string" || !REPO.test(o.repo))) problems.push(`${at}.repo" must be "owner/name"`);
638
+ if (o.path !== void 0) {
639
+ const bad = typeof o.path !== "string" || !o.path.trim() || o.path.startsWith("/") || o.path.split("/").includes("..");
640
+ if (bad) problems.push(`${at}.path" must be a folder relative to the repository root, without a leading "/" or "..", such as "apps/admin"`);
641
+ }
642
+ if (o.preview !== void 0 && (typeof o.preview !== "string" || !/^https?:\/\//.test(o.preview))) problems.push(`${at}.preview" must be an http(s) URL template, such as "https://app-git-{branch}.vercel.app"`);
643
+ if (o.framework !== void 0 && (typeof o.framework !== "string" || !o.framework.trim())) problems.push(`${at}.framework" must be a name such as "react", "vue" or "other"`);
644
+ if (o.default !== void 0 && typeof o.default !== "boolean") problems.push(`${at}.default" must be true or false`);
645
+ if (o.default === true) defaults++;
646
+ });
647
+ if (defaults > 1) problems.push('"products" marks more than one product as default: keep "default": true on the library only');
648
+ return problems;
649
+ }
650
+ function sameProducts(a, b) {
651
+ const norm2 = (l) => JSON.stringify(l.map((p) => FIELDS.map((f) => p[f] ?? null)));
652
+ return norm2(a) === norm2(b);
653
+ }
561
654
  const CONFIG_FILE = "bridge.config.json";
562
655
  const DEFAULT_OVERRIDE = { allowed: [], requireReason: true, minReasonLength: 20 };
563
656
  const DEFAULT_TOKEN_PATHS = {
@@ -697,6 +790,7 @@ function defineConfig(input) {
697
790
  } : {},
698
791
  ...g.rights ? { rights: normalizeRights(g.rights) } : {}
699
792
  },
793
+ products: input.products?.length ? input.products.map((p) => ({ ...p })) : DEFAULT_PRODUCTS.map((p) => ({ ...p })),
700
794
  ...input.audit ? { audit: { ...input.audit } } : {},
701
795
  ...input.visualImpact ? { visualImpact: { mode: input.visualImpact.mode === "on-demand" ? "on-demand" : "auto" } } : {},
702
796
  ...input.integrations ? { integrations: { ...input.integrations } } : {},
@@ -819,6 +913,7 @@ function loadConfig(source) {
819
913
  }
820
914
  }
821
915
  problems.push(...visualImpactProblems(d.visualImpact));
916
+ problems.push(...productProblems(d.products));
822
917
  const audit = d.audit;
823
918
  if (audit !== void 0) {
824
919
  if (!isObj(audit)) problems.push('"audit" must be an object');
@@ -865,7 +960,8 @@ function toConfigJson(config, schema = "./packages/core/bridge.config.schema.jso
865
960
  governance: config.governance,
866
961
  ...config.audit ? { audit: config.audit } : {},
867
962
  ...config.previews ? { previews: config.previews } : {},
868
- ...config.visualImpact ? { visualImpact: config.visualImpact } : {}
963
+ ...config.visualImpact ? { visualImpact: config.visualImpact } : {},
964
+ ...config.products && !sameProducts(config.products, DEFAULT_PRODUCTS) ? { products: config.products } : {}
869
965
  };
870
966
  }
871
967
  class JsonParseError extends Error {
@@ -2900,6 +2996,13 @@ const SPEC_FIELDS = [
2900
2996
  "textDecoration"
2901
2997
  ];
2902
2998
  const COLOR_FIELDS = /* @__PURE__ */ new Set(["fill", "stroke", "textFill"]);
2999
+ const TRIGGER_LABELS = {
3000
+ ON_HOVER: "While hovering",
3001
+ ON_PRESS: "While pressing",
3002
+ ON_CLICK: "On click",
3003
+ MOUSE_ENTER: "Mouse enter",
3004
+ MOUSE_LEAVE: "Mouse leave"
3005
+ };
2903
3006
  function coverageSummary(file) {
2904
3007
  const list2 = file.coverage ?? file.components.map((c) => ({ name: c.name, status: "generated" }));
2905
3008
  const generated = list2.filter((c) => c.status === "generated").length;
@@ -2984,6 +3087,16 @@ function validateComponentSpec(spec, tokenTypes) {
2984
3087
  for (const [id, vec] of Object.entries(v.vectors ?? {})) if (parts.get(id)?.kind !== "vector" || !/^<svg[\s>]/.test(vec.svg)) at(where, `vector "${id}" is not a vector part with an SVG`);
2985
3088
  for (const id of Object.keys(v.slots ?? {})) if (!parts.has(id)) at(where, `shows a component in "${id}", which is not a part`);
2986
3089
  }
3090
+ for (const [i, x] of (spec.interactions ?? []).entries()) {
3091
+ const where = `interaction ${i + 1}`;
3092
+ const axis = spec.axes.find((a) => a.name === x.axis);
3093
+ if (!(x.trigger in TRIGGER_LABELS)) at(where, `trigger ${String(x.trigger)} is not one Figma has`);
3094
+ if (!axis) at(where, `${x.axis} is not an axis`);
3095
+ else if (!axis.values.includes(x.from) || !axis.values.includes(x.to) || x.from === x.to) at(where, `${x.from} to ${x.to} are not two values of ${x.axis}`);
3096
+ for (const k of x.variants ?? []) if (!seen.has(k)) at(where, `variant ${k} does not exist`);
3097
+ const t = x.transition;
3098
+ if (t && (!(t.duration > 0) || t.easing.type === "CUSTOM_CUBIC_BEZIER" && (t.easing.bezier?.length !== 4 || t.easing.bezier.some((n) => typeof n !== "number")))) at(where, "the transition needs a duration and a valid easing");
3099
+ }
2987
3100
  return out;
2988
3101
  }
2989
3102
  function FIELD_TOKEN_TYPES(field) {
@@ -3008,6 +3121,48 @@ function hashSpec(spec) {
3008
3121
  }
3009
3122
  const variantName = (props) => Object.entries(props).map(([k, v]) => `${k}=${v}`).join(", ");
3010
3123
  const variantKeyOf = (props) => Object.keys(props).sort().map((k) => `${k}=${props[k]}`).join(", ") || "Default";
3124
+ const REDUCED_MOTION_NOTE = "In code, reduced motion turns this off.";
3125
+ function componentMotion(spec) {
3126
+ const keys = new Set(spec.variants.map((v) => variantKeyOf(v.props)));
3127
+ const reactions = [];
3128
+ const triggers = [];
3129
+ for (const x of spec.interactions ?? []) {
3130
+ const only = x.variants ? new Set(x.variants) : void 0;
3131
+ let count = 0;
3132
+ for (const v of spec.variants) {
3133
+ if (v.props[x.axis] !== x.from) continue;
3134
+ const fromKey = variantKeyOf(v.props);
3135
+ if (only && !only.has(fromKey)) continue;
3136
+ const to = { ...v.props, [x.axis]: x.to };
3137
+ const toKey = variantKeyOf(to);
3138
+ if (!keys.has(toKey)) continue;
3139
+ reactions.push({ trigger: x.trigger, label: TRIGGER_LABELS[x.trigger], from: { ...v.props }, to, fromKey, toKey, transition: x.transition });
3140
+ count++;
3141
+ }
3142
+ triggers.push({ ...x, label: TRIGGER_LABELS[x.trigger], count });
3143
+ }
3144
+ const transitions = (spec.interactions ?? []).map((x) => x.transition).filter((t) => !!t);
3145
+ const cannotPlay = [...spec.motion ?? []];
3146
+ const openNote = cannotPlay.find((n) => n.enter || n.exit);
3147
+ const opening = openNote ? { enter: openNote.enter ?? null, exit: openNote.exit ?? null } : void 0;
3148
+ const openTransitions = opening ? [opening.enter, opening.exit].filter((t) => !!t) : [];
3149
+ const tokens = [
3150
+ ...new Set([...transitions, ...openTransitions].flatMap((t) => [t.durationToken, t.easingToken]).concat(cannotPlay.map((n) => n.durationToken)).filter((t) => !!t))
3151
+ ].sort();
3152
+ const properties = [...new Set(transitions.flatMap((t) => t.properties))].sort();
3153
+ const approximations = [...new Set(transitions.map((t) => t.approximated).filter((t) => !!t))];
3154
+ const animates = transitions.length > 0 || openTransitions.length > 0 || cannotPlay.some((n) => /animation/i.test(n.what));
3155
+ return { name: spec.name, reactions, triggers, tokens, properties, approximations, cannotPlay, opening, reducedMotion: animates ? REDUCED_MOTION_NOTE : void 0 };
3156
+ }
3157
+ function componentsUsingMotionToken(specs, tokenPath, chainOf) {
3158
+ const out = /* @__PURE__ */ new Set();
3159
+ for (const c of specs.components) {
3160
+ for (const t of componentMotion(c).tokens) {
3161
+ if (t === tokenPath || (chainOf?.(t) ?? []).includes(tokenPath)) out.add(c.name);
3162
+ }
3163
+ }
3164
+ return [...out].sort();
3165
+ }
3011
3166
  function parseComponentSpecs(text) {
3012
3167
  let data;
3013
3168
  try {
@@ -3021,186 +3176,208 @@ function parseComponentSpecs(text) {
3021
3176
  return f;
3022
3177
  }
3023
3178
  const tokenCssVar = (path, prefix = "--", separator = "-") => `${prefix}${path.split(".").join(separator)}`;
3179
+ function figmaCell(entry) {
3180
+ if (!entry) return void 0;
3181
+ if (entry.status === "generated") return { label: "Yes" };
3182
+ if (entry.status === "drafted") return { label: "Drafted", title: "Drafted with Claude where the code cannot be read on its own: in Figma, check it against the code." };
3183
+ if (entry.status === "layout") return { label: "Auto layout", title: "A layout helper: nothing to draw, use auto layout in Figma." };
3184
+ return { label: "Not yet", ...entry.reason ? { title: `Not supported yet: ${entry.reason}` } : {} };
3185
+ }
3024
3186
  export {
3025
- buildHistoryEntry as $,
3026
- contextLabel as A,
3027
- pathId as B,
3187
+ applyTokenEdits as $,
3188
+ evaluatePairs as A,
3189
+ contrastScope as B,
3028
3190
  CONFIG_FILE as C,
3029
- flattenTokens as D,
3030
- serializeTokenFile as E,
3031
- removeToken as F,
3032
- upsertToken as G,
3033
- threeWayDiff as H,
3034
- emptyTokenFile as I,
3035
- parseTokenFile as J,
3036
- EXT_ID as K,
3037
- EXT_SCOPES as L,
3038
- resolve as M,
3039
- moveToken as N,
3040
- effectiveScopes as O,
3041
- sameScopes as P,
3042
- defaultScopes as Q,
3043
- readTokenAt as R,
3191
+ contextLabel as D,
3192
+ pathId as E,
3193
+ flattenTokens as F,
3194
+ serializeTokenFile as G,
3195
+ removeToken as H,
3196
+ upsertToken as I,
3197
+ threeWayDiff as J,
3198
+ emptyTokenFile as K,
3199
+ parseTokenFile as L,
3200
+ EXT_ID as M,
3201
+ EXT_SCOPES as N,
3202
+ moveToken as O,
3203
+ effectiveScopes as P,
3204
+ sameScopes as Q,
3205
+ defaultScopes as R,
3044
3206
  SINGLE_MODE as S,
3045
3207
  TIER_NAMES as T,
3046
- modeFile as U,
3047
- defaultFile as V,
3048
- DEFAULT_PROTECTED_BRANCHES as W,
3049
- ProtectedBranchError as X,
3050
- ConfigError as Y,
3051
- DEFAULT_TOKEN_PATHS as Z,
3052
- applyTokenEdits as _,
3208
+ readTokenAt as U,
3209
+ modeFile as V,
3210
+ defaultFile as W,
3211
+ DEFAULT_PROTECTED_BRANCHES as X,
3212
+ ProtectedBranchError as Y,
3213
+ ConfigError as Z,
3214
+ DEFAULT_TOKEN_PATHS as _,
3053
3215
  assertSafeBranch as a,
3054
- composeProposalBody as a$,
3055
- resolveBranchPreviews as a0,
3056
- tokensPath as a1,
3057
- coerceValue as a2,
3058
- toConfigJson as a3,
3059
- parseContrastChecks as a4,
3060
- checkLayeredPair as a5,
3061
- classifyRisk as a6,
3062
- formatChangeset as a7,
3063
- RISK_LABELS as a8,
3064
- parseJson as a9,
3065
- RIGHTS as aA,
3066
- RIGHT_LABEL as aB,
3067
- RISK_TIER as aC,
3068
- SPEC_FIELDS as aD,
3069
- TIER_ORDER as aE,
3070
- TeamDirectory as aF,
3071
- UNRELEASED as aG,
3072
- VISUAL_CHECK_LABEL as aH,
3073
- affectedContrast as aI,
3074
- appForProject as aJ,
3075
- appUrl as aK,
3076
- approverEntries as aL,
3077
- approverLists as aM,
3078
- assignVersions as aN,
3079
- baseBranchOf as aO,
3080
- branchName as aP,
3081
- branchSlug as aQ,
3082
- canShip as aR,
3083
- changeKind as aS,
3084
- changeTable as aT,
3085
- changedModes as aU,
3086
- changesetBump as aV,
3087
- classifyLayered as aW,
3088
- clearRawDeep as aX,
3089
- commitMessage as aY,
3090
- composeChangeset as aZ,
3091
- composePrBody as a_,
3092
- serializeJson as aa,
3093
- plainEqual as ab,
3094
- toPlain as ac,
3095
- getEntry as ad,
3096
- fromPlain as ae,
3097
- previewLinks as af,
3098
- slugify as ag,
3099
- readPreviewComment as ah,
3100
- findPreviewComment as ai,
3101
- previewsSettled as aj,
3102
- AAA_MIN as ak,
3103
- AA_MIN as al,
3104
- BULK_LIMIT as am,
3105
- CONTRAST_CELL_MAX as an,
3106
- CONTRAST_CHECKS_FILE as ao,
3107
- DEFAULT_COMPONENT_SPECS_FILE as ap,
3108
- DEFAULT_GOVERNANCE as aq,
3109
- DEFAULT_OVERRIDE as ar,
3110
- DEFAULT_RIGHTS as as,
3111
- DEFAULT_VISUAL_IMPACT as at,
3112
- JsonParseError as au,
3113
- OWNER_GROUPS as av,
3114
- PREVIEW_APP_LABELS as aw,
3115
- PREVIEW_COMMENT_MARKER as ax,
3116
- PREVIEW_PLACEHOLDERS as ay,
3117
- PRIMITIVE_MODE as az,
3216
+ changedModes as a$,
3217
+ buildHistoryEntry as a0,
3218
+ resolveBranchPreviews as a1,
3219
+ tokensPath as a2,
3220
+ coerceValue as a3,
3221
+ toConfigJson as a4,
3222
+ parseContrastChecks as a5,
3223
+ checkLayeredPair as a6,
3224
+ classifyRisk as a7,
3225
+ formatChangeset as a8,
3226
+ RISK_LABELS as a9,
3227
+ OWNER_GROUPS as aA,
3228
+ PREVIEW_APP_LABELS as aB,
3229
+ PREVIEW_COMMENT_MARKER as aC,
3230
+ PREVIEW_PLACEHOLDERS as aD,
3231
+ PRIMITIVE_MODE as aE,
3232
+ PRODUCT_LABEL_PREFIX as aF,
3233
+ REDUCED_MOTION_NOTE as aG,
3234
+ RIGHTS as aH,
3235
+ RIGHT_LABEL as aI,
3236
+ RISK_TIER as aJ,
3237
+ SPEC_FIELDS as aK,
3238
+ TIER_ORDER as aL,
3239
+ TRIGGER_LABELS as aM,
3240
+ TeamDirectory as aN,
3241
+ UNRELEASED as aO,
3242
+ VISUAL_CHECK_LABEL as aP,
3243
+ affectedContrast as aQ,
3244
+ appForProject as aR,
3245
+ appUrl as aS,
3246
+ approverEntries as aT,
3247
+ approverLists as aU,
3248
+ assignVersions as aV,
3249
+ baseBranchOf as aW,
3250
+ branchName as aX,
3251
+ branchSlug as aY,
3252
+ changeKind as aZ,
3253
+ changeTable as a_,
3254
+ parseJson as aa,
3255
+ serializeJson as ab,
3256
+ plainEqual as ac,
3257
+ toPlain as ad,
3258
+ getEntry as ae,
3259
+ fromPlain as af,
3260
+ previewLinks as ag,
3261
+ slugify as ah,
3262
+ readPreviewComment as ai,
3263
+ findPreviewComment as aj,
3264
+ previewsSettled as ak,
3265
+ canShip as al,
3266
+ whoCanShipSentence as am,
3267
+ unreadableShipTeams as an,
3268
+ AAA_MIN as ao,
3269
+ AA_MIN as ap,
3270
+ BULK_LIMIT as aq,
3271
+ CONTRAST_CELL_MAX as ar,
3272
+ CONTRAST_CHECKS_FILE as as,
3273
+ DEFAULT_COMPONENT_SPECS_FILE as at,
3274
+ DEFAULT_GOVERNANCE as au,
3275
+ DEFAULT_OVERRIDE as av,
3276
+ DEFAULT_PRODUCTS as aw,
3277
+ DEFAULT_RIGHTS as ax,
3278
+ DEFAULT_VISUAL_IMPACT as ay,
3279
+ JsonParseError as az,
3118
3280
  parseChangelog as b,
3119
- snapshotUrl as b$,
3120
- composite as b0,
3121
- contextFor as b1,
3122
- contrastDelta as b2,
3123
- contrastDeltaTable as b3,
3124
- contrastLevel as b4,
3125
- contrastPair as b5,
3126
- contrastRatio as b6,
3127
- countChanges as b7,
3128
- coverageSummary as b8,
3129
- defaultContext as b9,
3130
- isVercelComment as bA,
3131
- kindForMin as bB,
3132
- layeredImpact as bC,
3133
- luminance as bD,
3134
- modeLabel as bE,
3135
- nodesEqual as bF,
3136
- normalizeRights as bG,
3137
- overrideKey as bH,
3138
- ownerEntryProblems as bI,
3139
- pairKey as bJ,
3140
- parseChangesetText as bK,
3141
- parseComponentSpecs as bL,
3142
- parseOwnerEntry as bM,
3143
- parseVercelComment as bN,
3144
- planRestore as bO,
3145
- planRevert as bP,
3146
- planToJson as bQ,
3147
- previewComment as bR,
3148
- previewLinksOf as bS,
3149
- previewUrl as bT,
3150
- projectOfLabel as bU,
3151
- protectedBranchesOf as bV,
3152
- renderedColor as bW,
3153
- rightsProblems as bX,
3154
- runLayeredContrast as bY,
3155
- sameToken as bZ,
3156
- shipPolicy as b_,
3157
- defaultTitle as ba,
3158
- defineConfig as bb,
3159
- detectLayout as bc,
3160
- diffLayered as bd,
3161
- entriesFor as be,
3162
- entryLabel as bf,
3163
- expandEntries as bg,
3164
- expandOwners as bh,
3165
- fieldChanges as bi,
3166
- fileModes as bj,
3167
- filterHistory as bk,
3168
- findToken as bl,
3169
- findVercelComment as bm,
3170
- firstParagraph as bn,
3171
- formatNumber as bo,
3172
- formatOwnerEntry as bp,
3173
- getChild as bq,
3174
- groupsPhrase as br,
3175
- holdersOf as bs,
3176
- indexByPath as bt,
3177
- inheritedTypeAt as bu,
3178
- installCommand as bv,
3179
- installCommandFromPreviewComment as bw,
3180
- isGuardrail as bx,
3181
- isTeamEntry as by,
3182
- isTokenFile as bz,
3281
+ planToJson as b$,
3282
+ changesetBump as b0,
3283
+ classifyLayered as b1,
3284
+ clearRawDeep as b2,
3285
+ commitMessage as b3,
3286
+ componentMotion as b4,
3287
+ componentsUsingMotionToken as b5,
3288
+ composeChangeset as b6,
3289
+ composePrBody as b7,
3290
+ composeProposalBody as b8,
3291
+ composite as b9,
3292
+ formatOwnerEntry as bA,
3293
+ getChild as bB,
3294
+ groupsPhrase as bC,
3295
+ holdersOf as bD,
3296
+ indexByPath as bE,
3297
+ inheritedTypeAt as bF,
3298
+ installCommand as bG,
3299
+ installCommandFromPreviewComment as bH,
3300
+ isGuardrail as bI,
3301
+ isTeamEntry as bJ,
3302
+ isTokenFile as bK,
3303
+ isVercelComment as bL,
3304
+ kindForMin as bM,
3305
+ layeredImpact as bN,
3306
+ luminance as bO,
3307
+ modeLabel as bP,
3308
+ nodesEqual as bQ,
3309
+ normalizeRights as bR,
3310
+ overrideKey as bS,
3311
+ ownerEntryProblems as bT,
3312
+ pairKey as bU,
3313
+ parseChangesetText as bV,
3314
+ parseComponentSpecs as bW,
3315
+ parseOwnerEntry as bX,
3316
+ parseVercelComment as bY,
3317
+ planRestore as bZ,
3318
+ planRevert as b_,
3319
+ contextFor as ba,
3320
+ contrastDelta as bb,
3321
+ contrastDeltaTable as bc,
3322
+ contrastLevel as bd,
3323
+ contrastPair as be,
3324
+ contrastRatio as bf,
3325
+ countChanges as bg,
3326
+ coverageSummary as bh,
3327
+ defaultProduct as bi,
3328
+ defaultTitle as bj,
3329
+ defineConfig as bk,
3330
+ detectLayout as bl,
3331
+ diffLayered as bm,
3332
+ entriesFor as bn,
3333
+ entryLabel as bo,
3334
+ expandEntries as bp,
3335
+ expandOwners as bq,
3336
+ fieldChanges as br,
3337
+ figmaCell as bs,
3338
+ fileModes as bt,
3339
+ filterHistory as bu,
3340
+ findProduct as bv,
3341
+ findToken as bw,
3342
+ findVercelComment as bx,
3343
+ firstParagraph as by,
3344
+ formatNumber as bz,
3183
3345
  collectHistory as c,
3184
- summarizeTokenChange as c0,
3185
- tarballAssetName as c1,
3186
- tarballUrl as c2,
3187
- teamKey as c3,
3188
- teamKeyOf as c4,
3189
- teamUnreadableMessage as c5,
3190
- teamsIn as c6,
3191
- titleOf as c7,
3192
- toChangeSummary as c8,
3193
- toMap as c9,
3194
- tokenBump as ca,
3195
- tokenHistory as cb,
3196
- tokenNode as cc,
3197
- unreadableShipTeams as cd,
3198
- unreadableTeams as ce,
3199
- valueIn as cf,
3200
- variantName as cg,
3201
- versionTimeline as ch,
3202
- visualImpactProblems as ci,
3203
- whoCanShipSentence as cj,
3346
+ previewComment as c0,
3347
+ previewLinksOf as c1,
3348
+ previewUrl as c2,
3349
+ productForPlace as c3,
3350
+ productLabel as c4,
3351
+ productOfBranch as c5,
3352
+ productProblems as c6,
3353
+ productsOf as c7,
3354
+ projectOfLabel as c8,
3355
+ protectedBranchesOf as c9,
3356
+ renderedColor as ca,
3357
+ rightsProblems as cb,
3358
+ runLayeredContrast as cc,
3359
+ sameProducts as cd,
3360
+ sameToken as ce,
3361
+ shipPolicy as cf,
3362
+ snapshotUrl as cg,
3363
+ summarizeTokenChange as ch,
3364
+ tarballAssetName as ci,
3365
+ tarballUrl as cj,
3366
+ teamKey as ck,
3367
+ teamKeyOf as cl,
3368
+ teamUnreadableMessage as cm,
3369
+ teamsIn as cn,
3370
+ titleOf as co,
3371
+ toChangeSummary as cp,
3372
+ toMap as cq,
3373
+ tokenBump as cr,
3374
+ tokenHistory as cs,
3375
+ tokenNode as ct,
3376
+ unreadableTeams as cu,
3377
+ valueIn as cv,
3378
+ variantName as cw,
3379
+ versionTimeline as cx,
3380
+ visualImpactProblems as cy,
3204
3381
  buildReport as d,
3205
3382
  prNumberFromSubject as e,
3206
3383
  variantKeyOf as f,
@@ -3208,21 +3385,21 @@ export {
3208
3385
  hashSpec as h,
3209
3386
  iconComponentName as i,
3210
3387
  buildTokenSet as j,
3211
- COMPONENT_SPECS_VERSION as k,
3388
+ defaultContext as k,
3212
3389
  loadConfig as l,
3213
3390
  mergeReleases as m,
3214
- COLOR_FIELDS as n,
3215
- modeDisplayName as o,
3391
+ resolve as n,
3392
+ COMPONENT_SPECS_VERSION as o,
3216
3393
  packageDirCandidates as p,
3217
- modesOf as q,
3394
+ COLOR_FIELDS as q,
3218
3395
  releasesFromTags as r,
3219
3396
  specHash as s,
3220
3397
  tokenCssVar as t,
3221
- isMultiMode as u,
3398
+ modeDisplayName as u,
3222
3399
  validateComponentSpec as v,
3223
- TIER_AXIS as w,
3224
- findReferenceProblems as x,
3225
- evaluatePairs as y,
3226
- contrastScope as z
3400
+ modesOf as w,
3401
+ isMultiMode as x,
3402
+ TIER_AXIS as y,
3403
+ findReferenceProblems as z
3227
3404
  };
3228
- //# sourceMappingURL=component-spec-GFVEE6Fc.js.map
3405
+ //# sourceMappingURL=component-spec-1z2ih4E3.js.map