@bridge-ds/core 0.5.1 → 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.
@@ -544,7 +544,7 @@ function groupsPhrase(groups) {
544
544
  }
545
545
  function whoCanShipSentence(policy) {
546
546
  const names = (policy.entries ?? policy.logins).map((l) => entryLabel(l, policy.teams)).join(", ");
547
- return `Only ${groupsPhrase(policy.groups)} can ship this${names ? ` (${names})` : ""}.`;
547
+ return `Only ${groupsPhrase(policy.groups)} can merge this${names ? ` (${names})` : ""}.`;
548
548
  }
549
549
  const DEFAULT_VISUAL_IMPACT = { mode: "auto" };
550
550
  const VISUAL_CHECK_LABEL = "visual-check";
@@ -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 {
@@ -2885,18 +2981,131 @@ const SPEC_FIELDS = [
2885
2981
  "paddingBottom",
2886
2982
  "paddingLeft",
2887
2983
  "itemSpacing",
2984
+ "counterAxisSpacing",
2888
2985
  "width",
2889
2986
  "height",
2890
2987
  "minWidth",
2891
2988
  "minHeight",
2989
+ "opacity",
2892
2990
  "textFill",
2893
2991
  "fontFamily",
2894
2992
  "fontSize",
2895
2993
  "fontWeight",
2896
2994
  "lineHeight",
2897
- "letterSpacing"
2995
+ "letterSpacing",
2996
+ "textDecoration"
2898
2997
  ];
2899
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
+ };
3006
+ function coverageSummary(file) {
3007
+ const list2 = file.coverage ?? file.components.map((c) => ({ name: c.name, status: "generated" }));
3008
+ const generated = list2.filter((c) => c.status === "generated").length;
3009
+ const drafted = list2.filter((c) => c.status === "drafted").length;
3010
+ const layout = list2.filter((c) => c.status === "layout").length;
3011
+ return { generated, drafted, inFigma: generated + drafted, visual: list2.length - layout, layout, total: list2.length, missing: list2.filter((c) => c.status === "unsupported") };
3012
+ }
3013
+ const LAYOUT_DIRECTIONS = /* @__PURE__ */ new Set(["HORIZONTAL", "VERTICAL"]);
3014
+ const PRIMARY = /* @__PURE__ */ new Set(["MIN", "CENTER", "MAX", "SPACE_BETWEEN"]);
3015
+ const COUNTER = /* @__PURE__ */ new Set(["MIN", "CENTER", "MAX", "STRETCH"]);
3016
+ const PART_KINDS = /* @__PURE__ */ new Set(["frame", "text", "icon", "vector"]);
3017
+ function validateComponentSpec(spec, tokenTypes) {
3018
+ const out = [];
3019
+ const at = (where, why) => out.push(`${spec.name ?? "spec"}: ${where}: ${why}`);
3020
+ if (typeof spec.name !== "string" || !spec.name) return ["the spec has no name"];
3021
+ if (!Array.isArray(spec.axes) || !Array.isArray(spec.properties) || !Array.isArray(spec.parts) || !Array.isArray(spec.variants) || !Array.isArray(spec.unmapped)) return [`${spec.name}: axes, properties, parts, variants and unmapped must be lists`];
3022
+ const axisNames = /* @__PURE__ */ new Set();
3023
+ for (const a of spec.axes) {
3024
+ if (!a.name || axisNames.has(a.name)) at("axes", `"${a.name}" is missing or repeated`);
3025
+ axisNames.add(a.name);
3026
+ if (!Array.isArray(a.values) || !a.values.length) at(`axis ${a.name}`, "has no values");
3027
+ else if (!a.values.includes(a.default)) at(`axis ${a.name}`, `default "${a.default}" is not one of its values`);
3028
+ }
3029
+ const props = /* @__PURE__ */ new Map();
3030
+ for (const p of spec.properties) {
3031
+ if (props.has(p.name)) at("properties", `"${p.name}" is repeated`);
3032
+ props.set(p.name, p);
3033
+ if (p.type !== "TEXT" && p.type !== "BOOLEAN") at(`property ${p.name}`, `type ${String(p.type)} is not TEXT or BOOLEAN`);
3034
+ else if (typeof p.default !== (p.type === "TEXT" ? "string" : "boolean")) at(`property ${p.name}`, `default must be a ${p.type === "TEXT" ? "text" : "true or false"}`);
3035
+ }
3036
+ const parts = /* @__PURE__ */ new Map();
3037
+ for (const part of spec.parts) {
3038
+ if (!part.id || parts.has(part.id)) at("parts", `id "${part.id}" is missing or repeated`);
3039
+ if (!PART_KINDS.has(part.kind)) at(`part ${part.id}`, `kind ${String(part.kind)} is not frame, text, icon or vector`);
3040
+ if (part.parent === void 0) {
3041
+ if ([...parts.values()].some((x) => x.parent === void 0)) at(`part ${part.id}`, "a second root (every other part needs a parent)");
3042
+ } else if (!parts.has(part.parent)) at(`part ${part.id}`, `parent "${part.parent}" is not a part listed before it`);
3043
+ else if (parts.get(part.parent).kind !== "frame") at(`part ${part.id}`, `parent "${part.parent}" is not a frame`);
3044
+ if (part.layout && (!LAYOUT_DIRECTIONS.has(part.layout.direction) || !PRIMARY.has(part.layout.primary) || !COUNTER.has(part.layout.counter))) at(`part ${part.id}`, "layout is not a valid auto layout");
3045
+ if (part.text !== void 0 && props.get(part.text)?.type !== "TEXT") at(`part ${part.id}`, `text property "${part.text}" does not exist`);
3046
+ if (part.visible !== void 0 && props.get(part.visible)?.type !== "BOOLEAN") at(`part ${part.id}`, `visibility property "${part.visible}" does not exist`);
3047
+ if (part.kind === "text" && part.text === void 0 && part.characters === void 0 && !part.swap) at(`part ${part.id}`, "a text part needs a TEXT property or its characters");
3048
+ parts.set(part.id, part);
3049
+ }
3050
+ if (!spec.parts.length || spec.parts[0].parent !== void 0) at("parts", "the first part must be the root");
3051
+ const expected = spec.axes.reduce((n, a) => n * (a.values?.length || 1), 1);
3052
+ if (spec.variants.length !== expected) at("variants", `${spec.variants.length} variants for ${expected} combinations of the axes`);
3053
+ const seen = /* @__PURE__ */ new Set();
3054
+ for (const v of spec.variants) {
3055
+ const key = variantKeyOf(v.props ?? {});
3056
+ const where = `variant ${key}`;
3057
+ if (seen.has(key)) at(where, "is repeated");
3058
+ seen.add(key);
3059
+ for (const a of spec.axes) if (!a.values?.includes(v.props?.[a.name] ?? "")) at(where, `${a.name} is not one of its values`);
3060
+ for (const k of Object.keys(v.props ?? {})) if (!axisNames.has(k)) at(where, `${k} is not an axis`);
3061
+ for (const [id, fields] of Object.entries(v.values ?? {})) {
3062
+ const part = parts.get(id);
3063
+ if (!part) {
3064
+ at(where, `values for "${id}", which is not a part`);
3065
+ continue;
3066
+ }
3067
+ for (const [field, value] of Object.entries(fields ?? {})) {
3068
+ if (!SPEC_FIELDS.includes(field)) at(`${where}, ${id}`, `${field} is not a field`);
3069
+ else if (value === null) {
3070
+ if (!COLOR_FIELDS.has(field)) at(`${where}, ${id}`, `${field} cannot be empty (only colors can be none)`);
3071
+ } else if (typeof value === "number") {
3072
+ if (COLOR_FIELDS.has(field)) at(`${where}, ${id}`, `${field} cannot be a number`);
3073
+ } else if (typeof value !== "string") at(`${where}, ${id}`, `${field} must be a token path, a number or none`);
3074
+ else if (field === "textDecoration") {
3075
+ if (!/^(UNDERLINE|STRIKETHROUGH|NONE)$/.test(value)) at(`${where}, ${id}`, `${value} is not a text decoration`);
3076
+ } else if (tokenTypes) {
3077
+ for (const path of value.startsWith("calc(") ? (value.match(/[A-Za-z][\w.-]*/g) ?? []).filter((x) => x !== "calc" && !/^\d|^px$/.test(x)) : [value]) {
3078
+ const type = tokenTypes.get(path);
3079
+ if (!type) at(`${where}, ${id}`, `${path} is not a token`);
3080
+ else if (!value.startsWith("calc(") && !FIELD_TOKEN_TYPES(field).includes(type)) at(`${where}, ${id}`, `${path} is a ${type} token, ${field} needs ${FIELD_TOKEN_TYPES(field).join(" or ")}`);
3081
+ }
3082
+ }
3083
+ }
3084
+ }
3085
+ for (const id of v.hidden ?? []) if (!parts.has(id)) at(where, `hides "${id}", which is not a part`);
3086
+ for (const id of Object.keys(v.layout ?? {})) if (!parts.has(id)) at(where, `lays out "${id}", which is not a part`);
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`);
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`);
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
+ }
3100
+ return out;
3101
+ }
3102
+ function FIELD_TOKEN_TYPES(field) {
3103
+ if (COLOR_FIELDS.has(field)) return ["color"];
3104
+ if (field === "fontFamily") return ["fontFamily"];
3105
+ if (field === "fontWeight") return ["fontWeight", "number"];
3106
+ if (field === "opacity") return ["number"];
3107
+ return ["dimension", "number"];
3108
+ }
2900
3109
  const iconComponentName = (name) => `Icon/${name}`;
2901
3110
  function specHash(text) {
2902
3111
  let h = 2166136261;
@@ -2907,11 +3116,53 @@ function specHash(text) {
2907
3116
  return (h >>> 0).toString(16).padStart(8, "0");
2908
3117
  }
2909
3118
  function hashSpec(spec) {
2910
- const { hash: _ignored, ...rest } = spec;
3119
+ const { hash: _ignored, example: _example, ...rest } = spec;
2911
3120
  return specHash(JSON.stringify(rest));
2912
3121
  }
2913
3122
  const variantName = (props) => Object.entries(props).map(([k, v]) => `${k}=${v}`).join(", ");
2914
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
+ }
2915
3166
  function parseComponentSpecs(text) {
2916
3167
  let data;
2917
3168
  try {
@@ -2925,206 +3176,230 @@ function parseComponentSpecs(text) {
2925
3176
  return f;
2926
3177
  }
2927
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
+ }
2928
3186
  export {
2929
- tokensPath as $,
2930
- flattenTokens as A,
2931
- serializeTokenFile as B,
2932
- COMPONENT_SPECS_VERSION as C,
2933
- removeToken as D,
2934
- upsertToken as E,
2935
- threeWayDiff as F,
2936
- emptyTokenFile as G,
2937
- parseTokenFile as H,
2938
- EXT_ID as I,
2939
- EXT_SCOPES as J,
2940
- resolve as K,
2941
- moveToken as L,
2942
- effectiveScopes as M,
2943
- sameScopes as N,
2944
- defaultScopes as O,
2945
- readTokenAt as P,
2946
- modeFile as Q,
2947
- defaultFile as R,
3187
+ applyTokenEdits as $,
3188
+ evaluatePairs as A,
3189
+ contrastScope as B,
3190
+ CONFIG_FILE as C,
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,
2948
3206
  SINGLE_MODE as S,
2949
3207
  TIER_NAMES as T,
2950
- DEFAULT_PROTECTED_BRANCHES as U,
2951
- ProtectedBranchError as V,
2952
- ConfigError as W,
2953
- DEFAULT_TOKEN_PATHS as X,
2954
- applyTokenEdits as Y,
2955
- buildHistoryEntry as Z,
2956
- resolveBranchPreviews 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 _,
2957
3215
  assertSafeBranch as a,
2958
- contextFor as a$,
2959
- coerceValue as a0,
2960
- toConfigJson as a1,
2961
- parseContrastChecks as a2,
2962
- checkLayeredPair as a3,
2963
- classifyRisk as a4,
2964
- formatChangeset as a5,
2965
- RISK_LABELS as a6,
2966
- parseJson as a7,
2967
- serializeJson as a8,
2968
- plainEqual as a9,
2969
- RISK_TIER as aA,
2970
- SPEC_FIELDS as aB,
2971
- TIER_ORDER as aC,
2972
- TeamDirectory as aD,
2973
- UNRELEASED as aE,
2974
- VISUAL_CHECK_LABEL as aF,
2975
- affectedContrast as aG,
2976
- appForProject as aH,
2977
- appUrl as aI,
2978
- approverEntries as aJ,
2979
- approverLists as aK,
2980
- assignVersions as aL,
2981
- baseBranchOf as aM,
2982
- branchName as aN,
2983
- branchSlug as aO,
2984
- canShip as aP,
2985
- changeKind as aQ,
2986
- changeTable as aR,
2987
- changedModes as aS,
2988
- changesetBump as aT,
2989
- classifyLayered as aU,
2990
- clearRawDeep as aV,
2991
- commitMessage as aW,
2992
- composeChangeset as aX,
2993
- composePrBody as aY,
2994
- composeProposalBody as aZ,
2995
- composite as a_,
2996
- toPlain as aa,
2997
- getEntry as ab,
2998
- fromPlain as ac,
2999
- previewLinks as ad,
3000
- slugify as ae,
3001
- readPreviewComment as af,
3002
- findPreviewComment as ag,
3003
- previewsSettled as ah,
3004
- AAA_MIN as ai,
3005
- AA_MIN as aj,
3006
- BULK_LIMIT as ak,
3007
- CONTRAST_CELL_MAX as al,
3008
- CONTRAST_CHECKS_FILE as am,
3009
- DEFAULT_COMPONENT_SPECS_FILE as an,
3010
- DEFAULT_GOVERNANCE as ao,
3011
- DEFAULT_OVERRIDE as ap,
3012
- DEFAULT_RIGHTS as aq,
3013
- DEFAULT_VISUAL_IMPACT as ar,
3014
- JsonParseError as as,
3015
- OWNER_GROUPS as at,
3016
- PREVIEW_APP_LABELS as au,
3017
- PREVIEW_COMMENT_MARKER as av,
3018
- PREVIEW_PLACEHOLDERS as aw,
3019
- PRIMITIVE_MODE as ax,
3020
- RIGHTS as ay,
3021
- RIGHT_LABEL 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,
3022
3280
  parseChangelog as b,
3023
- tarballAssetName as b$,
3024
- contrastDelta as b0,
3025
- contrastDeltaTable as b1,
3026
- contrastLevel as b2,
3027
- contrastPair as b3,
3028
- contrastRatio as b4,
3029
- countChanges as b5,
3030
- defaultContext as b6,
3031
- defaultTitle as b7,
3032
- defineConfig as b8,
3033
- detectLayout as b9,
3034
- luminance as bA,
3035
- modeLabel as bB,
3036
- nodesEqual as bC,
3037
- normalizeRights as bD,
3038
- overrideKey as bE,
3039
- ownerEntryProblems as bF,
3040
- pairKey as bG,
3041
- parseChangesetText as bH,
3042
- parseComponentSpecs as bI,
3043
- parseOwnerEntry as bJ,
3044
- parseVercelComment as bK,
3045
- planRestore as bL,
3046
- planRevert as bM,
3047
- planToJson as bN,
3048
- previewComment as bO,
3049
- previewLinksOf as bP,
3050
- previewUrl as bQ,
3051
- projectOfLabel as bR,
3052
- protectedBranchesOf as bS,
3053
- renderedColor as bT,
3054
- rightsProblems as bU,
3055
- runLayeredContrast as bV,
3056
- sameToken as bW,
3057
- shipPolicy as bX,
3058
- snapshotUrl as bY,
3059
- specHash as bZ,
3060
- summarizeTokenChange as b_,
3061
- diffLayered as ba,
3062
- entriesFor as bb,
3063
- entryLabel as bc,
3064
- expandEntries as bd,
3065
- expandOwners as be,
3066
- fieldChanges as bf,
3067
- fileModes as bg,
3068
- filterHistory as bh,
3069
- findToken as bi,
3070
- findVercelComment as bj,
3071
- firstParagraph as bk,
3072
- formatNumber as bl,
3073
- formatOwnerEntry as bm,
3074
- getChild as bn,
3075
- groupsPhrase as bo,
3076
- holdersOf as bp,
3077
- indexByPath as bq,
3078
- inheritedTypeAt as br,
3079
- installCommand as bs,
3080
- installCommandFromPreviewComment as bt,
3081
- isGuardrail as bu,
3082
- isTeamEntry as bv,
3083
- isTokenFile as bw,
3084
- isVercelComment as bx,
3085
- kindForMin as by,
3086
- layeredImpact 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,
3087
3345
  collectHistory as c,
3088
- tarballUrl as c0,
3089
- teamKey as c1,
3090
- teamKeyOf as c2,
3091
- teamUnreadableMessage as c3,
3092
- teamsIn as c4,
3093
- titleOf as c5,
3094
- toChangeSummary as c6,
3095
- toMap as c7,
3096
- tokenBump as c8,
3097
- tokenHistory as c9,
3098
- tokenNode as ca,
3099
- unreadableShipTeams as cb,
3100
- unreadableTeams as cc,
3101
- valueIn as cd,
3102
- variantName as ce,
3103
- versionTimeline as cf,
3104
- visualImpactProblems as cg,
3105
- whoCanShipSentence as ch,
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,
3106
3381
  buildReport as d,
3107
3382
  prNumberFromSubject as e,
3108
- CONFIG_FILE as f,
3383
+ variantKeyOf as f,
3109
3384
  layoutOptions as g,
3110
3385
  hashSpec as h,
3111
- buildTokenSet as i,
3112
- iconComponentName as j,
3113
- COLOR_FIELDS as k,
3386
+ iconComponentName as i,
3387
+ buildTokenSet as j,
3388
+ defaultContext as k,
3114
3389
  loadConfig as l,
3115
3390
  mergeReleases as m,
3116
- modeDisplayName as n,
3117
- modesOf as o,
3391
+ resolve as n,
3392
+ COMPONENT_SPECS_VERSION as o,
3118
3393
  packageDirCandidates as p,
3119
- isMultiMode as q,
3394
+ COLOR_FIELDS as q,
3120
3395
  releasesFromTags as r,
3121
- TIER_AXIS as s,
3396
+ specHash as s,
3122
3397
  tokenCssVar as t,
3123
- findReferenceProblems as u,
3124
- variantKeyOf as v,
3125
- evaluatePairs as w,
3126
- contrastScope as x,
3127
- contextLabel as y,
3128
- pathId as z
3398
+ modeDisplayName as u,
3399
+ validateComponentSpec as v,
3400
+ modesOf as w,
3401
+ isMultiMode as x,
3402
+ TIER_AXIS as y,
3403
+ findReferenceProblems as z
3129
3404
  };
3130
- //# sourceMappingURL=component-spec-cvrSvIZj.js.map
3405
+ //# sourceMappingURL=component-spec-1z2ih4E3.js.map