@bridge-ds/core 0.17.0 → 0.19.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.
Files changed (64) hide show
  1. package/bridge.config.schema.json +16 -0
  2. package/dist/activity.d.ts +207 -0
  3. package/dist/audit/index.js +3 -3
  4. package/dist/audit/report.d.ts +17 -2
  5. package/dist/branch-actions.d.ts +7 -1
  6. package/dist/build-requests-github.d.ts +25 -0
  7. package/dist/build-requests.d.ts +403 -0
  8. package/dist/changelog-model.d.ts +102 -0
  9. package/dist/component-spec.d.ts +3 -1
  10. package/dist/config.d.ts +21 -0
  11. package/dist/css-color.d.ts +25 -0
  12. package/dist/docs-proposal.d.ts +1 -0
  13. package/dist/explorations.d.ts +1 -0
  14. package/dist/fidelity-references.d.ts +12 -0
  15. package/dist/figma-fix-loop.d.ts +153 -0
  16. package/dist/figma-fixes.d.ts +169 -0
  17. package/dist/figma-push-github.d.ts +7 -2
  18. package/dist/figma-push.d.ts +15 -2
  19. package/dist/gap-case.d.ts +144 -0
  20. package/dist/github-client.d.ts +31 -0
  21. package/dist/id-map.d.ts +10 -0
  22. package/dist/index.d.ts +14 -0
  23. package/dist/index.js +3944 -774
  24. package/dist/index.js.map +1 -1
  25. package/dist/layered-review.d.ts +2 -0
  26. package/dist/measure-status.d.ts +127 -0
  27. package/dist/measured-only.d.ts +28 -0
  28. package/dist/measured-spec.d.ts +349 -0
  29. package/dist/measured-tokens.d.ts +25 -0
  30. package/dist/motion-docs.d.ts +51 -0
  31. package/dist/node/audit.d.ts +11 -3
  32. package/dist/node/index.d.ts +1 -0
  33. package/dist/node/index.js +1637 -24
  34. package/dist/node/index.js.map +1 -1
  35. package/dist/node/measure-script.d.ts +1 -0
  36. package/dist/node/measure.d.ts +212 -0
  37. package/dist/node/spec-css.d.ts +9 -1
  38. package/dist/node/tokens-script.d.ts +3 -0
  39. package/dist/pr-composer.d.ts +5 -0
  40. package/dist/previews.d.ts +4 -1
  41. package/dist/{prod-branch-DenQkr_e.js → prod-branch-Bdx_2bRQ.js} +197 -159
  42. package/dist/prod-branch-Bdx_2bRQ.js.map +1 -0
  43. package/dist/prod-branch.d.ts +1 -1
  44. package/dist/repo-model.d.ts +5 -1
  45. package/dist/repo-source-github.d.ts +8 -0
  46. package/dist/{repo-source-B4jNZhyC.js → repo-source-m0Tc603o.js} +1406 -629
  47. package/dist/repo-source-m0Tc603o.js.map +1 -0
  48. package/dist/repo-source.d.ts +6 -0
  49. package/dist/{report-DVEmUr0p.js → report-DFPKygfk.js} +17 -6
  50. package/dist/{report-DVEmUr0p.js.map → report-DFPKygfk.js.map} +1 -1
  51. package/dist/requester.d.ts +14 -0
  52. package/dist/requests.d.ts +2 -0
  53. package/dist/review-gate.d.ts +183 -2
  54. package/dist/risk.d.ts +12 -0
  55. package/dist/share-branch.d.ts +1 -1
  56. package/dist/snapshot.d.ts +34 -0
  57. package/dist/suggestion-review.d.ts +2 -0
  58. package/dist/suggestions-github.d.ts +21 -0
  59. package/dist/suggestions.d.ts +6 -0
  60. package/dist/token-proposal.d.ts +7 -0
  61. package/dist/try-in-product.d.ts +9 -0
  62. package/package.json +1 -1
  63. package/dist/prod-branch-DenQkr_e.js.map +0 -1
  64. package/dist/repo-source-B4jNZhyC.js.map +0 -1
@@ -2,10 +2,11 @@ import { execFile, execFileSync } from "node:child_process";
2
2
  import { mkdtemp, rm, mkdir, writeFile, lstat, readFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join, resolve, relative, dirname, sep, posix } from "node:path";
5
- import { b2 as assertSafeBranch, c as collectHistory, p as packageDirCandidates, a as parseChangelog, m as mergeReleases, r as releasesFromTags, b as buildReport, cI as prNumberFromSubject, d3 as specHash, dy as validateComponentSpec, bZ as hashSpec, b_ as iconComponentName, C as variantKeyOf, dt as tokenCssVar, ap as COMPONENT_SPECS_VERSION, ao as COLOR_FIELDS, d8 as suggestionAppliedComment, X as gitBlobSha, cG as planSuggestionApply, ak as normalizeRepoPath } from "../repo-source-B4jNZhyC.js";
6
- import { K as selectTokenFiles, ag as globToRegExp, N as loadConfig, L as LayeredTokenSet, V as CONFIG_FILE, $ as layoutOptions, a0 as buildTokenSet, b7 as defaultContext, B as resolve$1, ae as slugify, b$ as protectedBranchesOf, aQ as baseBranchOf } from "../prod-branch-DenQkr_e.js";
5
+ import { bo as assertSafeBranch, c as collectHistory, p as packageDirCandidates, a as parseChangelog, m as mergeReleases, r as releasesFromTags, b as buildReport, de as prNumberFromSubject, dE as specHash, e9 as validateComponentSpec, K as hashSpec, cn as iconComponentName, F as variantKeyOf, e3 as tokenCssVar, aG as COMPONENT_SPECS_VERSION, J as COLOR_FIELDS, dM as suggestionAppliedComment, a1 as gitBlobSha, dc as planSuggestionApply, aq as normalizeRepoPath, dB as sharedTokenPrefix, e6 as tokenVariablePath, ej as withSrgbColors, dH as storybookIframeUrl, cX as parseBoxShadow } from "../repo-source-m0Tc603o.js";
6
+ import { aV, C, c4, cJ, I, c_, H } from "../repo-source-m0Tc603o.js";
7
+ import { K as selectTokenFiles, ag as globToRegExp, N as loadConfig, L as LayeredTokenSet, V as CONFIG_FILE, $ as layoutOptions, a0 as buildTokenSet, b9 as defaultContext, B as resolve$1, ae as slugify, c2 as protectedBranchesOf, aS as baseBranchOf } from "../prod-branch-Bdx_2bRQ.js";
7
8
  import { statSync, readFileSync, existsSync, writeFileSync, readdirSync } from "node:fs";
8
- import { i as isAuditable, Q as planCssFixes, O as parseAllowlist, d as DesignSystemIndex, l as buildAuditReport, o as compareWithBaseline, b as AUDIT_IGNORE_DIRS } from "../report-DVEmUr0p.js";
9
+ import { i as isAuditable, Q as planCssFixes, O as parseAllowlist, d as DesignSystemIndex, l as buildAuditReport, o as compareWithBaseline, b as AUDIT_IGNORE_DIRS } from "../report-DFPKygfk.js";
9
10
  import ts from "typescript";
10
11
  function git(root, args, opts = {}) {
11
12
  return new Promise((resolve2, reject) => {
@@ -295,16 +296,17 @@ function runAudit(target, opts = {}) {
295
296
  );
296
297
  return opts.baseline ? compareWithBaseline(report, opts.baseline) : report;
297
298
  }
298
- function fixCss(target, ds, write) {
299
- const { root, files } = collectAuditFiles(target);
299
+ function fixCss(target, ds, write, opts = {}) {
300
+ const { root, files } = collectAuditFiles(target, opts.exclude ?? []);
300
301
  const out = [];
301
302
  for (const f of files) {
302
303
  const lang = f.path.endsWith(".scss") || f.path.endsWith(".sass") ? "scss" : f.path.endsWith(".less") ? "less" : f.path.endsWith(".css") ? "css" : null;
303
304
  if (!lang) continue;
304
- const plan = planCssFixes(f.text, lang, ds);
305
- if (!plan.edits.length) continue;
306
- if (write) writeFileSync(join(root, f.path), plan.output);
307
- out.push({ file: f.path, edits: plan.edits });
305
+ const allowlist = (opts.allowlist ?? []).filter((e) => toPosix(e.file) === f.path);
306
+ const plan = planCssFixes(f.text, lang, ds, { allowlist });
307
+ if (!plan.edits.length && !plan.kept.length) continue;
308
+ if (write && plan.edits.length) writeFileSync(join(root, f.path), plan.output);
309
+ out.push({ file: f.path, edits: plan.edits, kept: plan.kept });
308
310
  }
309
311
  return out;
310
312
  }
@@ -429,11 +431,17 @@ function specificityOf(c) {
429
431
  return sp;
430
432
  }
431
433
  const cmpSpec = (a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
434
+ const SPEC_VIEWPORT_WIDTH = 1200;
432
435
  function mediaApplies(query) {
433
436
  const q = query.replace(/\s+/g, " ").trim().toLowerCase();
434
437
  if (q.startsWith("@supports")) return true;
435
438
  const cond = q.replace(/^@media /, "");
436
- return /^\((any-)?hover: ?hover\)$/.test(cond) || cond === "screen" || cond === "all";
439
+ return cond.split(" and ").every((c) => {
440
+ if (/^\((any-)?hover: ?hover\)$/.test(c) || c === "screen" || c === "all") return true;
441
+ const w = /^\((min|max)-width: ?([\d.]+)px\)$/.exec(c);
442
+ if (!w) return false;
443
+ return w[1] === "min" ? SPEC_VIEWPORT_WIDTH >= Number(w[2]) : SPEC_VIEWPORT_WIDTH <= Number(w[2]);
444
+ });
437
445
  }
438
446
  function parseCssModule(module, text, startOrder = 0) {
439
447
  const rules = [];
@@ -1052,6 +1060,25 @@ class Reader {
1052
1060
  opts;
1053
1061
  cache = /* @__PURE__ */ new Map();
1054
1062
  aliasCache = /* @__PURE__ */ new Map();
1063
+ elements = /* @__PURE__ */ new Map();
1064
+ /**
1065
+ * The element a Base UI part renders ("Increment" -> "button"), as Base UI's own docs say it
1066
+ * (node_modules/@base-ui/react/docs/react/components/<module>.md: "### Increment ... Renders a `<button>` element").
1067
+ */
1068
+ baseUiElement(modules, part) {
1069
+ for (const m of modules) {
1070
+ let parts = this.elements.get(m);
1071
+ if (!parts) {
1072
+ parts = /* @__PURE__ */ new Map();
1073
+ const text = this.opts.read(`node_modules/@base-ui/react/docs/react/components/${m}.md`) ?? "";
1074
+ for (const hit of text.matchAll(/^### ([\w.]+)\n(?:(?!#)[^\n]*\n){0,6}?Renders an? `<([a-z0-9-]+)>` element/gm)) parts.set(hit[1], hit[2]);
1075
+ this.elements.set(m, parts);
1076
+ }
1077
+ const el = parts.get(part);
1078
+ if (el) return el;
1079
+ }
1080
+ return void 0;
1081
+ }
1055
1082
  dirOf(name) {
1056
1083
  return `${this.opts.componentsDir}/${name}`;
1057
1084
  }
@@ -1424,7 +1451,11 @@ function evaluate(e, scope) {
1424
1451
  if (ts.isObjectLiteralExpression(e)) {
1425
1452
  const out = {};
1426
1453
  for (const p of e.properties) {
1427
- if (ts.isPropertyAssignment(p)) out[unquote(p.name.getText(sf))] = evaluate(p.initializer, scope);
1454
+ if (ts.isPropertyAssignment(p) && ts.isComputedPropertyName(p.name)) {
1455
+ const key = evaluate(p.name.expression, scope);
1456
+ if (typeof key !== "string" && typeof key !== "number") return OPAQUE;
1457
+ out[String(key)] = evaluate(p.initializer, scope);
1458
+ } else if (ts.isPropertyAssignment(p)) out[unquote(p.name.getText(sf))] = evaluate(p.initializer, scope);
1428
1459
  else if (ts.isShorthandPropertyAssignment(p)) out[p.name.text] = lookup(scope, p.name.text);
1429
1460
  else if (ts.isSpreadAssignment(p)) {
1430
1461
  const v = evaluate(p.expression, scope);
@@ -1436,6 +1467,12 @@ function evaluate(e, scope) {
1436
1467
  if (ts.isArrayLiteralExpression(e)) return e.elements.map((x) => evaluate(x, scope));
1437
1468
  return OPAQUE;
1438
1469
  }
1470
+ function styleVarsOf(style) {
1471
+ if (!style || typeof style !== "object" || Array.isArray(style) || isJsx(style)) return void 0;
1472
+ const vars = /* @__PURE__ */ new Map();
1473
+ for (const [k, v] of Object.entries(style)) if (k.startsWith("--") && (typeof v === "number" || typeof v === "string")) vars.set(k, String(v));
1474
+ return vars.size ? vars : void 0;
1475
+ }
1439
1476
  const isData = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" || v === null || v === void 0 || Array.isArray(v) && v.every(isData) || !!v && typeof v === "object" && !isJsx(v) && !isClass(v) && !isStyles(v) && !isTextRef(v) && !isFnRef(v) && Object.values(v).every(isData);
1440
1477
  function callData(fn, args) {
1441
1478
  const data = args.map((a) => isTextRef(a) ? a.text : a);
@@ -1725,7 +1762,11 @@ function renderJsx(ref, ctx, visible) {
1725
1762
  const extra = classList(attrs.className);
1726
1763
  if (isJsx(r)) {
1727
1764
  const nodes = renderJsx(r, ctx, visible);
1728
- if (nodes[0]) nodes[0].classes = [...nodes[0].classes, ...extra];
1765
+ if (nodes[0]) {
1766
+ nodes[0].classes = [...nodes[0].classes, ...extra];
1767
+ const vars2 = styleVarsOf(attrs.style);
1768
+ if (vars2) nodes[0].styleVars = new Map([...nodes[0].styleVars ?? [], ...vars2]);
1769
+ }
1729
1770
  return nodes;
1730
1771
  }
1731
1772
  const init = open.attributes.properties.find((a) => ts.isJsxAttribute(a) && a.name.getText(sf) === "render")?.initializer;
@@ -1763,22 +1804,20 @@ function renderJsx(ref, ctx, visible) {
1763
1804
  children: [],
1764
1805
  kind: "frame",
1765
1806
  ...visible ? { visible } : {},
1766
- ...scope.src.baseUi.has(tag.split(".")[0]) ? ctx.selected !== void 0 && typeof attrs.value === "string" ? { baseUi: true, checked: attrs.value === ctx.selected ? "true" : "false", selectedBy: true } : { baseUi: true, checked: scope.main ? "state" : scope.checked ?? "false" } : {},
1807
+ ...scope.src.baseUi.has(tag.split(".")[0]) ? ctx.selected !== void 0 && typeof attrs.value === "string" ? { baseUi: true, checked: (Array.isArray(ctx.selected) ? ctx.selected.includes(attrs.value) : attrs.value === ctx.selected) ? "true" : "false", selectedBy: true } : { baseUi: true, checked: scope.main ? "state" : scope.checked ?? "false" } : {},
1767
1808
  ...dataAttrs.size ? { attrs: dataAttrs } : {},
1768
1809
  .../(^img$|\.Image$)/.test(tag) ? { media: true } : {},
1769
1810
  // Base UI indicators are only mounted while their item is checked, unless keepMounted.
1770
1811
  .../\.(Item)?Indicator$/.test(tag) && scope.src.baseUi.has(tag.split(".")[0]) && attrs.keepMounted !== true && ctx.fraction === void 0 ? { whenChecked: true } : {}
1771
1812
  };
1813
+ const element = isBaseUi ? ctx.reader.baseUiElement(scope.src.baseUiModules, tag.split(".").slice(1).join(".")) : tag;
1814
+ if (element === "button" || element === "select") node.borderBox = true;
1772
1815
  if (isBaseUi && /\.Panel$/.test(tag) && node.selectedBy && node.checked === "false") node.inactive = true;
1773
1816
  if (isBaseUi && /\.Thumb$/.test(tag) && ctx.fraction !== void 0) node.at = ctx.fraction;
1774
1817
  const bg = attrs.style && typeof attrs.style === "object" && !Array.isArray(attrs.style) ? attrs.style.backgroundColor : void 0;
1775
1818
  if (typeof bg === "string") node.inlineFill = bg;
1776
- const style = attrs.style;
1777
- if (style && typeof style === "object" && !Array.isArray(style) && !isJsx(style)) {
1778
- const vars = /* @__PURE__ */ new Map();
1779
- for (const [k, v] of Object.entries(style)) if (k.startsWith("--") && (typeof v === "number" || typeof v === "string")) vars.set(k, String(v));
1780
- if (vars.size) node.styleVars = vars;
1781
- }
1819
+ const vars = styleVarsOf(attrs.style);
1820
+ if (vars) node.styleVars = vars;
1782
1821
  if (tag === "svg") {
1783
1822
  const lit = {};
1784
1823
  for (const [k, v] of Object.entries(attrs)) if ((typeof v === "string" || typeof v === "number") && k !== "className") lit[k] = String(v);
@@ -2190,6 +2229,24 @@ function collapseText(n, root = true, boxed = () => false, unseen = () => false)
2190
2229
  }
2191
2230
  return n;
2192
2231
  }
2232
+ function inheritedInside(root, classes, rules, page) {
2233
+ const path = [];
2234
+ const find = (n) => {
2235
+ if (n !== root && classes.every((c) => n.classes.includes(c))) return true;
2236
+ path.push(n);
2237
+ for (const c of n.children) if (find(c)) return true;
2238
+ path.pop();
2239
+ return false;
2240
+ };
2241
+ if (!find(root)) return void 0;
2242
+ let ctx = page;
2243
+ for (const n of path) {
2244
+ if (n.kind !== "frame") continue;
2245
+ const el = { tag: n.tag, classes: new Set(n.classes), children: [], present: true, isRoot: false, inputLike: false };
2246
+ ctx = computeValues(declaredFor(rules, el, DEFAULT_STATE), ctx);
2247
+ }
2248
+ return ctx;
2249
+ }
2193
2250
  function applyView(root, view) {
2194
2251
  if (!view) return root;
2195
2252
  const isPortal = (n) => /\.Portal$/.test(n.tag);
@@ -2209,7 +2266,8 @@ function applyView(root, view) {
2209
2266
  }
2210
2267
  function build(reader, src, props, preview, view, rules = [], tokens, examples) {
2211
2268
  const blockers = [];
2212
- const selected = typeof props.defaultValue === "string" ? props.defaultValue : void 0;
2269
+ const dv = props.defaultValue;
2270
+ const selected = typeof dv === "string" ? dv : Array.isArray(dv) && dv.every((x) => typeof x === "string") ? dv : void 0;
2213
2271
  const rendered = renderComponent(reader, src.name, { ...props, children: CHILDREN }, { reader, depth: 0, component: src.name, blockers, ...selected !== void 0 ? { selected } : {}, ...examples ? { examples } : {} }, void 0, preview);
2214
2272
  let root = rendered && applyView(rendered, view);
2215
2273
  if (!root) return void 0;
@@ -2227,10 +2285,12 @@ function build(reader, src, props, preview, view, rules = [], tokens, examples)
2227
2285
  root.children.push(n);
2228
2286
  }
2229
2287
  }
2230
- const follow = (n, inherited) => {
2288
+ const follow = (n, inherited, item) => {
2231
2289
  if (n.baseUi && n.selectedBy) inherited = n.checked;
2232
2290
  else if (n.baseUi && inherited) n.checked = inherited;
2233
- for (const c of n.children) follow(c, inherited);
2291
+ if (n.baseUi && /\.Item$/.test(n.tag)) item = n;
2292
+ if (n.baseUi && /\.Panel$/.test(n.tag) && item && item.checked !== "true" && item.checked !== "state") n.inactive = true;
2293
+ for (const c of n.children) follow(c, inherited, item);
2234
2294
  };
2235
2295
  follow(root, void 0);
2236
2296
  decorate(root, rules, tokens);
@@ -2393,9 +2453,23 @@ function resolveValue(raw, values, tokens, depth = 0, parent, forColor = false)
2393
2453
  return { unmapped: "literal value, not a token" };
2394
2454
  }
2395
2455
  function calcValue(v, values, tokens, depth, parent) {
2396
- const inner = v.slice(v.indexOf("(") + 1, v.lastIndexOf(")"));
2456
+ let inner = v.slice(v.indexOf("(") + 1, v.lastIndexOf(")"));
2397
2457
  let failed;
2458
+ if (/\d*\.?\d+lh\b/.test(inner)) {
2459
+ const fs = resolveValue(values.get("font-size"), values, tokens, depth + 1, parent);
2460
+ const lh = resolveValue(values.get("line-height"), values, tokens, depth + 1, parent);
2461
+ if (typeof fs?.value === "string" && typeof lh?.value === "string" && !fs.value.startsWith("calc(") && !lh.value.startsWith("calc(")) {
2462
+ inner = inner.replace(/(\d*\.?\d+)lh\b/g, (_m, n) => Number(n) === 1 ? `(${fs.value} * ${lh.value})` : `${n} * (${fs.value} * ${lh.value})`);
2463
+ }
2464
+ }
2398
2465
  const substituted = inner.replace(/var\(\s*--[\w-]+\s*(?:,[^()]*)?\)/g, (m) => {
2466
+ let raw = m;
2467
+ for (let hops = 0; hops < 12 && raw; hops++) {
2468
+ const name = /^var\(\s*(--[\w-]+)/.exec(raw.trim())?.[1];
2469
+ if (!name || tokens.has(name)) break;
2470
+ raw = values.get(name);
2471
+ }
2472
+ if (raw !== void 0 && /^-?\d*\.?\d+$/.test(raw.trim())) return raw.trim();
2399
2473
  const r = resolveValue(m, values, tokens, depth + 1, parent);
2400
2474
  if (!r || r.unmapped !== void 0 || r.value === null || r.value === void 0) {
2401
2475
  failed ??= r?.unmapped ?? `${m} has no value`;
@@ -2531,8 +2605,29 @@ function partValues(node, computed, own, tokens, parent) {
2531
2605
  const v = own.get(prop);
2532
2606
  if (v !== void 0 && /var\(/.test(v)) out.unmapped.push({ property: prop, value: v, reason });
2533
2607
  }
2608
+ contentBoxMinimums(out.values, computed, node.borderBox);
2534
2609
  return out;
2535
2610
  }
2611
+ function contentBoxMinimums(values, computed, borderBoxByDefault = false) {
2612
+ if ((computed.get("box-sizing") ?? (borderBoxByDefault ? "border-box" : "content-box")).trim() === "border-box") return;
2613
+ const term = (v) => {
2614
+ if (v === void 0 || v === null || v === 0) return void 0;
2615
+ if (typeof v === "number") return String(v);
2616
+ if (typeof v !== "string") return void 0;
2617
+ return v.startsWith("calc(") ? `(${v.slice(5, -1)})` : v;
2618
+ };
2619
+ const sum = (base, extra) => {
2620
+ const add = extra.map(term).filter((t) => !!t);
2621
+ const head = term(base);
2622
+ if (!add.length || !head) return base;
2623
+ return `calc(${[head, ...add].join(" + ")})`;
2624
+ };
2625
+ const border = (side) => values[`stroke${side}Weight`] ?? values.strokeWeight;
2626
+ if (values.minHeight !== void 0) values.minHeight = sum(values.minHeight, [values.paddingTop, values.paddingBottom, border("Top"), border("Bottom")]);
2627
+ if (values.minWidth !== void 0) values.minWidth = sum(values.minWidth, [values.paddingLeft, values.paddingRight, border("Left"), border("Right")]);
2628
+ if (values.height !== void 0) values.height = sum(values.height, [values.paddingTop, values.paddingBottom, border("Top"), border("Bottom")]);
2629
+ if (values.width !== void 0) values.width = sum(values.width, [values.paddingLeft, values.paddingRight, border("Left"), border("Right")]);
2630
+ }
2536
2631
  const singleCellGrid = (c) => /grid/.test(c.get("display") ?? "") && ["grid-template-columns", "grid-template-rows", "grid-template-areas", "grid-template", "grid-auto-flow", "grid-auto-columns"].every((k) => !c.get(k) || c.get(k) === "none");
2537
2632
  const TABLE_DISPLAY = { table: "table", thead: "table-row-group", tbody: "table-row-group", tfoot: "table-row-group", tr: "table-row", td: "table-cell", th: "table-cell", caption: "table-caption" };
2538
2633
  const gridCounter = (v) => /center/.test(v ?? "") ? "CENTER" : /end/.test(v ?? "") ? "MAX" : /start/.test(v ?? "") ? "MIN" : "STRETCH";
@@ -2944,6 +3039,14 @@ function generateComponentSpec(name, opts, view, setName = name, fixed = {}) {
2944
3039
  const v = previewEl?.p?.[p.name];
2945
3040
  if (p.kind === "string" && p.optional && typeof v === "string" && baseProps[p.name] === void 0) examples[p.name] = v;
2946
3041
  }
3042
+ if (view === "without-popup" && name !== src.folder) {
3043
+ const own = build(reader, src, { ...baseProps, ...fixed }, previewKids, view, rules, opts.tokens)?.root.classes ?? [];
3044
+ const folderSrc = reader.load(src.folder);
3045
+ const folderPreview = previewElement(docs?.preview, src.folder) ?? storyElement(readStories(src.folder, opts), src.folder);
3046
+ const folderKids = folderPreview?.children?.some((c) => typeof c !== "string") ? folderPreview.children : void 0;
3047
+ const popup = own.length && folderSrc && folderKids ? build(reader, folderSrc, {}, folderKids, "popup", rules, opts.tokens) : void 0;
3048
+ if (popup) page = inheritedInside(popup.root, own, rules, page) ?? inheritedInside({ ...popup.root, children: [{ ...popup.root, classes: own, children: [] }] }, own, rules, page) ?? page;
3049
+ }
2947
3050
  const evalAt = (props, state) => evaluateVariant(reader, src, rules, { ...baseProps, ...props, ...fixed }, state, opts.tokens, previewKids, page, view, Object.keys(examples).length ? examples : void 0);
2948
3051
  const base = evalAt({}, DEFAULT_STATE);
2949
3052
  if (!base) throw new UnsupportedComponentError(name, "renders in a way the generator cannot read yet");
@@ -3844,25 +3947,1518 @@ function fsSource(root, ref = {}) {
3844
3947
  }
3845
3948
  };
3846
3949
  }
3950
+ const MEASURE_SCRIPT = String.raw`(function (arg) {
3951
+ arg = arg || {};
3952
+ var MAX_NODES = arg.maxNodes || 400;
3953
+ var MAX_DEPTH = arg.maxDepth || 14;
3954
+ var rootSel = arg.root || '#storybook-root, #root';
3955
+ var PROPS = ['display', 'position', 'visibility', 'opacity', 'overflow', 'box-sizing',
3956
+ 'flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'align-self', 'flex-grow', 'row-gap', 'column-gap',
3957
+ 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
3958
+ 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
3959
+ 'width', 'height', 'min-width', 'min-height',
3960
+ 'background-color', 'background-image',
3961
+ 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width',
3962
+ 'border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style',
3963
+ 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color',
3964
+ 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius',
3965
+ 'box-shadow', 'outline-style', 'outline-width', 'outline-color',
3966
+ 'color', 'font-family', 'font-size', 'font-weight', 'line-height', 'letter-spacing', 'text-decoration-line', 'text-transform', 'text-align', 'white-space',
3967
+ 'fill', 'stroke', 'stroke-width', 'transform', 'grid-auto-flow', 'grid-template-columns', 'grid-template-rows', 'left', 'top', 'right', 'bottom'];
3968
+ // Properties a token is looked for (paint, spacing, shape, type).
3969
+ var TOKENED = ['row-gap', 'column-gap', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'width', 'height', 'min-width', 'min-height',
3970
+ 'background-color', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width',
3971
+ 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color',
3972
+ 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius',
3973
+ 'box-shadow', 'opacity', 'color', 'font-family', 'font-size', 'font-weight', 'line-height', 'letter-spacing', 'fill', 'stroke', 'stroke-width'];
3974
+ // Longhand -> shorthands that may set it, with the position of the longhand in a 1 to 4 value box shorthand.
3975
+ var SIDES = { top: 0, right: 1, bottom: 2, left: 3 };
3976
+ var CORNERS = { 'top-left': 0, 'top-right': 1, 'bottom-right': 2, 'bottom-left': 3 };
3977
+ var LOGICAL = { top: 'block-start', bottom: 'block-end', left: 'inline-start', right: 'inline-end' };
3978
+ var LOGICAL_CORNER = { 'top-left': 'start-start', 'top-right': 'start-end', 'bottom-right': 'end-end', 'bottom-left': 'end-start' };
3979
+ function shorthandsOf(p) {
3980
+ var m;
3981
+ // Logical longhands too (padding-block-start: a horizontal writing mode, left to right).
3982
+ if ((m = /^padding-(top|right|bottom|left)$/.exec(p))) return [['padding-' + LOGICAL[m[1]], -1], ['padding', SIDES[m[1]]], ['padding-block', m[1] === 'top' ? 0 : m[1] === 'bottom' ? 1 : -1], ['padding-inline', m[1] === 'left' ? 0 : m[1] === 'right' ? 1 : -1]].filter(function (x) { return !/block$|inline$/.test(x[0]) || x[1] >= 0; });
3983
+ if ((m = /^margin-(top|right|bottom|left)$/.exec(p))) return [['margin-' + LOGICAL[m[1]], -1], ['margin', SIDES[m[1]]]];
3984
+ if ((m = /^border-(top-left|top-right|bottom-right|bottom-left)-radius$/.exec(p))) return [['border-' + LOGICAL_CORNER[m[1]] + '-radius', -1], ['border-radius', CORNERS[m[1]]]];
3985
+ if ((m = /^border-(top|right|bottom|left)-(width|color|style)$/.exec(p))) return [['border-' + LOGICAL[m[1]] + '-' + m[2], -1], ['border-' + LOGICAL[m[1]], -1], ['border-' + m[2], SIDES[m[1]]], ['border-' + m[1], -1], ['border', -1], ['border-' + (m[1] === 'top' || m[1] === 'bottom' ? 'block' : 'inline'), -1]];
3986
+ if (p === 'row-gap') return [['gap', 0]];
3987
+ if (p === 'column-gap') return [['gap', 1]];
3988
+ if (p === 'background-color') return [['background', -1]];
3989
+ if (/^font-/.test(p) || p === 'line-height') return [['font', -1]];
3990
+ return [];
3991
+ }
3992
+
3993
+ // ---- style rules, read once ----
3994
+ var rules = [];
3995
+ var order = 0;
3996
+ function walk(list, layered) {
3997
+ for (var i = 0; i < list.length; i++) {
3998
+ var r = list[i];
3999
+ try {
4000
+ if (r.selectorText !== undefined && r.style) {
4001
+ rules.push({ sel: r.selectorText, style: r.style, order: order++, layered: layered });
4002
+ if (r.cssRules && r.cssRules.length) walk(r.cssRules, layered); // CSS nesting
4003
+ } else if (r.media !== undefined && r.cssRules) {
4004
+ if (window.matchMedia(r.media.mediaText || 'all').matches) walk(r.cssRules, layered);
4005
+ } else if (r.conditionText !== undefined && r.cssRules) {
4006
+ walk(r.cssRules, layered);
4007
+ } else if (r.cssRules && r.name !== undefined) {
4008
+ walk(r.cssRules, true); // @layer block: unlayered rules win over it
4009
+ } else if (r.cssRules) {
4010
+ walk(r.cssRules, layered);
4011
+ }
4012
+ } catch (e) {}
4013
+ }
4014
+ }
4015
+ var sheetsRead = 0, sheetsBlocked = 0;
4016
+ for (var s = 0; s < document.styleSheets.length; s++) {
4017
+ try { walk(document.styleSheets[s].cssRules, false); sheetsRead++; } catch (e) { sheetsBlocked++; }
4018
+ }
4019
+ try { for (var a = 0; a < (document.adoptedStyleSheets || []).length; a++) walk(document.adoptedStyleSheets[a].cssRules, false); } catch (e) {}
4020
+
4021
+ function splitTop(text, sepRe) {
4022
+ var out = [], depth = 0, cur = '', q = null;
4023
+ for (var i = 0; i < text.length; i++) {
4024
+ var c = text[i];
4025
+ if (q) { cur += c; if (c === q) q = null; continue; }
4026
+ if (c === '"' || c === "'") { q = c; cur += c; continue; }
4027
+ if (c === '(' || c === '[') depth++;
4028
+ if (c === ')' || c === ']') depth--;
4029
+ if (depth === 0 && sepRe.test(c)) { if (cur.trim()) out.push(cur.trim()); cur = ''; continue; }
4030
+ cur += c;
4031
+ }
4032
+ if (cur.trim()) out.push(cur.trim());
4033
+ return out;
4034
+ }
4035
+ function specificity(sel) {
4036
+ var s = sel.replace(/:where\([^)]*\)/g, '').replace(/::?(before|after|placeholder|selection|marker|backdrop)\b/g, '');
4037
+ var ids = (s.match(/#[\w-]+/g) || []).length;
4038
+ var cls = (s.match(/\.[\w-]+|\[[^\]]*\]|:(?!not\b|is\b|has\b)[\w-]+(\([^)]*\))?/g) || []).length;
4039
+ var types = (s.replace(/\[[^\]]*\]|\([^)]*\)/g, '').match(/(^|[\s>+~(])[a-zA-Z][\w-]*/g) || []).length;
4040
+ return ids * 10000 + cls * 100 + types;
4041
+ }
4042
+ var PSEUDO_END = /::?(before|after)\s*$/;
4043
+ // pseudo: the rules for el::before / el::after (the selector minus its pseudo-element); none: the element's own.
4044
+ function matchSpec(el, selText, pseudo) {
4045
+ var best = -1;
4046
+ var parts = splitTop(selText, /,/);
4047
+ for (var i = 0; i < parts.length; i++) {
4048
+ var part = parts[i];
4049
+ var pm = PSEUDO_END.exec(part);
4050
+ if (pseudo) {
4051
+ if (!pm || pm[1] !== pseudo) continue;
4052
+ part = part.slice(0, pm.index).trim() || '*';
4053
+ } else if (pm || /::/.test(part)) continue;
4054
+ try { if (el.matches(part)) best = Math.max(best, specificity(part) + (pseudo ? 1 : 0)); } catch (e) {}
4055
+ }
4056
+ return best;
4057
+ }
4058
+ var matchCache = { '': new Map(), before: new Map(), after: new Map() };
4059
+ function matching(el, pseudo) {
4060
+ var cache = matchCache[pseudo || ''];
4061
+ var m = cache.get(el);
4062
+ if (m) return m;
4063
+ m = [];
4064
+ for (var i = 0; i < rules.length; i++) {
4065
+ var sp = matchSpec(el, rules[i].sel, pseudo);
4066
+ if (sp >= 0) m.push({ r: rules[i], sp: sp });
4067
+ }
4068
+ cache.set(el, m);
4069
+ return m;
4070
+ }
4071
+ // The winning declared value of a property (longhand or the shorthand that sets it) on an element or its pseudo.
4072
+ function declared(el, prop, pseudo) {
4073
+ var best = null;
4074
+ function consider(value, important, layered, sp, ord, shorthand, pos) {
4075
+ if (!value) return;
4076
+ var rank = [important ? (layered ? 3 : 2) : (layered ? 0 : 1), sp, ord];
4077
+ if (!best || cmp(rank, best.rank) > 0) best = { value: value, rank: rank, shorthand: shorthand, pos: pos };
4078
+ }
4079
+ function cmp(x, y) { for (var i = 0; i < x.length; i++) if (x[i] !== y[i]) return x[i] - y[i]; return 0; }
4080
+ var short = prop.indexOf('--') === 0 ? [] : shorthandsOf(prop);
4081
+ var m = matching(el, pseudo);
4082
+ for (var i = 0; i < m.length; i++) {
4083
+ var st = m[i].r.style;
4084
+ var v = st.getPropertyValue(prop);
4085
+ if (v) consider(v, st.getPropertyPriority(prop) === 'important', m[i].r.layered, m[i].sp, m[i].r.order, null, -1);
4086
+ else for (var k = 0; k < short.length; k++) {
4087
+ var sv = st.getPropertyValue(short[k][0]);
4088
+ if (sv) consider(sv, st.getPropertyPriority(short[k][0]) === 'important', m[i].r.layered, m[i].sp, m[i].r.order, short[k][0], short[k][1]);
4089
+ }
4090
+ }
4091
+ var inl = !pseudo && el.style && el.style.getPropertyValue(prop);
4092
+ if (inl) consider(inl, el.style.getPropertyPriority(prop) === 'important', false, 1e9, 1e9, null, -1);
4093
+ else if (el.style && !pseudo) for (var j = 0; j < short.length; j++) {
4094
+ var iv = el.style.getPropertyValue(short[j][0]);
4095
+ if (iv) consider(iv, false, false, 1e9, 1e9, short[j][0], short[j][1]);
4096
+ }
4097
+ return best;
4098
+ }
4099
+ function varsIn(value) {
4100
+ var out = [], re = /var\(\s*(--[\w-]+)/g, m;
4101
+ while ((m = re.exec(value))) out.push(m[1]);
4102
+ return out;
4103
+ }
4104
+ // The piece of a box shorthand that sets one side ("padding: var(--a) var(--b)" -> right is var(--b)).
4105
+ function boxPiece(value, pos) {
4106
+ if (pos < 0) return value;
4107
+ var parts = splitTop(value.replace(/\s*\/.*$/, ''), /\s/);
4108
+ if (parts.length === 1) return parts[0];
4109
+ if (parts.length === 2) return parts[pos % 2];
4110
+ if (parts.length === 3) return parts[pos === 3 ? 1 : pos];
4111
+ return parts[pos] || value;
4112
+ }
4113
+ // Custom property chain: --button-bg -> --color-action-primary-bg -> --color-orange-500.
4114
+ function chainOf(el, name) {
4115
+ var chain = [name], seen = {};
4116
+ seen[name] = 1;
4117
+ var cur = name;
4118
+ for (var d = 0; d < 8; d++) {
4119
+ var found = null;
4120
+ for (var e = el; e && e.nodeType === 1; e = e.parentElement) {
4121
+ var dv = declared(e, cur);
4122
+ if (dv) { found = dv.value; break; }
4123
+ }
4124
+ if (!found) break;
4125
+ var next = varsIn(found);
4126
+ if (next.length !== 1 || seen[next[0]] || found.trim().indexOf('var(') !== 0) break;
4127
+ seen[next[0]] = 1;
4128
+ chain.push(next[0]);
4129
+ cur = next[0];
4130
+ }
4131
+ return chain;
4132
+ }
4133
+
4134
+ // ---- value normalisation through a probe element ----
4135
+ var probe = document.createElement('div');
4136
+ probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none;width:0;height:0';
4137
+ document.body.appendChild(probe);
4138
+ var colorCache = {};
4139
+ function normColor(v) {
4140
+ if (v in colorCache) return colorCache[v];
4141
+ probe.style.color = '';
4142
+ probe.style.color = v;
4143
+ var out = probe.style.color ? getComputedStyle(probe).color : null;
4144
+ colorCache[v] = out;
4145
+ return out;
4146
+ }
4147
+ function normLength(v) {
4148
+ probe.style.width = '';
4149
+ probe.style.width = v;
4150
+ if (!probe.style.width) return null;
4151
+ var w = getComputedStyle(probe).width;
4152
+ probe.style.width = '0';
4153
+ return w;
4154
+ }
4155
+ var isColorProp = function (p) { return /color$/.test(p) || p === 'fill' || p === 'stroke'; };
4156
+
4157
+ // Variables in scope at the component (for value matching): defined on :root, or on a provider element around the
4158
+ // story (Fluent's FluentProvider, a theme wrapper). Custom properties inherit, so the component root's computed style
4159
+ // holds both.
4160
+ var rootVars = null;
4161
+ var scopeEl = null;
4162
+ function rootTokens() {
4163
+ if (rootVars) return rootVars;
4164
+ rootVars = { colors: {}, lengths: {}, count: 0, scoped: 0 };
4165
+ var cs = getComputedStyle(scopeEl || document.documentElement);
4166
+ var top = scopeEl ? getComputedStyle(document.documentElement) : cs;
4167
+ var names = {};
4168
+ for (var i = 0; i < rules.length; i++) {
4169
+ var st = rules[i].style;
4170
+ for (var k = 0; k < st.length; k++) if (st[k].indexOf('--') === 0) names[st[k]] = 1;
4171
+ }
4172
+ for (var i2 = 0; i2 < cs.length; i2++) if (cs[i2].indexOf('--') === 0) names[cs[i2]] = 1;
4173
+ for (var i3 = 0; scopeEl && i3 < top.length; i3++) if (top[i3].indexOf('--') === 0) names[top[i3]] = 1;
4174
+ for (var n in names) {
4175
+ var v = cs.getPropertyValue(n).trim();
4176
+ if (!v) continue;
4177
+ rootVars.count++;
4178
+ if (scopeEl && !top.getPropertyValue(n).trim()) rootVars.scoped++;
4179
+ if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(v)) {
4180
+ var c = normColor(v);
4181
+ if (c) (rootVars.colors[c] = rootVars.colors[c] || []).push(n);
4182
+ } else if (/^-?[\d.]+(px|rem|em)$/.test(v)) {
4183
+ var l = normLength(v);
4184
+ if (l) (rootVars.lengths[l] = rootVars.lengths[l] || []).push(n);
4185
+ }
4186
+ }
4187
+ return rootVars;
4188
+ }
4189
+
4190
+ function tokenFor(el, prop, computed, pseudo) {
4191
+ var d = declared(el, prop, pseudo);
4192
+ // A pseudo-element inherits from its element, an element from its parent.
4193
+ var parentOf = pseudo ? el : el.parentElement;
4194
+ if (d) {
4195
+ var piece = d.shorthand && /^(padding|margin|border-radius|border-width|border-color|border-style|gap)$/.test(d.shorthand) ? boxPiece(d.value, d.pos) : d.value;
4196
+ var vars = varsIn(piece);
4197
+ if (vars.length) {
4198
+ var pick = vars[0];
4199
+ if (vars.length > 1) {
4200
+ var cs = getComputedStyle(el, pseudo ? '::' + pseudo : null);
4201
+ for (var i = 0; i < vars.length; i++) {
4202
+ var rv = cs.getPropertyValue(vars[i]).trim();
4203
+ var same = isColorProp(prop) ? normColor(rv) === computed : normLength(rv) === computed;
4204
+ if (same) { pick = vars[i]; break; }
4205
+ }
4206
+ }
4207
+ var chain = chainOf(el, pick);
4208
+ // A color function around channels alone ("hsl(var(--primary))") gives the variable's color: tied to it too.
4209
+ var channels = isColorProp(prop) && vars.length === 1 ? /^(rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\(\s*var\(\s*--[\w-]+\s*\)\s*\)$/i.exec(piece.trim()) : null;
4210
+ var direct = (piece.trim().indexOf('var(') === 0 && vars.length === 1) || !!channels;
4211
+ // A declaration that does not give the computed value lost the cascade somewhere this script does not model:
4212
+ // the value is not tied to it (it may still match a variable by value below).
4213
+ if (direct && !/^(line-height|font-weight|opacity|font-family)$/.test(prop)) {
4214
+ var own = getComputedStyle(el, pseudo ? '::' + pseudo : null).getPropertyValue(pick).trim();
4215
+ var got = isColorProp(prop) ? normColor(channels ? channels[1] + '(' + own + ')' : own) : /px$/.test(computed) ? normLength(own) : null;
4216
+ if (own && got && got !== computed) d = null;
4217
+ }
4218
+ if (d) return { via: 'declared', chain: chain, exact: direct, declared: piece.trim() };
4219
+ }
4220
+ if (d && /^(inherit|currentcolor)$/i.test(d.value.trim()) && parentOf && prop !== 'background-color') {
4221
+ var cp = prop === 'fill' || prop === 'stroke' || /border-.*-color/.test(prop) ? 'color' : prop;
4222
+ // currentcolor on another property reads this element's (or pseudo's) own color; inherit, and color:
4223
+ // currentcolor, read the parent's (a pseudo-element's parent is its element).
4224
+ var up = /currentcolor/i.test(d.value) && cp !== prop
4225
+ ? tokenFor(el, cp, getComputedStyle(el, pseudo ? '::' + pseudo : null).getPropertyValue(cp), pseudo)
4226
+ : parentOf ? tokenFor(parentOf, cp, getComputedStyle(parentOf).getPropertyValue(cp)) : null;
4227
+ if (up) return up;
4228
+ }
4229
+ } else if (/^(color|font-family|font-size|font-weight|line-height|letter-spacing)$/.test(prop) && parentOf) {
4230
+ // Inherited: the token comes from the nearest ancestor that declares it.
4231
+ return tokenFor(parentOf, prop, computed);
4232
+ }
4233
+ var rt = rootTokens();
4234
+ var hit = isColorProp(prop) ? rt.colors[computed] : rt.lengths[computed];
4235
+ if (hit && hit.length) return { via: 'matched', chain: hit.slice(0, 3), exact: false };
4236
+ return null;
4237
+ }
4238
+
4239
+ // ---- the rendered tree ----
4240
+ var count = 0;
4241
+ function own(el, cs) {
4242
+ var bg = cs.backgroundColor;
4243
+ var hasBg = bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent';
4244
+ var hasBorder = ['Top', 'Right', 'Bottom', 'Left'].some(function (s) { return parseFloat(cs['border' + s + 'Width']) > 0 && cs['border' + s + 'Style'] !== 'none'; });
4245
+ var pad = ['Top', 'Right', 'Bottom', 'Left'].some(function (s) { return parseFloat(cs['padding' + s]) > 0; });
4246
+ var paints = function (v) { return !!v && v !== 'none'; };
4247
+ return hasBg || hasBorder || pad || paints(cs.boxShadow) || paints(cs.backgroundImage);
4248
+ }
4249
+ function directText(el) {
4250
+ var t = '';
4251
+ for (var c = el.firstChild; c; c = c.nextSibling) if (c.nodeType === 3) t += c.nodeValue;
4252
+ return t.replace(/\s+/g, ' ').trim();
4253
+ }
4254
+ function visible(el, cs) {
4255
+ if (cs.display === 'none' || cs.visibility === 'hidden' || cs.visibility === 'collapse') return false;
4256
+ // Closed or hidden content is not a layer: transparent, hidden, inert, clipped away, or a hidden popover.
4257
+ if (parseFloat(cs.opacity) === 0 || el.hidden || el.hasAttribute('inert')) return false;
4258
+ if (/inset\((50|100)%/.test(cs.clipPath || '')) return false;
4259
+ if (el.getAttribute('aria-hidden') === 'true' && (/^(tooltip|dialog|menu|listbox)$/.test(el.getAttribute('role') || '') || /popover|tooltip/i.test(String(el.className && el.className.baseVal !== undefined ? el.className.baseVal : el.className)))) return false;
4260
+ var r = el.getBoundingClientRect();
4261
+ if (r.width === 0 && r.height === 0 && !el.children.length) return false;
4262
+ // Visually hidden text for screen readers (1 px, clipped): not drawn, not a layer.
4263
+ if ((cs.position === 'absolute' || cs.position === 'fixed') && r.width <= 1 && r.height <= 1 && (/hidden|clip/.test(cs.overflow) || cs.clip !== 'auto' && cs.clip !== '' || cs.clipPath !== 'none')) return false;
4264
+ return true;
4265
+ }
4266
+ function round(n) { return Math.round(n * 100) / 100; }
4267
+ // An inline SVG as markup Figma can draw: every shape's computed fill and stroke written on it, currentColor
4268
+ // resolved, the rendered size set.
4269
+ function svgMarkup(el, r) {
4270
+ if (el.outerHTML.length > 12000) return null;
4271
+ var strokes = [];
4272
+ var clone = el.cloneNode(true);
4273
+ var src = [el].concat(Array.prototype.slice.call(el.querySelectorAll('*')));
4274
+ var dst = [clone].concat(Array.prototype.slice.call(clone.querySelectorAll('*')));
4275
+ var color = getComputedStyle(el).color;
4276
+ for (var i = 0; i < src.length && i < dst.length; i++) {
4277
+ var cs = getComputedStyle(src[i]);
4278
+ if (/^(path|circle|rect|ellipse|line|polyline|polygon|use|text)$/.test(src[i].tagName.toLowerCase()) || i === 0) {
4279
+ var f = cs.fill, k = cs.stroke;
4280
+ if (f) dst[i].setAttribute('fill', /url\(/.test(f) ? (src[i].getAttribute('fill') || 'none') : f);
4281
+ if (k && k !== 'none') {
4282
+ dst[i].setAttribute('stroke', k);
4283
+ if (cs.strokeWidth) dst[i].setAttribute('stroke-width', parseFloat(cs.strokeWidth));
4284
+ if (i > 0) strokes.push(k);
4285
+ }
4286
+ else if (i > 0 && k === 'none' && src[i].getAttribute('stroke')) dst[i].setAttribute('stroke', 'none');
4287
+ }
4288
+ dst[i].removeAttribute('class');
4289
+ dst[i].removeAttribute('style');
4290
+ }
4291
+ clone.setAttribute('width', round(r.width));
4292
+ clone.setAttribute('height', round(r.height));
4293
+ if (!clone.getAttribute('xmlns')) clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
4294
+ return { svg: clone.outerHTML.replace(/currentColor/gi, color), strokes: strokes };
4295
+ }
4296
+ // ::before / ::after drawn as a box (a switch knob, a checkbox's box, a radio's circle): a frame part with its box,
4297
+ // paint, border, radius and position. Text-only or empty pseudo-elements are not parts.
4298
+ function pseudoNode(el, which, hostRect) {
4299
+ var cs = getComputedStyle(el, '::' + which);
4300
+ var content = cs.content;
4301
+ if (!content || content === 'none' || content === 'normal' || cs.display === 'none' || cs.visibility === 'hidden') return null;
4302
+ var w = parseFloat(cs.width), h = parseFloat(cs.height);
4303
+ if (!(w > 0) || !(h > 0) || !/px$/.test(cs.width) || !/px$/.test(cs.height)) return null;
4304
+ var bg = cs.backgroundColor;
4305
+ var paints = (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') || (cs.backgroundImage && cs.backgroundImage !== 'none') || (cs.boxShadow && cs.boxShadow !== 'none');
4306
+ var bordered = ['Top', 'Right', 'Bottom', 'Left'].some(function (s) { return parseFloat(cs['border' + s + 'Width']) > 0 && cs['border' + s + 'Style'] !== 'none'; });
4307
+ if (!paints && !bordered) return null;
4308
+ // Border box: CSS width/height are content-box unless box-sizing says otherwise.
4309
+ if (cs.boxSizing !== 'border-box') {
4310
+ w += (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0) + (parseFloat(cs.borderLeftWidth) || 0) + (parseFloat(cs.borderRightWidth) || 0);
4311
+ h += (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0) + (parseFloat(cs.borderTopWidth) || 0) + (parseFloat(cs.borderBottomWidth) || 0);
4312
+ }
4313
+ var hcs = getComputedStyle(el);
4314
+ var padX = hostRect.left + (parseFloat(hcs.borderLeftWidth) || 0), padY = hostRect.top + (parseFloat(hcs.borderTopWidth) || 0);
4315
+ var padW = hostRect.width - (parseFloat(hcs.borderLeftWidth) || 0) - (parseFloat(hcs.borderRightWidth) || 0);
4316
+ var padH = hostRect.height - (parseFloat(hcs.borderTopWidth) || 0) - (parseFloat(hcs.borderBottomWidth) || 0);
4317
+ var x, y;
4318
+ if (cs.position === 'absolute' || cs.position === 'fixed') {
4319
+ x = /px$/.test(cs.left) ? padX + parseFloat(cs.left) : /px$/.test(cs.right) ? padX + padW - parseFloat(cs.right) - w : padX;
4320
+ y = /px$/.test(cs.top) ? padY + parseFloat(cs.top) : /px$/.test(cs.bottom) ? padY + padH - parseFloat(cs.bottom) - h : padY;
4321
+ } else {
4322
+ // In flow: before at the start of the content box, after at its end.
4323
+ var cx = padX + (parseFloat(hcs.paddingLeft) || 0), cy = padY + (parseFloat(hcs.paddingTop) || 0);
4324
+ x = which === 'before' ? cx : padX + padW - (parseFloat(hcs.paddingRight) || 0) - w;
4325
+ y = cy;
4326
+ }
4327
+ var m = /matrix\(([^)]+)\)/.exec(cs.transform || '');
4328
+ if (m) { var mv = m[1].split(',').map(parseFloat); x += mv[4] || 0; y += mv[5] || 0; }
4329
+ var style = {};
4330
+ for (var i = 0; i < PROPS.length; i++) style[PROPS[i]] = cs.getPropertyValue(PROPS[i]);
4331
+ style.width = round(w) + 'px';
4332
+ style.height = round(h) + 'px';
4333
+ var tokens = {};
4334
+ for (var j = 0; j < TOKENED.length; j++) {
4335
+ var p = TOKENED[j], v = style[p];
4336
+ if (!v || v === 'none' || v === 'normal' || v === 'auto' || v === 'rgba(0, 0, 0, 0)') continue;
4337
+ if (/width$/.test(p) && /^border-/.test(p) && v === '0px') continue;
4338
+ if (/^border-.*-color$/.test(p) && parseFloat(style[p.replace('color', 'width')]) === 0) continue;
4339
+ var t = tokenFor(el, p, v, which);
4340
+ if (t) tokens[p] = t;
4341
+ }
4342
+ count++;
4343
+ return { tag: '::' + which, kind: 'frame', pseudo: which, sized: { width: true, height: true }, classes: [], box: { x: round(x - originX), y: round(y - originY), width: round(w), height: round(h) }, style: style, tokens: tokens, children: [] };
4344
+ }
4345
+ var originX = 0, originY = 0;
4346
+ function node(el, depth) {
4347
+ count++;
4348
+ var cs = getComputedStyle(el);
4349
+ var r = el.getBoundingClientRect();
4350
+ var tag = el.tagName.toLowerCase();
4351
+ var style = {};
4352
+ for (var i = 0; i < PROPS.length; i++) style[PROPS[i]] = cs.getPropertyValue(PROPS[i]);
4353
+ var tokens = {};
4354
+ for (var j = 0; j < TOKENED.length; j++) {
4355
+ var p = TOKENED[j], v = style[p];
4356
+ if (!v || v === 'none' || v === 'normal' || v === 'auto' || v === 'rgba(0, 0, 0, 0)') continue;
4357
+ if (/width$/.test(p) && /^border-/.test(p) && v === '0px') continue;
4358
+ if (/^border-.*-color$/.test(p) && parseFloat(style[p.replace('color', 'width')]) === 0) continue;
4359
+ var t = tokenFor(el, p, v);
4360
+ if (t) tokens[p] = t;
4361
+ }
4362
+ // A width or height the CSS sets (not auto, a percentage or content-sized): the pull keeps it fixed.
4363
+ var sized = {};
4364
+ ['width', 'height'].forEach(function (k) {
4365
+ var dv = declared(el, k);
4366
+ var v = dv ? dv.value.trim() : (el.style && el.style.getPropertyValue(k)) || '';
4367
+ if (v && !/^(auto|inherit|initial|unset|revert|fit-content|max-content|min-content|stretch|-webkit-fill-available)/.test(v) && !/%/.test(v)) sized[k] = true;
4368
+ });
4369
+ var n = { tag: tag, classes: Array.prototype.slice.call(el.classList || []).slice(0, 8), box: { x: round(r.left - originX), y: round(r.top - originY), width: round(r.width), height: round(r.height) }, style: style, tokens: tokens, children: [] };
4370
+ var role = el.getAttribute('role');
4371
+ if (role) n.role = role;
4372
+ if (sized.width || sized.height) n.sized = sized;
4373
+ var dataState = {};
4374
+ for (var ai = 0; ai < el.attributes.length; ai++) {
4375
+ var an = el.attributes[ai].name;
4376
+ if (/^(data-(state|variant|size|disabled|checked|selected|tone|appearance)|aria-(checked|pressed|disabled|selected|invalid))$/.test(an)) dataState[an] = el.attributes[ai].value;
4377
+ }
4378
+ if (Object.keys(dataState).length) n.attrs = dataState;
4379
+ if (tag === 'svg') {
4380
+ n.kind = r.width <= 48 && r.height <= 48 ? 'icon' : 'vector';
4381
+ var mk = svgMarkup(el, r);
4382
+ if (mk) { n.svg = mk.svg; n.svgStrokes = mk.strokes; }
4383
+ return n;
4384
+ }
4385
+ if (tag === 'img') { n.kind = 'frame'; n.media = true; return n; }
4386
+ if (tag === 'input' || tag === 'textarea' || tag === 'select') {
4387
+ n.kind = 'frame';
4388
+ n.input = { type: el.type || tag, value: el.value || '', placeholder: el.getAttribute('placeholder') || '', checked: !!el.checked };
4389
+ }
4390
+ var hasEl = false;
4391
+ var before = pseudoNode(el, 'before', r), after = pseudoNode(el, 'after', r);
4392
+ if (before) { n.children.push(before); hasEl = true; }
4393
+ for (var c = el.firstChild; c; c = c.nextSibling) {
4394
+ if (count >= MAX_NODES) { n.truncated = true; break; }
4395
+ if (c.nodeType === 3) {
4396
+ var tx = c.nodeValue.replace(/\s+/g, ' ').trim();
4397
+ if (!tx) continue;
4398
+ var range = document.createRange();
4399
+ range.selectNodeContents(c);
4400
+ var tr = range.getBoundingClientRect();
4401
+ n.children.push({ tag: '#text', kind: 'text', text: tx, box: { x: round(tr.left - originX), y: round(tr.top - originY), width: round(tr.width), height: round(tr.height) }, style: {}, tokens: {}, children: [] });
4402
+ } else if (c.nodeType === 1) {
4403
+ var ccs = getComputedStyle(c);
4404
+ if (!visible(c, ccs)) continue;
4405
+ if (depth + 1 > MAX_DEPTH) { hasEl = true; n.truncated = true; continue; }
4406
+ var cn = node(c, depth + 1);
4407
+ // A box with no area and nothing drawn inside (a closed popover's shell) is not a layer.
4408
+ if (cn.kind === 'frame' && !cn.children.length && !(cn.box.width * cn.box.height) && !cn.input && !cn.media) continue;
4409
+ hasEl = true;
4410
+ n.children.push(cn);
4411
+ }
4412
+ }
4413
+ if (after) { n.children.push(after); hasEl = true; }
4414
+ // An element holding only text is the text layer itself.
4415
+ if (!hasEl && n.children.length === 1 && n.children[0].kind === 'text' && !own(el, cs)) {
4416
+ n.kind = 'text';
4417
+ n.text = n.children[0].text;
4418
+ n.children = [];
4419
+ } else if (!n.kind) n.kind = 'frame';
4420
+ return n;
4421
+ }
4422
+
4423
+ var host = document.querySelector(rootSel);
4424
+ if (!host) return { error: 'no element matches ' + rootSel + ' in the page' };
4425
+ // Popups portaled to the body (a menu, a dialog, a toast region): visible elements outside the story root.
4426
+ var portals = [];
4427
+ for (var b = document.body.firstElementChild; b; b = b.nextElementSibling) {
4428
+ if (b === probe || b.contains(host) || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(b.tagName)) continue;
4429
+ if (/sb-(wrapper|errordisplay|nopreview|preparing)|sb-show-main/.test(b.className || '')) continue;
4430
+ var bcs = getComputedStyle(b);
4431
+ if (!visible(b, bcs)) continue;
4432
+ // A portal container can be zero-size around its positioned popup: it counts when anything in it has a box.
4433
+ var br = b.getBoundingClientRect();
4434
+ if (br.width > 0 && br.height > 0) { portals.push(b); continue; }
4435
+ var inner = b.querySelectorAll('*');
4436
+ for (var q = 0; q < inner.length && q < 200; q++) { var ir = inner[q].getBoundingClientRect(); if (ir.width > 0 && ir.height > 0) { portals.push(b); break; } }
4437
+ }
4438
+ var storyRoot = host;
4439
+ // target 'portal': the component is the open popup (the newest portal), not the trigger in the story root.
4440
+ if (arg.target === 'portal') {
4441
+ if (!portals.length) { probe.remove(); return { error: 'no popup is open outside the story root' }; }
4442
+ host = portals[portals.length - 1];
4443
+ portals = portals.slice(0, -1);
4444
+ // A modal portal holds a backdrop beside the popup: the popup is the element with a popup role, when there is one.
4445
+ var roled = host.querySelector('[role="dialog"], [role="alertdialog"], [role="menu"], [role="listbox"], [role="tooltip"], [role="tree"], [role="grid"]');
4446
+ if (roled && visible(roled, getComputedStyle(roled))) host = roled;
4447
+ }
4448
+ // Decorators and plain wrappers: go down while an element has one child and draws nothing itself.
4449
+ var el = host, wrappers = 0;
4450
+ // A decorator canvas the size of the viewport (a theme frame with a background and padding) is a wrapper too.
4451
+ // So is a full-width band around one narrower child (a theme provider painting the page background).
4452
+ function canvas(e) {
4453
+ var r = e.getBoundingClientRect();
4454
+ if (r.width >= window.innerWidth * 0.9 && r.height >= window.innerHeight * 0.9) return true;
4455
+ if (r.width < window.innerWidth * 0.9) return false;
4456
+ var c = e.children[0].getBoundingClientRect();
4457
+ if (c.width < r.width * 0.9) return true;
4458
+ // A full-width background with no border, radius or shadow: a theme surface, not a component.
4459
+ var cs = getComputedStyle(e);
4460
+ var noBorder = ['Top', 'Right', 'Bottom', 'Left'].every(function (x) { return !(parseFloat(cs['border' + x + 'Width']) > 0) || cs['border' + x + 'Style'] === 'none'; });
4461
+ return noBorder && !(parseFloat(cs.borderTopLeftRadius) > 0) && (!cs.boxShadow || cs.boxShadow === 'none');
4462
+ }
4463
+ while (arg.unwrap !== false && el.children.length === 1 && !directText(el) && (!own(el, getComputedStyle(el)) || canvas(el)) && el.children[0].tagName.toLowerCase() !== 'svg') {
4464
+ var only = el.children[0];
4465
+ var ocs = getComputedStyle(only);
4466
+ if (!visible(only, ocs)) break;
4467
+ el = only;
4468
+ wrappers++;
4469
+ }
4470
+ // within: a part that only renders inside its parent or a popup (a menu item, an accordion item, a toast) is measured
4471
+ // alone: the first visible match in the component, then in the popups.
4472
+ if (arg.within) {
4473
+ var pool = [el].concat(portals), hit = null;
4474
+ for (var wi = 0; wi < pool.length && !hit; wi++) {
4475
+ var cands = [];
4476
+ try { if (pool[wi].matches(arg.within)) cands.push(pool[wi]); cands = cands.concat(Array.prototype.slice.call(pool[wi].querySelectorAll(arg.within))); } catch (e) { probe.remove(); return { error: 'not a CSS selector: ' + arg.within }; }
4477
+ for (var ci = 0; ci < cands.length && !hit; ci++) if (visible(cands[ci], getComputedStyle(cands[ci])) && cands[ci].getBoundingClientRect().width > 0) hit = cands[ci];
4478
+ }
4479
+ if (!hit) { probe.remove(); return { error: 'no element matches ' + arg.within + ' in the story or its popups' }; }
4480
+ portals = portals.filter(function (p) { return !p.contains(hit); });
4481
+ el = hit;
4482
+ }
4483
+ // mark: tag the component element (for a forced :hover / :focus-visible from the browser driver) and stop.
4484
+ if (arg.mark) {
4485
+ var prev = document.querySelectorAll('[data-bridge-measure-root]');
4486
+ for (var mi = 0; mi < prev.length; mi++) prev[mi].removeAttribute('data-bridge-measure-root');
4487
+ el.setAttribute('data-bridge-measure-root', '');
4488
+ probe.remove();
4489
+ return { marked: true };
4490
+ }
4491
+ scopeEl = el;
4492
+ var hr = el.getBoundingClientRect();
4493
+ // Fill or hug: a block-level root that spans its container's content box (or is declared width: 100%) fills it.
4494
+ var rootFill = false;
4495
+ (function () {
4496
+ var pe = el.parentElement;
4497
+ var ecs = getComputedStyle(el);
4498
+ var inner = window.innerWidth;
4499
+ if (pe) {
4500
+ var pcs = getComputedStyle(pe);
4501
+ inner = pe.getBoundingClientRect().width - (parseFloat(pcs.paddingLeft) || 0) - (parseFloat(pcs.paddingRight) || 0) - (parseFloat(pcs.borderLeftWidth) || 0) - (parseFloat(pcs.borderRightWidth) || 0);
4502
+ }
4503
+ var dw = declared(el, 'width');
4504
+ var full = (dw && /^100%$/.test(dw.value.trim())) || (el.style && el.style.width === '100%');
4505
+ var blockish = /^(block|flex|grid|table|list-item|flow-root)$/.test(ecs.display);
4506
+ rootFill = !!full || (inner > 0 && Math.abs(hr.width - inner) <= 1 && (blockish || hr.width >= window.innerWidth * 0.5));
4507
+ })();
4508
+ originX = hr.left; originY = hr.top;
4509
+ var tree = arg.unwrap !== false && el === storyRoot && !storyRoot.children.length && !directText(storyRoot) ? null : node(el, 0);
4510
+ var portalTrees = [];
4511
+ for (var pi = 0; pi < portals.length && pi < 3; pi++) portalTrees.push(node(portals[pi], 0));
4512
+ probe.remove();
4513
+ var rt = rootVars || { count: 0 };
4514
+ return {
4515
+ root: tree,
4516
+ portals: portalTrees,
4517
+ wrappers: wrappers,
4518
+ nodes: count,
4519
+ rules: rules.length,
4520
+ sheets: { read: sheetsRead, blocked: sheetsBlocked },
4521
+ rootFill: rootFill,
4522
+ rootVariables: rt.count,
4523
+ scopedVariables: rt.scoped || 0,
4524
+ viewport: { width: window.innerWidth, height: window.innerHeight },
4525
+ error: document.body.classList.contains('sb-show-errordisplay') ? (document.querySelector('#error-message') || {}).textContent || 'the story threw' : undefined
4526
+ };
4527
+ })`;
4528
+ const TOKENS_SCRIPT = String.raw`(function (arg) {
4529
+ arg = arg || {};
4530
+ var rootSel = arg.root || '#storybook-root, #root';
4531
+ var host = document.querySelector(rootSel) || document.body;
4532
+ var at = host.firstElementChild || host;
4533
+ var decls = {};
4534
+ var order = 0;
4535
+ // Every var() use: the color function around it (rgb, hsl...), or a bare use; and the properties that alias it.
4536
+ var COLOR_FN = /^(rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)$/i;
4537
+ var useFn = {}, useBare = {}, aliasUses = {};
4538
+ function enclosing(s, pos) {
4539
+ for (var i = pos - 1, depth = 0; i >= 0; i--) {
4540
+ if (s[i] === ')') depth++;
4541
+ else if (s[i] === '(') {
4542
+ if (depth) { depth--; continue; }
4543
+ var j = i;
4544
+ while (j > 0 && /[\w-]/.test(s[j - 1])) j--;
4545
+ var fn = s.slice(j, i).toLowerCase();
4546
+ // A fallback (var(--a, var(--b))): the function around the outer var.
4547
+ if (fn !== 'var') return fn;
4548
+ }
4549
+ }
4550
+ return '';
4551
+ }
4552
+ function scanDecl(d) {
4553
+ var c = d.indexOf(':');
4554
+ if (c < 0) return;
4555
+ var prop = d.slice(0, c).trim(), val = d.slice(c + 1).replace(/!important\s*$/, '').trim();
4556
+ var alias = /^var\(\s*(--[\w-]+)\s*\)$/.exec(val);
4557
+ if (alias && prop.indexOf('--') === 0) { (aliasUses[alias[1]] = aliasUses[alias[1]] || []).push(prop); return; }
4558
+ var re = /var\(\s*(--[\w-]+)/g, m;
4559
+ while ((m = re.exec(val))) {
4560
+ var fn = enclosing(val, m.index);
4561
+ if (COLOR_FN.test(fn)) (useFn[m[1]] = useFn[m[1]] || {})[fn === 'rgba' || fn === 'hsla' ? fn.slice(0, 3) : fn] = 1;
4562
+ else useBare[m[1]] = 1;
4563
+ }
4564
+ }
4565
+ function scanUses(text) {
4566
+ for (var i = 0, depth = 0, start = 0; i <= text.length; i++) {
4567
+ var ch = text[i];
4568
+ if (ch === '(') depth++;
4569
+ else if (ch === ')') depth--;
4570
+ else if (i === text.length || (ch === ';' && depth <= 0)) { scanDecl(text.slice(start, i)); start = i + 1; depth = 0; }
4571
+ }
4572
+ }
4573
+ // The one color function every use of a property wraps it in, through the properties that alias it: '' unused, null
4574
+ // when a use is bare or two functions disagree.
4575
+ function channelFn(name, seen) {
4576
+ if (seen[name]) return '';
4577
+ seen[name] = 1;
4578
+ if (useBare[name]) return null;
4579
+ var fns = {};
4580
+ for (var f in useFn[name] || {}) fns[f] = 1;
4581
+ var al = aliasUses[name] || [];
4582
+ for (var i = 0; i < al.length; i++) {
4583
+ var g = channelFn(al[i], seen);
4584
+ if (g === null) return null;
4585
+ if (g) fns[g] = 1;
4586
+ }
4587
+ var k = Object.keys(fns);
4588
+ return k.length === 1 ? k[0] : k.length ? null : '';
4589
+ }
4590
+ function add(sel, style) {
4591
+ try { scanUses(style.cssText || ''); } catch (e) {}
4592
+ for (var k = 0; k < style.length; k++) {
4593
+ var n = style[k];
4594
+ if (n.indexOf('--') !== 0 || n.indexOf('--_') === 0 || n.indexOf('--sb-') === 0) continue;
4595
+ (decls[n] = decls[n] || []).push({ sel: sel, raw: style.getPropertyValue(n).trim(), order: order++ });
4596
+ }
4597
+ }
4598
+ function walk(list) {
4599
+ for (var i = 0; i < list.length; i++) {
4600
+ var r = list[i];
4601
+ try {
4602
+ if (r.selectorText !== undefined && r.style) {
4603
+ add(r.selectorText, r.style);
4604
+ if (r.cssRules && r.cssRules.length) walk(r.cssRules);
4605
+ } else if (r.media !== undefined && r.cssRules) {
4606
+ if (window.matchMedia(r.media.mediaText || 'all').matches) walk(r.cssRules);
4607
+ } else if (r.cssRules) walk(r.cssRules);
4608
+ } catch (e) {}
4609
+ }
4610
+ }
4611
+ var blocked = 0;
4612
+ for (var s = 0; s < document.styleSheets.length; s++) {
4613
+ try { walk(document.styleSheets[s].cssRules); } catch (e) { blocked++; }
4614
+ }
4615
+ try { for (var a = 0; a < (document.adoptedStyleSheets || []).length; a++) walk(document.adoptedStyleSheets[a].cssRules); } catch (e) {}
4616
+ // Inline styles on the story's ancestors (a provider that sets variables in style="").
4617
+ for (var up = at; up && up.nodeType === 1; up = up.parentElement) if (up.style && up.style.length) add('[style]', up.style);
4618
+ // Inline styles in the story use variables too.
4619
+ var inline = host.querySelectorAll('[style]');
4620
+ for (var q = 0; q < inline.length; q++) try { scanUses(inline[q].style.cssText || ''); } catch (e) {}
4621
+
4622
+ function specificity(sel) {
4623
+ var x = sel.replace(/:where\([^)]*\)/g, '');
4624
+ var ids = (x.match(/#[\w-]+/g) || []).length;
4625
+ var cls = (x.match(/\.[\w-]+|\[[^\]]*\]|:(?!not\b|is\b|has\b|root\b)[\w-]+(\([^)]*\))?/g) || []).length + (x.match(/:root/g) || []).length;
4626
+ var types = (x.replace(/\[[^\]]*\]|\([^)]*\)/g, '').match(/(^|[\s>+~(])[a-zA-Z][\w-]*/g) || []).length;
4627
+ return ids * 10000 + cls * 100 + types;
4628
+ }
4629
+ function matchSpec(el, selText) {
4630
+ var best = -1, parts = selText.split(/,(?![^(]*\))/);
4631
+ for (var i = 0; i < parts.length; i++) {
4632
+ var p = parts[i].trim();
4633
+ if (!p || /::/.test(p)) continue;
4634
+ try { if (el.matches(p)) best = Math.max(best, specificity(p)); } catch (e) {}
4635
+ }
4636
+ return best;
4637
+ }
4638
+ // The declaration that applies at the story: the nearest element up from it with a matching rule, then specificity
4639
+ // and order; inline style wins at its element.
4640
+ function winning(name) {
4641
+ var list = decls[name];
4642
+ for (var el = at; el && el.nodeType === 1; el = el.parentElement) {
4643
+ var best = null, bestRank = null;
4644
+ if (el.style && el.style.getPropertyValue(name)) return { sel: '[style]', raw: el.style.getPropertyValue(name).trim() };
4645
+ for (var i = 0; i < list.length; i++) {
4646
+ if (list[i].sel === '[style]') continue;
4647
+ var sp = matchSpec(el, list[i].sel);
4648
+ if (sp < 0) continue;
4649
+ if (!best || sp > bestRank[0] || (sp === bestRank[0] && list[i].order > bestRank[1])) { best = list[i]; bestRank = [sp, list[i].order]; }
4650
+ }
4651
+ if (best) return best;
4652
+ }
4653
+ return null;
4654
+ }
4655
+
4656
+ var probe = document.createElement('div');
4657
+ probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none;width:0;height:0';
4658
+ (at.parentElement || document.body).appendChild(probe);
4659
+ function norm(v) {
4660
+ if (!v) return { type: 'string', value: '' };
4661
+ probe.style.color = '';
4662
+ probe.style.color = v;
4663
+ if (probe.style.color) return { type: 'color', value: getComputedStyle(probe).color };
4664
+ if (/^-?[\d.]+$/.test(v)) return { type: 'number', value: Number(v) };
4665
+ probe.style.width = '';
4666
+ probe.style.width = v;
4667
+ if (probe.style.width && !/auto|%/.test(v)) {
4668
+ var w = getComputedStyle(probe).width;
4669
+ if (/px$/.test(w)) return { type: 'length', value: Math.round(parseFloat(w) * 100) / 100 };
4670
+ }
4671
+ return { type: 'string', value: v };
4672
+ }
4673
+ var cs = getComputedStyle(at), rootCs = getComputedStyle(document.documentElement);
4674
+ var out = [];
4675
+ var ROOTISH = /^(:root|html|:host|body|\*)(\s*,\s*(:root|html|:host|body|\*))*$/;
4676
+ for (var name in decls) {
4677
+ var w = winning(name);
4678
+ var resolved = cs.getPropertyValue(name).trim() || rootCs.getPropertyValue(name).trim();
4679
+ var r = norm(resolved);
4680
+ var fn = r.type === 'string' && resolved ? channelFn(name, {}) : '';
4681
+ if (fn) {
4682
+ probe.style.color = '';
4683
+ probe.style.color = fn + '(' + resolved + ')';
4684
+ if (probe.style.color) r = { type: 'color', value: getComputedStyle(probe).color };
4685
+ }
4686
+ var scopes = [];
4687
+ for (var j = 0; j < decls[name].length && scopes.length < 6; j++) {
4688
+ var sel = decls[name][j].sel;
4689
+ if (!ROOTISH.test(sel.trim()) && scopes.indexOf(sel) < 0) scopes.push(sel.length > 120 ? sel.slice(0, 120) : sel);
4690
+ }
4691
+ out.push({ name: name, raw: w ? w.raw : decls[name][0].raw, applies: !!w, type: r.type, value: r.value, scopes: scopes });
4692
+ }
4693
+ probe.remove();
4694
+ return { properties: out, blocked: blocked };
4695
+ })`;
4696
+ const GLOBALS_SCRIPT = String.raw`(function () {
4697
+ var p = window.__STORYBOOK_PREVIEW__;
4698
+ if (!p) return null;
4699
+ var store = p.storyStoreValue || {};
4700
+ var ann = store.projectAnnotations || p.projectAnnotations || {};
4701
+ var types = ann.globalTypes || (store.globals && store.globals.globalTypes) || {};
4702
+ var current = (store.userGlobals && store.userGlobals.get && store.userGlobals.get()) || (store.globals && store.globals.get && store.globals.get()) || ann.initialGlobals || ann.globals || {};
4703
+ var out = [];
4704
+ for (var k in types) {
4705
+ var t = types[k] || {};
4706
+ var items = (t.toolbar && t.toolbar.items) || t.options || [];
4707
+ var values = [];
4708
+ for (var i = 0; i < items.length; i++) {
4709
+ var it = items[i];
4710
+ var v = typeof it === 'string' ? it : it && (it.value !== undefined ? it.value : it.title);
4711
+ if (typeof v === 'string' && v && values.indexOf(v) < 0) values.push(v);
4712
+ }
4713
+ if (values.length < 2 || values.length > 12) continue;
4714
+ var def = current[k] !== undefined ? String(current[k]) : (t.defaultValue !== undefined ? String(t.defaultValue) : values[0]);
4715
+ out.push({ global: k, values: values, default: def });
4716
+ }
4717
+ return out;
4718
+ })()`;
4719
+ async function markMeasuredRoot(page, o = {}) {
4720
+ const arg = { root: o.root ?? "#storybook-root, #root", unwrap: o.unwrap, within: o.within, target: o.target ?? (o.open && !o.within ? "portal" : void 0), mark: true };
4721
+ const r = await page.evaluate(`(${MEASURE_SCRIPT})(${JSON.stringify(arg)})`).catch(() => null);
4722
+ return !!r?.marked;
4723
+ }
4724
+ const WAIT_SCRIPT = (rootSel, timeout, self = false) => `(async () => {
4725
+ const t0 = performance.now();
4726
+ const frame = () => new Promise((r) => requestAnimationFrame(() => r(null)));
4727
+ const host = () => document.querySelector(${JSON.stringify(rootSel)});
4728
+ let state = 'timeout';
4729
+ while (performance.now() - t0 < ${timeout}) {
4730
+ if (document.body && document.body.classList.contains('sb-show-errordisplay')) { state = 'error'; break; }
4731
+ const h = host();
4732
+ if (h && (${self} || h.children.length || (h.textContent || '').trim())) { state = 'rendered'; break; }
4733
+ await new Promise((r) => setTimeout(r, 50));
4734
+ }
4735
+ try { await Promise.race([document.fonts.ready, new Promise((r) => setTimeout(r, 3000))]); } catch (e) {}
4736
+ // Settle briefly: the markup stops changing for a few frames, or 1.5 s passes (a spinner never stops).
4737
+ let last = '', same = 0;
4738
+ const settle0 = performance.now();
4739
+ while (state === 'rendered' && same < 3 && performance.now() - settle0 < 1500) {
4740
+ await frame();
4741
+ await new Promise((r) => setTimeout(r, 60));
4742
+ const s = document.body.innerHTML.length + ':' + document.querySelectorAll('*').length;
4743
+ same = s === last ? same + 1 : 0;
4744
+ last = s;
4745
+ }
4746
+ // Animations: finished ones jump to their end, endless ones (a loading spinner) are paused where they are.
4747
+ try { (document.getAnimations ? document.getAnimations() : []).forEach((a) => { try { a.finish(); } catch (e) { a.pause(); } }); } catch (e) {}
4748
+ return state;
4749
+ })()`;
4750
+ const OPEN_SCRIPT = (rootSel) => `(async () => {
4751
+ const root = document.querySelector(${JSON.stringify(rootSel)});
4752
+ if (!root) return 'none';
4753
+ const shown = () => Array.prototype.filter.call(document.body.children, (b) => {
4754
+ if (b.contains(root) || /^(SCRIPT|STYLE|LINK|TEMPLATE)$/.test(b.tagName) || /sb-/.test(String(b.className || ''))) return false;
4755
+ const cs = getComputedStyle(b), r = b.getBoundingClientRect();
4756
+ if (cs.display === 'none' || cs.visibility === 'hidden') return false;
4757
+ return r.width > 0 && r.height > 0 || Array.prototype.some.call(b.querySelectorAll('*'), (c) => { const x = c.getBoundingClientRect(); return x.width > 0 && x.height > 0; });
4758
+ }).length;
4759
+ const settle = async () => {
4760
+ for (let i = 0; i < 20; i++) {
4761
+ await new Promise((r) => setTimeout(r, 50));
4762
+ const running = (document.getAnimations ? document.getAnimations() : []).filter((a) => a.playState === 'running');
4763
+ if (!running.length) break;
4764
+ await Promise.race([Promise.all(running.map((a) => a.finished.catch(() => null))), new Promise((r) => setTimeout(r, 1500))]);
4765
+ }
4766
+ };
4767
+ if (shown()) { await settle(); return 'already'; }
4768
+ const trigger = root.querySelector('[aria-haspopup]:not([aria-expanded="true"]), [aria-expanded="false"]') || root.querySelector('button, [role="button"], [role="combobox"], a[href], [tabindex="0"]');
4769
+ if (!trigger) return 'none';
4770
+ const wait = async (ms) => { const t0 = performance.now(); while (performance.now() - t0 < ms) { if (shown()) { await settle(); return true; } await new Promise((r) => setTimeout(r, 50)); } return false; };
4771
+ const r = trigger.getBoundingClientRect();
4772
+ const at = { bubbles: true, cancelable: true, composed: true, clientX: r.left + r.width / 2, clientY: r.top + r.height / 2, button: 0, pointerId: 1, pointerType: 'mouse', isPrimary: true };
4773
+ const fire = (type, Ctor) => trigger.dispatchEvent(new Ctor(type, type === 'pointerdown' || type === 'mousedown' ? { ...at, buttons: 1 } : at));
4774
+ fire('pointerdown', PointerEvent); fire('mousedown', MouseEvent); fire('pointerup', PointerEvent); fire('mouseup', MouseEvent); fire('click', MouseEvent);
4775
+ if (await wait(800)) return 'click';
4776
+ fire('pointerover', PointerEvent); fire('pointerenter', PointerEvent); fire('mouseover', MouseEvent); fire('mouseenter', MouseEvent); fire('pointermove', PointerEvent); fire('mousemove', MouseEvent);
4777
+ if (await wait(1200)) return 'hover';
4778
+ try { trigger.focus(); } catch (e) {}
4779
+ if (await wait(800)) return 'focus';
4780
+ return 'none';
4781
+ })()`;
4782
+ const PROPS_SCRIPT = (id) => `(async () => {
4783
+ const p = window.__STORYBOOK_PREVIEW__;
4784
+ if (!p) return null;
4785
+ const want = ${JSON.stringify(id ?? null)};
4786
+ let story = p.currentRender && p.currentRender.story;
4787
+ if (want && (!story || story.id !== want)) { try { story = await p.storyStoreValue.loadStory({ storyId: want }); } catch (e) { story = story || null; } }
4788
+ if (!story) return null;
4789
+ const plain = (v) => ['string', 'number', 'boolean'].includes(typeof v);
4790
+ const clean = (o) => { const out = {}; for (const k in o || {}) if (plain(o[k])) out[k] = o[k]; return out; };
4791
+ let live;
4792
+ try { live = p.storyStoreValue && p.storyStoreValue.args && p.storyStoreValue.args.get(story.id); } catch (e) {}
4793
+ const args = clean(live || story.initialArgs);
4794
+ const lit = (v) => {
4795
+ if (v === undefined || v === null) return undefined;
4796
+ if (typeof v !== 'string') return plain(v) ? v : undefined;
4797
+ const t = v.trim();
4798
+ if (t === 'true' || t === 'false') return t === 'true';
4799
+ if (/^-?\\d+(\\.\\d+)?$/.test(t)) return Number(t);
4800
+ const q = /^(['"\`])(.*)\\1$/.exec(t);
4801
+ return q ? q[2] : undefined;
4802
+ };
4803
+ const argTypes = {}, defaults = {};
4804
+ for (const name in story.argTypes || {}) {
4805
+ const a = story.argTypes[name] || {};
4806
+ if (a.table && a.table.disable) continue;
4807
+ const t = a.type || {};
4808
+ const tn = typeof t === 'string' ? t : t.name;
4809
+ let options = Array.isArray(a.options) ? a.options : tn === 'enum' && Array.isArray(t.value) ? t.value : undefined;
4810
+ if (!options && tn === 'union' && Array.isArray(t.value) && t.value.every((x) => x && x.name === 'literal')) options = t.value.map((x) => x.value);
4811
+ if (options) options = options.filter(plain).map((x) => String(x).replace(/^(['"])(.*)\\1$/, '$2'));
4812
+ const control = a.control && typeof a.control === 'object' ? a.control.type : typeof a.control === 'string' ? a.control : undefined;
4813
+ const kind = options && options.length ? 'enum' : tn === 'boolean' || control === 'boolean' ? 'boolean' : tn === 'string' || control === 'text' ? 'text' : tn === 'number' || control === 'number' || control === 'range' ? 'number' : 'other';
4814
+ const d = lit(a.defaultValue !== undefined ? a.defaultValue : a.table && a.table.defaultValue && a.table.defaultValue.summary);
4815
+ argTypes[name] = { kind };
4816
+ if (options && options.length) argTypes[name].options = options;
4817
+ if (d !== undefined) { argTypes[name].default = d; defaults[name] = d; }
4818
+ if (control) argTypes[name].control = control;
4819
+ }
4820
+ const c = story.component;
4821
+ const component = c && (c.displayName || c.name) || undefined;
4822
+ return { props: Object.assign({}, defaults, args), args, argTypes, component };
4823
+ })()`;
4824
+ async function resolveTokenValues(page, vars) {
4825
+ const expr = `(() => {
4826
+ const vars = ${JSON.stringify(vars)};
4827
+ const el = document.querySelector('[data-bridge-measure-root]') || document.querySelector('#storybook-root > *, #root > *') || document.documentElement;
4828
+ const cs = getComputedStyle(el);
4829
+ const probe = document.createElement('div');
4830
+ probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none';
4831
+ (el.parentElement || document.body).appendChild(probe);
4832
+ const out = {};
4833
+ for (const path in vars) {
4834
+ const raw = cs.getPropertyValue(vars[path]).trim();
4835
+ if (!raw) continue;
4836
+ probe.style.color = ''; probe.style.width = '';
4837
+ probe.style.color = raw;
4838
+ if (probe.style.color) { out[path] = getComputedStyle(probe).color; continue; }
4839
+ probe.style.width = raw;
4840
+ out[path] = probe.style.width ? getComputedStyle(probe).width : raw;
4841
+ }
4842
+ probe.remove();
4843
+ return out;
4844
+ })()`;
4845
+ return await page.evaluate(expr) ?? {};
4846
+ }
4847
+ const STATE_TARGETS = "[data-bridge-measure-root], [data-bridge-measure-root] *";
4848
+ const PSEUDO_CLASSES = { hover: ["hover"], "focus-visible": ["focus-visible", "focus"], active: ["active", "hover"] };
4849
+ const MODE_GLOBAL = /theme|scheme|mode|brand|density|appearance/i;
4850
+ const ALIAS = /^var\(\s*(--[\w-]+)\s*(?:,[^)]*)?\)$/;
4851
+ async function harvestTokens(page, storybook, story, o = {}) {
4852
+ const timeout = o.timeout ?? 15e3;
4853
+ const read = async (globals) => {
4854
+ const iframe = { ...o.iframe ?? {}, globals: { ...o.iframe?.globals ?? {}, ...globals } };
4855
+ await page.goto(storybookIframeUrl(storybook, story, iframe), { waitUntil: "domcontentloaded", timeout: timeout + 15e3 });
4856
+ await page.evaluate(WAIT_SCRIPT("#storybook-root, #root", timeout));
4857
+ const r = await page.evaluate(`(${TOKENS_SCRIPT})({})`);
4858
+ return withSrgbColors(r?.properties ?? []);
4859
+ };
4860
+ const base = await read({});
4861
+ let moved = false;
4862
+ const readWithAttribute = async (attr, value) => {
4863
+ if (moved) {
4864
+ await read({});
4865
+ moved = false;
4866
+ }
4867
+ await page.evaluate(`(async () => { const els = document.querySelectorAll('[${attr}]'); (els.length ? Array.from(els) : [document.documentElement]).forEach((e) => e.setAttribute('${attr}', ${JSON.stringify(value)})); await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); })()`);
4868
+ const r = await page.evaluate(`(${TOKENS_SCRIPT})({})`);
4869
+ return withSrgbColors(r?.properties ?? []);
4870
+ };
4871
+ const found = o.modes === false ? [] : await page.evaluate(GLOBALS_SCRIPT).catch(() => null) ?? [];
4872
+ const modes = found.filter((m) => MODE_GLOBAL.test(m.global)).map((m) => ({ ...m, values: [m.default, ...m.values.filter((v) => v !== m.default)].filter((v) => !/^(all|side-?by-?side|stacked|both|none)$/i.test(v)) })).filter((m) => m.values.length >= 2);
4873
+ if (o.modes !== false && !modes.some((m) => /theme|scheme|mode/i.test(m.global))) {
4874
+ const attrs = /* @__PURE__ */ new Map();
4875
+ for (const p of base)
4876
+ for (const sel of p.scopes)
4877
+ for (const part of sel.split(","))
4878
+ for (const m of part.trim().matchAll(/^(?::root|html|body)?\[([\w-]+)=["']?([\w-]+)["']?\]$/g)) {
4879
+ const vals = attrs.get(m[1]) ?? /* @__PURE__ */ new Map();
4880
+ vals.set(m[2], (vals.get(m[2]) ?? 0) + 1);
4881
+ attrs.set(m[1], vals);
4882
+ }
4883
+ for (const [attr, vals] of attrs) {
4884
+ const values = [...vals.entries()].filter(([, n]) => n >= 10).map(([v]) => v);
4885
+ if (values.length < 2 || values.length > 12 || !MODE_GLOBAL.test(attr)) continue;
4886
+ const current = await page.evaluate(`(() => { const e = document.querySelector('[${attr}]'); return e && e.getAttribute('${attr}'); })()`).catch(() => null);
4887
+ const def = current ?? values[0];
4888
+ modes.push({ global: attr, attribute: true, values: [def, ...values.filter((v) => v !== def)], default: def });
4889
+ }
4890
+ }
4891
+ const prefix = sharedTokenPrefix(base.map((p) => p.name));
4892
+ const props = base.map((p) => {
4893
+ const alias = ALIAS.exec(p.raw)?.[1];
4894
+ const kind = alias ? "alias" : /var\(/.test(p.raw) ? "expression" : "literal";
4895
+ return {
4896
+ name: p.name,
4897
+ path: tokenVariablePath(p.name, prefix),
4898
+ tier: alias ? "semantic" : "primitive",
4899
+ kind,
4900
+ type: p.type,
4901
+ raw: p.raw,
4902
+ ...alias ? { aliasOf: alias } : {},
4903
+ value: p.value,
4904
+ ...p.scopes.length ? { scopes: p.scopes } : {}
4905
+ };
4906
+ });
4907
+ const byName = new Map(props.map((p) => [p.name, p]));
4908
+ for (const m of modes) {
4909
+ for (const value of m.values) {
4910
+ const key = `${m.global}:${value}`;
4911
+ const rows = value === m.default ? base : m.attribute ? await readWithAttribute(m.global, value) : (moved = true, await read({ [m.global]: value }));
4912
+ for (const r of rows) {
4913
+ const p = byName.get(r.name);
4914
+ if (!p) continue;
4915
+ (p.values ??= {})[key] = r.value;
4916
+ const alias = ALIAS.exec(r.raw)?.[1];
4917
+ if (p.tier === "semantic" && alias && alias !== p.aliasOf) (p.aliasOfByMode ??= {})[key] = alias;
4918
+ }
4919
+ }
4920
+ }
4921
+ for (const p of props) {
4922
+ for (const m of modes) {
4923
+ const keys = m.values.map((v) => `${m.global}:${v}`);
4924
+ if (new Set(keys.map((k) => JSON.stringify(p.values?.[k]))).size <= 1) for (const k of keys) delete p.values?.[k];
4925
+ }
4926
+ if (p.values && !Object.keys(p.values).length) delete p.values;
4927
+ }
4928
+ const live = modes.filter((m) => props.some((p) => p.values && `${m.global}:${m.default}` in p.values));
4929
+ if (live.length !== modes.length) {
4930
+ const dead = new Set(modes.filter((m) => !live.includes(m)).map((m) => m.global));
4931
+ for (const p of props) {
4932
+ for (const k of Object.keys(p.values ?? {})) if (dead.has(k.split(":")[0])) delete p.values[k];
4933
+ for (const k of Object.keys(p.aliasOfByMode ?? {})) if (dead.has(k.split(":")[0])) delete p.aliasOfByMode[k];
4934
+ if (p.values && !Object.keys(p.values).length) delete p.values;
4935
+ if (p.aliasOfByMode && !Object.keys(p.aliasOfByMode).length) delete p.aliasOfByMode;
4936
+ }
4937
+ }
4938
+ const keyOf = (p, v) => `${p.type}:${v}`;
4939
+ const primitiveFor = /* @__PURE__ */ new Map();
4940
+ for (const p of [...props].sort((a, b) => a.name.length - b.name.length || a.name.localeCompare(b.name)))
4941
+ if (p.kind === "literal" && !p.values && (p.type === "color" || p.type === "length") && !primitiveFor.has(keyOf(p, p.value))) primitiveFor.set(keyOf(p, p.value), p.name);
4942
+ let inferred = 0;
4943
+ for (const p of props) {
4944
+ if (p.kind !== "literal" || !p.values) continue;
4945
+ const def = primitiveFor.get(keyOf(p, p.value));
4946
+ const byMode = Object.entries(p.values).map(([k, v]) => [k, primitiveFor.get(keyOf(p, v))]);
4947
+ if (!def || def === p.name || byMode.some(([, n]) => !n)) continue;
4948
+ p.tier = "semantic";
4949
+ p.kind = "alias";
4950
+ p.aliasOf = def;
4951
+ p.inferred = true;
4952
+ const changes = byMode.filter(([, n]) => n !== def);
4953
+ if (changes.length) p.aliasOfByMode = Object.fromEntries(byMode);
4954
+ inferred++;
4955
+ }
4956
+ return {
4957
+ story,
4958
+ ...prefix ? { prefix } : {},
4959
+ modes: live,
4960
+ properties: props,
4961
+ counts: {
4962
+ properties: props.length,
4963
+ primitives: props.filter((p) => p.tier === "primitive").length,
4964
+ semantic: props.filter((p) => p.tier === "semantic").length,
4965
+ used: 0,
4966
+ scoped: props.filter((p) => p.scopes?.length).length,
4967
+ inferred
4968
+ }
4969
+ };
4970
+ }
4971
+ const APPLY_ARGS_SCRIPT = (id, args, timeout) => `(async () => {
4972
+ const want = ${JSON.stringify(args)};
4973
+ const t0 = performance.now();
4974
+ let p = window.__STORYBOOK_PREVIEW__;
4975
+ while ((!p || !p.currentRender || !p.storyStoreValue) && performance.now() - t0 < ${timeout}) { await new Promise((r) => setTimeout(r, 50)); p = window.__STORYBOOK_PREVIEW__; }
4976
+ if (!p || !p.storyStoreValue) return 'failed';
4977
+ const id = ${JSON.stringify(id)};
4978
+ const held = () => { let a = {}; try { a = p.storyStoreValue.args.get(id) || {}; } catch (e) {} return Object.keys(want).every((k) => a[k] === want[k]); };
4979
+ // Let the first render finish (an update sent during it is lost), then check again.
4980
+ const root = () => document.querySelector('#storybook-root, #root');
4981
+ while (performance.now() - t0 < ${timeout} && !(root() && (root().children.length || (root().textContent || '').trim()))) await new Promise((r) => setTimeout(r, 50));
4982
+ await new Promise((r) => setTimeout(r, 100));
4983
+ if (held()) return 'url';
4984
+ const ch = window.__STORYBOOK_ADDONS_CHANNEL__;
4985
+ if (!ch) return 'failed';
4986
+ const done = await new Promise((resolve) => {
4987
+ const t = setTimeout(() => finish(false), 5000);
4988
+ const ok = () => finish(true);
4989
+ const bad = () => finish(false);
4990
+ function finish(v) { clearTimeout(t); ch.off('storyRendered', ok); ch.off('storyErrored', bad); ch.off('storyThrewException', bad); resolve(v); }
4991
+ ch.on('storyRendered', ok); ch.on('storyErrored', bad); ch.on('storyThrewException', bad);
4992
+ ch.emit('updateStoryArgs', { storyId: id, updatedArgs: want });
4993
+ });
4994
+ return done && held() ? 'channel' : 'failed';
4995
+ })()`;
4996
+ async function measureStory(page, storybook, id, o = {}) {
4997
+ const iframe = { ...o.iframe ?? {} };
4998
+ if (o.args && Object.keys(o.args).length) iframe.args = { ...iframe.args ?? {}, ...Object.fromEntries(Object.entries(o.args).map(([k, v]) => [k, typeof v === "boolean" ? `!${v}` : String(v)])) };
4999
+ const url = storybookIframeUrl(storybook, id, iframe);
5000
+ const t0 = Date.now();
5001
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: (o.timeout ?? 15e3) + 15e3 });
5002
+ if (o.args && Object.keys(o.args).length) await page.evaluate(APPLY_ARGS_SCRIPT(id, o.args, o.timeout ?? 15e3)).catch(() => "failed");
5003
+ const m = await measureRendered(page, o);
5004
+ let props = null;
5005
+ if (o.props !== false && m.root) props = await page.evaluate(PROPS_SCRIPT(id)).catch(() => null);
5006
+ return { id, url, ...m, ...props && typeof props === "object" ? { props } : {}, ms: Date.now() - t0 };
5007
+ }
5008
+ async function measureRendered(page, o = {}) {
5009
+ const t0 = Date.now();
5010
+ const root = o.root ?? "#storybook-root, #root";
5011
+ const timeout = o.timeout ?? 15e3;
5012
+ const rendered = await page.evaluate(WAIT_SCRIPT(root, timeout, o.unwrap === false));
5013
+ let opened;
5014
+ if (o.open && rendered === "rendered") opened = await page.evaluate(OPEN_SCRIPT(root));
5015
+ const target = o.target ?? (o.open && !o.within ? "portal" : void 0);
5016
+ const arg = { root, maxNodes: o.maxNodes, maxDepth: o.maxDepth, unwrap: o.unwrap, target, within: o.within };
5017
+ let state;
5018
+ if (o.state && page.forcePseudo && rendered === "rendered") {
5019
+ const marked = await page.evaluate(`(${MEASURE_SCRIPT})(${JSON.stringify({ ...arg, mark: true })})`);
5020
+ if (marked?.marked && await page.forcePseudo(STATE_TARGETS, PSEUDO_CLASSES[o.state]).catch(() => false)) {
5021
+ state = o.state;
5022
+ await page.evaluate("new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => setTimeout(r, 120))))");
5023
+ }
5024
+ }
5025
+ const r = await page.evaluate(`(${MEASURE_SCRIPT})(${JSON.stringify(arg)})`);
5026
+ let base = "root" in r ? r : { root: null, portals: [], wrappers: 0, nodes: 0, rules: 0, sheets: { read: 0, blocked: 0 }, rootVariables: 0, viewport: { width: 0, height: 0 }, error: r.error };
5027
+ const fillWidth = o.fillWidth ?? 400;
5028
+ if (fillWidth && base.root && base.rootFill && base.root.box.width > fillWidth + 1 && (state || await markMeasuredRoot(page, { ...o, root }))) {
5029
+ await page.evaluate(`(async () => { const e = document.querySelector('[data-bridge-measure-root]'); if (e) { e.style.width = '${fillWidth}px'; e.style.maxWidth = 'none'; e.style.minWidth = '0'; } await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); })()`);
5030
+ const again = await page.evaluate(`(${MEASURE_SCRIPT})(${JSON.stringify(arg)})`);
5031
+ if ("root" in again && again.root) base = { ...again, rootFill: true, fillWidth };
5032
+ }
5033
+ if (opened) base.opened = opened;
5034
+ if (opened === "none" && !base.root) base.error = "the popup did not open: no trigger in the story opened it";
5035
+ if (rendered === "timeout" && !base.error && !base.root) base.error = `the story did not render within ${timeout} ms`;
5036
+ if (rendered === "error" && !base.error) base.error = "the story threw";
5037
+ let shot;
5038
+ if (o.shot && page.screenshot && base.root) {
5039
+ if (state || await markMeasuredRoot(page, { ...o, root })) {
5040
+ const size = await page.screenshot("[data-bridge-measure-root]", o.shot).catch(() => null);
5041
+ if (size) shot = { file: o.shot, ...size };
5042
+ }
5043
+ }
5044
+ if (state) await page.forcePseudo?.(STATE_TARGETS, []).catch(() => false);
5045
+ return { ...withSrgbColors(base), ...state ? { state } : {}, ...shot ? { shot } : {}, ms: Date.now() - t0 };
5046
+ }
5047
+ function pickStoriesToMeasure(index, o = {}) {
5048
+ if (o.ids?.length) {
5049
+ const byId = new Map(index.entries.map((e) => [e.id, e]));
5050
+ return o.ids.map((id) => {
5051
+ const e = byId.get(id);
5052
+ return { id, title: e?.title ?? "", name: e?.name ?? id };
5053
+ });
5054
+ }
5055
+ const want = (o.only ?? []).map((x) => x.trim().toLowerCase()).filter(Boolean);
5056
+ const per = o.perComponent ?? 3;
5057
+ return index.components.filter((c) => c.stories.length && (!want.length || want.includes(c.name.toLowerCase()) || want.includes(c.title.toLowerCase()))).flatMap((c) => c.stories.slice(0, per).map((e) => ({ id: e.id, title: c.title, name: e.name })));
5058
+ }
5059
+ const SEMANTIC_CONTAINER = /^(fieldset|ul|ol|nav|form|menu|dl|select|header|footer|button|a|label|input|textarea)$/;
5060
+ function plainLayout(n, anyRole = false) {
5061
+ if (n.kind !== "frame" || n.input || n.media || !anyRole && (n.role || SEMANTIC_CONTAINER.test(n.tag))) return false;
5062
+ const st = n.style;
5063
+ const painted = !transparent(st["background-color"]) || st["background-image"] && st["background-image"] !== "none" || st["box-shadow"] && st["box-shadow"] !== "none";
5064
+ const bordered = ["top", "right", "bottom", "left"].some((x) => st[`border-${x}-style`] !== "none" && (px(st[`border-${x}-width`]) ?? 0) > 0);
5065
+ return !painted && !bordered && !((px(st["border-top-left-radius"]) ?? 0) > 0);
5066
+ }
5067
+ function sameComponent(a, b) {
5068
+ if (a.tag !== b.tag || a.kind !== b.kind || a.role !== b.role) return false;
5069
+ const ca = new Set((a.classes ?? []).map(localClassName));
5070
+ const cb = (b.classes ?? []).map(localClassName);
5071
+ if (!ca.size && !cb.length) return true;
5072
+ return cb.some((c) => ca.has(c));
5073
+ }
5074
+ function rebase(n, dx = n.box.x, dy = n.box.y) {
5075
+ return { ...n, box: { ...n.box, x: Math.round((n.box.x - dx) * 100) / 100, y: Math.round((n.box.y - dy) * 100) / 100 }, children: n.children.map((c) => rebase(c, dx, dy)) };
5076
+ }
5077
+ function splitInstances(root) {
5078
+ if (!root || !plainLayout(root)) return [];
5079
+ const found = [];
5080
+ const collect = (n, depth) => {
5081
+ for (const c of n.children) {
5082
+ if (c.kind === "text" && (c.text ?? "").length <= 24) continue;
5083
+ if (c.kind === "text") {
5084
+ found.push(c);
5085
+ continue;
5086
+ }
5087
+ if (plainLayout(c, true) && depth < 8 && c.children.length) collect(c, depth + 1);
5088
+ else if (!plainLayout(c, true)) found.push(c);
5089
+ }
5090
+ };
5091
+ collect(root, 0);
5092
+ if (found.length < 2) return [];
5093
+ let best = [];
5094
+ for (const k of found) {
5095
+ if (best.includes(k)) continue;
5096
+ const run = found.filter((c) => sameComponent(k, c));
5097
+ if (run.length > best.length) best = run;
5098
+ }
5099
+ if (best.length < 2 || best.length * 2 <= found.length) return [];
5100
+ return best.map((n) => ({ ...rebase(n), at: { x: n.box.x - root.box.x, y: n.box.y - root.box.y } }));
5101
+ }
5102
+ function localClassName(cls) {
5103
+ const hashed = (h) => !!h && /[0-9A-Z]/.test(h);
5104
+ const m = /^_([A-Za-z][\w-]*?)_[A-Za-z0-9]{5,8}_\d+$/.exec(cls) ?? [/^[A-Za-z][\w-]*?(?:-module)?_{1,2}([A-Za-z][\w-]*?)__([\w-]{5,8})$/.exec(cls)].find((x) => x && hashed(x[2])) ?? /^(?:[a-z]+-)?[A-Z][A-Za-z0-9]*-([A-Za-z]\w*)-[A-Za-z0-9_]{5}$/.exec(cls) ?? [/^_?([A-Za-z][\w-]*?)_([A-Za-z0-9-]{5,8})$/.exec(cls)].find((x) => x && hashed(x[2]));
5105
+ return m ? m[1] : cls;
5106
+ }
5107
+ const UTILITY_KEYWORDS = new Set(
5108
+ "flex inline-flex grid inline-grid block inline-block inline hidden contents table relative absolute fixed sticky static truncate uppercase lowercase capitalize normal-case italic not-italic underline overline line-through no-underline grow shrink border rounded shadow outline ring transition transform visible invisible collapse isolate container antialiased subpixel-antialiased group peer sr-only not-sr-only resize filter blur".split(" ")
5109
+ );
5110
+ const UTILITY_SHAPE = /^(?:p|px|py|pt|pr|pb|pl|ps|pe|m|mx|my|mt|mr|mb|ml|ms|me|w|h|min-w|min-h|max-w|max-h|size|gap|gap-x|gap-y|space-x|space-y|text|bg|from|via|to|border|border-[trblxyse]|rounded|rounded-[trblse]{1,2}|font|leading|tracking|z|top|right|bottom|left|start|end|inset|inset-x|inset-y|opacity|shadow|ring|ring-offset|outline|outline-offset|items|justify|justify-items|justify-self|content|self|place-items|place-content|place-self|flex|basis|grow|shrink|order|col|col-span|col-start|col-end|row|row-span|row-start|row-end|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows|overflow|overflow-x|overflow-y|cursor|select|pointer-events|transition|duration|ease|delay|animate|scale|scale-x|scale-y|rotate|translate-x|translate-y|skew-x|skew-y|origin|fill|stroke|object|aspect|line-clamp|whitespace|break|decoration|underline-offset|list|align|appearance|backdrop|brightness|contrast|drop-shadow|grayscale|invert|saturate|sepia|hue-rotate|tabular|caret|accent|scroll|snap|touch|will-change|columns|divide|divide-x|divide-y|indent|box|float|clear|mix-blend|bg-blend)-[\w.-]+$/;
5111
+ function isUtilityClass(cls) {
5112
+ if (/[:[\]/!]/.test(cls) || /^-[a-z]/.test(cls) || /\.\d/.test(cls)) return true;
5113
+ if (/^css-[a-z0-9]{5,8}$/.test(cls) || /^(?:emotion|sc|jsx|svelte|astro)-[A-Za-z0-9_-]{4,}$/.test(cls) && /\d|[A-Z]/.test(cls)) return true;
5114
+ return UTILITY_KEYWORDS.has(cls) || UTILITY_SHAPE.test(cls);
5115
+ }
5116
+ const defaultTokenOf = (v) => /^--_/.test(v) ? void 0 : v.replace(/^--/, "").split("-").filter(Boolean).join(".");
5117
+ const px = (v) => {
5118
+ if (!v) return void 0;
5119
+ const m = /^(-?[\d.]+)px$/.exec(v.trim());
5120
+ return m ? Math.round(Number(m[1]) * 100) / 100 : void 0;
5121
+ };
5122
+ const transparent = (v) => !v || v === "transparent" || /^rgba\([^)]*,\s*0\)$/.test(v);
5123
+ function arrangement(children) {
5124
+ const kids = children.filter((c) => c.width > 0 || c.height > 0);
5125
+ if (kids.length < 2) return void 0;
5126
+ const stacked = kids.every((c, i) => i === 0 || c.y >= kids[i - 1].y + kids[i - 1].height - 1);
5127
+ const row = kids.every((c, i) => i === 0 || c.x >= kids[i - 1].x + kids[i - 1].width - 1);
5128
+ return stacked && !row ? "stacked" : row && !stacked ? "row" : void 0;
5129
+ }
5130
+ function alignOf(style) {
5131
+ const a = style["align-items"] ?? "normal";
5132
+ return /center/.test(a) ? "CENTER" : /end/.test(a) ? "MAX" : /^(flex-)?start|baseline/.test(a) ? "MIN" : "STRETCH";
5133
+ }
5134
+ function measuredLayout(style, children = []) {
5135
+ const d = style.display ?? "";
5136
+ const arranged = arrangement(children);
5137
+ if (!/flex|grid|block|inline-block|list-item/.test(d)) return arranged ? { direction: arranged === "stacked" ? "VERTICAL" : "HORIZONTAL", primary: "MIN", counter: "MIN" } : void 0;
5138
+ const flex = /flex/.test(d);
5139
+ const grid = /grid/.test(d);
5140
+ const dir = style["flex-direction"] ?? "row";
5141
+ let direction = flex && dir.startsWith("row") ? "HORIZONTAL" : "VERTICAL";
5142
+ if (grid) {
5143
+ const tracks = (v) => v && v !== "none" ? v.trim().split(/\s+(?![^(]*\))/).length : 0;
5144
+ const cols = tracks(style["grid-template-columns"]);
5145
+ const rows = tracks(style["grid-template-rows"]);
5146
+ const sideBySide = children.length >= 2 && children.every((c) => Math.abs(c.y + c.height / 2 - (children[0].y + children[0].height / 2)) <= Math.max(2, children[0].height / 2)) && new Set(children.map((c) => Math.round(c.x))).size === children.length;
5147
+ direction = /column/.test(style["grid-auto-flow"] ?? "") || cols >= 2 && rows <= 1 || cols < 2 && rows < 2 && sideBySide ? "HORIZONTAL" : "VERTICAL";
5148
+ if (cols >= 2 && rows >= 2) direction = sideBySide ? "HORIZONTAL" : "VERTICAL";
5149
+ if (cols >= 2 && rows >= 2 && !sideBySide && !/column/.test(style["grid-auto-flow"] ?? "")) return { direction: "HORIZONTAL", primary: "MIN", counter: alignOf(style), wrap: true };
5150
+ }
5151
+ const j = style["justify-content"] ?? "normal";
5152
+ const primary = !flex && !grid ? "MIN" : /space-between/.test(j) ? "SPACE_BETWEEN" : /center/.test(j) ? "CENTER" : /end|right/.test(j) ? "MAX" : "MIN";
5153
+ const counter = alignOf(style);
5154
+ if (arranged === "stacked" && direction === "HORIZONTAL" && !(flex && style["flex-wrap"] === "wrap")) direction = "VERTICAL";
5155
+ else if (arranged === "row" && direction === "VERTICAL" && !flex) direction = "HORIZONTAL";
5156
+ const out = { direction, primary, counter };
5157
+ if (flex && /reverse/.test(dir)) out.reverse = true;
5158
+ if (flex && direction === "HORIZONTAL" && style["flex-wrap"] === "wrap") out.wrap = true;
5159
+ return out;
5160
+ }
5161
+ const FIELD_MAP = [
5162
+ ["fill", "background-color"],
5163
+ ["cornerRadius", "border-top-left-radius"],
5164
+ ["paddingTop", "padding-top"],
5165
+ ["paddingRight", "padding-right"],
5166
+ ["paddingBottom", "padding-bottom"],
5167
+ ["paddingLeft", "padding-left"],
5168
+ ["minWidth", "min-width"],
5169
+ ["minHeight", "min-height"],
5170
+ ["opacity", "opacity"]
5171
+ ];
5172
+ const TEXT_MAP = [
5173
+ ["textFill", "color"],
5174
+ ["fontFamily", "font-family"],
5175
+ ["fontSize", "font-size"],
5176
+ ["fontWeight", "font-weight"],
5177
+ ["lineHeight", "line-height"],
5178
+ ["letterSpacing", "letter-spacing"]
5179
+ ];
5180
+ function measuredToSpec(m, o = {}) {
5181
+ const tokenOf = o.tokenOf ?? defaultTokenOf;
5182
+ const out = { story: m.id, parts: [], values: {}, raw: {}, tokens: {}, boxes: {}, coverage: { fields: 0, declared: 0, matched: 0, literal: 0 } };
5183
+ if (!m.root) return out;
5184
+ const used = /* @__PURE__ */ new Set();
5185
+ const idFor = (n, isRoot, inherited) => {
5186
+ if (isRoot) return "root";
5187
+ const cls = (n.classes ?? []).map(localClassName).find((c) => /^[A-Za-z]/.test(c) && c.length < 40 && !isUtilityClass(c));
5188
+ let base = cls ?? (n.pseudo ? `${inherited ?? "root"}-${n.pseudo}` : n.kind === "text" ? inherited ? `${inherited}-text` : "text" : n.kind === "icon" ? "icon" : n.tag);
5189
+ base = base.replace(/[^A-Za-z0-9-]+/g, "-").toLowerCase() || "part";
5190
+ let id = base;
5191
+ for (let i = 2; used.has(id); i++) id = `${base}-${i}`;
5192
+ used.add(id);
5193
+ return id;
5194
+ };
5195
+ const visit = (n, parent, parentStyle, parentBox) => {
5196
+ const id = idFor(n, !parent, parent);
5197
+ const style = n.kind === "text" && n.tag === "#text" ? parentStyle ?? {} : n.style;
5198
+ const tokens = n.kind === "text" && n.tag === "#text" ? {} : n.tokens;
5199
+ const part = { id, name: id === "root" ? "Root" : id.replace(/-/g, " ").replace(/^./, (c) => c.toUpperCase()), kind: n.kind };
5200
+ if (parent) part.parent = parent;
5201
+ const named = (n.classes ?? []).map(localClassName).filter((c) => !isUtilityClass(c));
5202
+ if (named.length) part.source = named.join(" ");
5203
+ if (n.kind === "frame") {
5204
+ const l = measuredLayout(n.style, n.children.filter((c) => c.style.position !== "absolute" && c.style.position !== "fixed").map((c) => c.box));
5205
+ if (l) part.layout = l;
5206
+ if (/^(hidden|clip)/.test(n.style.overflow ?? "")) part.clip = true;
5207
+ if ((n.style.position === "absolute" || n.style.position === "fixed") && parent) {
5208
+ const zero = (v) => v !== void 0 && /^0(px)?$/.test(v.trim());
5209
+ if (["top", "right", "bottom", "left"].every((k) => zero(n.style[k]))) part.cover = true;
5210
+ else {
5211
+ const pb = parentBox ?? { x: 0, y: 0 };
5212
+ part.pin = { top: Math.round((n.box.y - pb.y) * 100) / 100, left: Math.round((n.box.x - pb.x) * 100) / 100 };
5213
+ }
5214
+ }
5215
+ if (Number(n.style["flex-grow"]) > 0) part.grow = true;
5216
+ }
5217
+ if (n.kind === "text") part.characters = n.text ?? "";
5218
+ if (!parent && m.rootFill) part.fill = true;
5219
+ const margins = Object.fromEntries(["top", "right", "bottom", "left"].map((k) => [k, px(n.style[`margin-${k}`]) ?? 0]).filter(([, v]) => Math.abs(v) > 0.5));
5220
+ if (Object.keys(margins).length) part.margins = margins;
5221
+ out.parts.push(part);
5222
+ partById.set(id, part);
5223
+ out.boxes[id] = n.box;
5224
+ const values = {};
5225
+ const raw = {};
5226
+ const ev = {};
5227
+ const put = (field, prop, literal) => {
5228
+ if (literal === void 0) return;
5229
+ out.coverage.fields++;
5230
+ if (literal !== null) raw[field] = literal;
5231
+ const t2 = tokens[prop];
5232
+ if (t2) ev[field] = t2;
5233
+ if (t2?.via === "declared" && t2.exact) {
5234
+ out.coverage.declared++;
5235
+ const path = t2.chain.map(tokenOf).find((x) => !!x);
5236
+ if (path) return void (values[field] = path);
5237
+ } else if (t2?.via === "declared") out.coverage.declared++;
5238
+ else if (t2?.via === "matched") out.coverage.matched++;
5239
+ else out.coverage.literal++;
5240
+ if (literal === null) values[field] = null;
5241
+ else if (typeof literal === "number") values[field] = literal;
5242
+ };
5243
+ if (n.kind === "frame") {
5244
+ for (const [field, prop] of FIELD_MAP) {
5245
+ const v = n.style[prop];
5246
+ if (field === "fill") put(field, prop, transparent(v) ? n.style["background-image"] && n.style["background-image"] !== "none" ? n.style["background-image"] : void 0 : v);
5247
+ else if (field === "opacity") put(field, prop, v && Number(v) < 1 ? Number(v) : void 0);
5248
+ else if (field === "minWidth" || field === "minHeight") {
5249
+ const sides = field === "minWidth" ? ["left", "right"] : ["top", "bottom"];
5250
+ const extra = n.style["box-sizing"] === "content-box" ? sides.reduce((a, x) => a + (px(n.style[`padding-${x}`]) ?? 0) + (n.style[`border-${x}-style`] === "none" ? 0 : px(n.style[`border-${x}-width`]) ?? 0), 0) : 0;
5251
+ const min = px(v);
5252
+ if (!min) continue;
5253
+ if (extra) {
5254
+ out.coverage.fields++;
5255
+ out.coverage.literal++;
5256
+ raw[field] = min + extra;
5257
+ values[field] = min + extra;
5258
+ } else put(field, prop, min);
5259
+ } else if (field === "cornerRadius" && v && /%$/.test(v.trim())) {
5260
+ const half = Math.min(n.box.width, n.box.height) / 2;
5261
+ const r = Math.min(half, Math.round(Math.min(n.box.width, n.box.height) * Number.parseFloat(v) / 100 * 100) / 100);
5262
+ if (r >= half - 0.5) part.fullRadius = true;
5263
+ if (r > 0) {
5264
+ out.coverage.fields++;
5265
+ out.coverage.literal++;
5266
+ raw[field] = r;
5267
+ values[field] = part.fullRadius ? 999 : r;
5268
+ }
5269
+ } else {
5270
+ const half = Math.min(n.box.width, n.box.height) / 2;
5271
+ if (field === "cornerRadius" && (px(v) ?? 0) >= half - 0.5 && half > 0) part.fullRadius = true;
5272
+ put(field, prop, px(v) || void 0);
5273
+ if (part.fullRadius && field === "cornerRadius" && typeof values.cornerRadius === "number") values.cornerRadius = 999;
5274
+ }
5275
+ }
5276
+ const widths = ["top", "right", "bottom", "left"].map((s) => n.style[`border-${s}-style`] === "none" ? 0 : px(n.style[`border-${s}-width`]) ?? 0);
5277
+ if (widths.some((w) => w > 0)) {
5278
+ const side = widths.findIndex((w) => w > 0);
5279
+ const s = ["top", "right", "bottom", "left"][side];
5280
+ const color = n.style[`border-${s}-color`];
5281
+ put("stroke", `border-${s}-color`, transparent(color) ? null : color);
5282
+ if (widths.every((w) => w === widths[0])) put("strokeWeight", "border-top-width", widths[0]);
5283
+ else ["top", "right", "bottom", "left"].forEach((x, i) => put({ top: "strokeTopWeight", right: "strokeRightWeight", bottom: "strokeBottomWeight", left: "strokeLeftWeight" }[x], `border-${x}-width`, widths[i]));
5284
+ }
5285
+ if (parseBoxShadow(n.style["box-shadow"]).length) put("shadow", "box-shadow", n.style["box-shadow"]);
5286
+ const l = part.layout;
5287
+ if (l && /flex|grid/.test(n.style.display ?? "")) {
5288
+ const gap = l.direction === "HORIZONTAL" ? n.style["column-gap"] : n.style["row-gap"];
5289
+ put("itemSpacing", l.direction === "HORIZONTAL" ? "column-gap" : "row-gap", px(gap) || void 0);
5290
+ if (l.wrap) put("counterAxisSpacing", "row-gap", px(n.style["row-gap"]) || void 0);
5291
+ }
5292
+ put("width", "width", n.box.width);
5293
+ put("height", "height", n.box.height);
5294
+ }
5295
+ if (n.kind === "text") {
5296
+ for (const [field, prop] of TEXT_MAP) {
5297
+ const v = style[prop];
5298
+ if (!v || v === "normal") continue;
5299
+ put(field, prop, field === "textFill" || field === "fontFamily" ? v : field === "fontWeight" ? Number(v) : px(v));
5300
+ }
5301
+ const deco = style["text-decoration-line"];
5302
+ if (deco && /underline|line-through/.test(deco)) raw.textDecoration = /underline/.test(deco) ? "UNDERLINE" : "STRIKETHROUGH";
5303
+ }
5304
+ if ((n.kind === "icon" || n.kind === "vector") && n.svg) (out.vectors ??= {})[id] = { svg: n.svg, strokes: n.svgStrokes ?? [] };
5305
+ if (n.kind === "icon" || n.kind === "vector") {
5306
+ put("width", "width", n.box.width);
5307
+ put("height", "height", n.box.height);
5308
+ const stroked = !!n.style.stroke && n.style.stroke !== "none";
5309
+ const prop = stroked ? "stroke" : "fill";
5310
+ const paint = n.style[prop];
5311
+ if (paint && paint !== "none") put(stroked ? "stroke" : "fill", n.tokens[prop] ? prop : "color", /currentcolor/i.test(paint) ? n.style.color : paint);
5312
+ if (stroked) put("strokeWeight", "stroke-width", px(n.style["stroke-width"]) ?? (Number(n.style["stroke-width"]) || void 0));
5313
+ }
5314
+ if (Object.keys(values).length) out.values[id] = values;
5315
+ if (Object.keys(raw).length) out.raw[id] = raw;
5316
+ if (Object.keys(ev).length) out.tokens[id] = ev;
5317
+ if (n.sized && (n.sized.width || n.sized.height)) (out.sized ??= {})[id] = { ...n.sized.width ? { width: n.box.width } : {}, ...n.sized.height ? { height: n.box.height } : {} };
5318
+ const kids = n.children.map((c) => [c, visit(c, id, n.style, n.box)]);
5319
+ if (part.layout?.wrap && /grid/.test(n.style.display ?? "")) {
5320
+ for (const [c, cid] of [[n, id], ...kids]) if (c === n || !/absolute|fixed/.test(c.style.position ?? "")) (out.sized ??= {})[cid] = { ...out.sized?.[cid], width: c.box.width };
5321
+ }
5322
+ if (part.layout) spacing(id, n, part.layout, kids);
5323
+ if (n.kind === "frame") positioned(id, part, n, kids);
5324
+ const t = /matrix\(([^)]+)\)/.exec(n.style.transform ?? "")?.[1]?.split(",").map(Number);
5325
+ if (parent && parentBox && t && t.length === 6 && Math.abs(t[1]) < 1e-6 && Math.abs(t[2]) < 1e-6 && (Math.abs(t[4]) >= 0.5 || Math.abs(t[5]) >= 0.5 || Math.abs(t[0] - 1) > 0.01 || Math.abs(t[3] - 1) > 0.01) && !part.cover) {
5326
+ part.pin = { top: Math.round((n.box.y - parentBox.y) * 100) / 100, left: Math.round((n.box.x - parentBox.x) * 100) / 100 };
5327
+ if (Math.abs(t[0] - 1) > 0.01 || Math.abs(t[3] - 1) > 0.01) (out.sized ??= {})[id] = { width: n.box.width, height: n.box.height };
5328
+ }
5329
+ return id;
5330
+ };
5331
+ const partById = /* @__PURE__ */ new Map();
5332
+ const byId = (id) => partById.get(id) ?? out.parts.find((p) => p.id === id);
5333
+ const positioned = (id, parentPart, n, kids) => {
5334
+ const abs = kids.filter(([c]) => c.style.position === "absolute" || c.style.position === "fixed");
5335
+ if (!abs.length) return;
5336
+ const flow = kids.filter(([c]) => !(c.style.position === "absolute" || c.style.position === "fixed") && (c.box.width > 0 || c.box.height > 0));
5337
+ const st = n.style;
5338
+ const b = (k) => st[`border-${k}-style`] === "none" ? 0 : px(st[`border-${k}-width`]) ?? 0;
5339
+ const inner = { x: n.box.x + b("left"), y: n.box.y + b("top"), r: n.box.x + n.box.width - b("right"), bottom: n.box.y + n.box.height - b("bottom") };
5340
+ const r2 = (x) => Math.round(x * 100) / 100;
5341
+ if (abs.length === 1 && !flow.length) {
5342
+ const [c, cid] = abs[0];
5343
+ const p = byId(cid);
5344
+ if (p && !p.cover) {
5345
+ const left = r2(c.box.x - inner.x), right = r2(inner.r - (c.box.x + c.box.width));
5346
+ const top = r2(c.box.y - inner.y), bottom = r2(inner.bottom - (c.box.y + c.box.height));
5347
+ const ax = (a, z) => Math.abs(a - z) <= 1 ? "center" : a <= z ? "start" : "end";
5348
+ const x = ax(left, right), y = ax(top, bottom);
5349
+ if (left >= -0.5 && right >= -0.5 && top >= -0.5 && bottom >= -0.5) {
5350
+ delete p.pin;
5351
+ const map = { start: "MIN", center: "CENTER", end: "MAX" };
5352
+ parentPart.layout = { direction: "HORIZONTAL", primary: map[x], counter: map[y], align: { [cid]: { primary: map[x], counter: map[y] } } };
5353
+ const vals = out.values[id] ??= {};
5354
+ const raws = out.raw[id] ??= {};
5355
+ const set = (k, v) => {
5356
+ if (v > 0.5) {
5357
+ vals[k] = v;
5358
+ raws[k] = v;
5359
+ } else {
5360
+ delete vals[k];
5361
+ delete raws[k];
5362
+ }
5363
+ };
5364
+ set("paddingLeft", x === "start" ? left : 0);
5365
+ set("paddingRight", x === "end" ? right : 0);
5366
+ set("paddingTop", y === "start" ? top : 0);
5367
+ set("paddingBottom", y === "end" ? bottom : 0);
5368
+ return;
5369
+ }
5370
+ }
5371
+ }
5372
+ const overlaps = (a, z) => a.x < z.x + z.width - 0.5 && z.x < a.x + a.width - 0.5 && a.y < z.y + z.height - 0.5 && z.y < a.y + a.height - 0.5;
5373
+ for (const [c, cid] of abs) {
5374
+ const p = byId(cid);
5375
+ if (!p || p.cover) continue;
5376
+ const outside = c.box.x < inner.x - 0.5 || c.box.y < inner.y - 0.5 || c.box.x + c.box.width > inner.r + 0.5 || c.box.y + c.box.height > inner.bottom + 0.5;
5377
+ if (outside || flow.some(([f]) => overlaps(c.box, f.box))) p.overlay = true;
5378
+ }
5379
+ };
5380
+ const spacing = (id, n, layout, kids) => {
5381
+ if (layout.primary !== "MIN" || layout.wrap || layout.reverse) return;
5382
+ const flow = kids.filter(([c]) => c.style.position !== "absolute" && c.style.position !== "fixed" && (c.box.width > 0 || c.box.height > 0));
5383
+ if (!flow.length) return;
5384
+ const v = layout.direction === "VERTICAL";
5385
+ const st = n.style;
5386
+ const side = v ? ["top", "bottom"] : ["left", "right"];
5387
+ const num = (x) => px(x) ?? 0;
5388
+ const startEdge = (v ? n.box.y : n.box.x) + (st[`border-${side[0]}-style`] === "none" ? 0 : num(st[`border-${side[0]}-width`])) + num(st[`padding-${side[0]}`]);
5389
+ const endEdge = (v ? n.box.y + n.box.height : n.box.x + n.box.width) - (st[`border-${side[1]}-style`] === "none" ? 0 : num(st[`border-${side[1]}-width`])) - num(st[`padding-${side[1]}`]);
5390
+ const lo = (b) => v ? b.y : b.x;
5391
+ const hi = (b) => v ? b.y + b.height : b.x + b.width;
5392
+ const gaps = flow.slice(1).map(([c], i) => Math.round((lo(c.box) - hi(flow[i][0].box)) * 100) / 100);
5393
+ if (gaps.some((g) => g < -0.5)) return;
5394
+ const vals = out.values[id] ??= {};
5395
+ const raws = out.raw[id] ??= {};
5396
+ const padKey = (k) => ({ top: "paddingTop", bottom: "paddingBottom", left: "paddingLeft", right: "paddingRight" })[k];
5397
+ const first = flow[0][0];
5398
+ const last = flow[flow.length - 1][0];
5399
+ const before = Math.min(num(first.style[`margin-${side[0]}`]), Math.round((lo(first.box) - startEdge) * 100) / 100);
5400
+ const after = Math.min(num(last.style[`margin-${side[1]}`]), Math.round((endEdge - hi(last.box)) * 100) / 100);
5401
+ for (const [k, extra] of [[side[0], before], [side[1], after]]) {
5402
+ if (!(extra > 0.5)) continue;
5403
+ const total = Math.round((num(st[`padding-${k}`]) + extra) * 100) / 100;
5404
+ vals[padKey(k)] = total;
5405
+ raws[padKey(k)] = total;
5406
+ }
5407
+ if (!gaps.length) return;
5408
+ const marginBetween = flow.slice(1).some(([c], i) => num(flow[i][0].style[`margin-${side[1]}`]) > 0.5 || num(c.style[`margin-${side[0]}`]) > 0.5);
5409
+ if (!marginBetween) return;
5410
+ const declaredGap = num(v ? st["row-gap"] : st["column-gap"]);
5411
+ const min = Math.min(...gaps);
5412
+ const uniform = gaps.every((g) => Math.abs(g - gaps[0]) <= 0.5);
5413
+ if (uniform && Math.abs(gaps[0] - declaredGap) <= 0.5) return;
5414
+ vals.itemSpacing = uniform ? gaps[0] : min;
5415
+ raws.itemSpacing = vals.itemSpacing;
5416
+ if (!uniform)
5417
+ flow.slice(1).forEach(([c, cid], i) => {
5418
+ const extra = Math.round((gaps[i] - min) * 100) / 100;
5419
+ if (!(extra > 0.5)) return;
5420
+ (out.spacers ??= {})[cid] = extra;
5421
+ const [prev, pid] = flow[i];
5422
+ const onPrev = num(prev.style[`margin-${side[1]}`]) > 0.5 && !(num(c.style[`margin-${side[0]}`]) > num(prev.style[`margin-${side[1]}`]));
5423
+ const owner = byId(onPrev ? pid : cid);
5424
+ if (owner) owner.wrap = { padding: { ...owner.wrap?.padding ?? {}, [onPrev ? side[1] : side[0]]: extra } };
5425
+ });
5426
+ };
5427
+ visit(m.root, void 0, void 0);
5428
+ for (const k of Object.keys(out.values)) if (!Object.keys(out.values[k]).length) delete out.values[k];
5429
+ for (const k of Object.keys(out.raw)) if (!Object.keys(out.raw[k]).length) delete out.raw[k];
5430
+ return out;
5431
+ }
3847
5432
  export {
5433
+ APPLY_ARGS_SCRIPT,
3848
5434
  COMMON_ICONS,
3849
5435
  DEFAULT_STATE,
5436
+ GLOBALS_SCRIPT,
3850
5437
  ICON_STYLE,
3851
5438
  INHERITED,
5439
+ MEASURE_SCRIPT,
3852
5440
  MEDIA_SLOT,
5441
+ aV as MeasuredSpecsError,
5442
+ OPEN_SCRIPT,
5443
+ PROPS_SCRIPT,
5444
+ SPEC_VIEWPORT_WIDTH,
5445
+ TOKENS_SCRIPT,
3853
5446
  UnsupportedComponentError,
5447
+ WAIT_SCRIPT,
3854
5448
  applySuggestionLocally,
3855
5449
  branchExists,
3856
5450
  changedProperties,
3857
5451
  collectAuditFiles,
3858
5452
  commitToNewLocalBranch,
3859
5453
  commitTree,
5454
+ C as compareSpecToMeasured,
3860
5455
  computeValues,
3861
5456
  currentBranch,
3862
5457
  declaredFor,
3863
5458
  draftedCodeHash,
3864
5459
  draftedSpec,
3865
5460
  entryFor,
5461
+ c4 as evalCalc,
3866
5462
  expandDecl,
3867
5463
  fileDiff,
3868
5464
  findDesignSystemRoot,
@@ -3876,37 +5472,54 @@ export {
3876
5472
  generateSlots,
3877
5473
  git,
3878
5474
  gitWorkspace,
5475
+ harvestTokens,
3879
5476
  isGitRepo,
5477
+ isUtilityClass,
3880
5478
  jsxText,
3881
5479
  listFilesAt,
3882
5480
  loadAllowlist,
3883
5481
  loadDesignSystem,
3884
5482
  loadLocalHistory,
5483
+ localClassName,
3885
5484
  localGitHistoryBackend,
3886
5485
  localRepoRef,
3887
5486
  localTags,
5487
+ markMeasuredRoot,
5488
+ cJ as markUsedTokens,
3888
5489
  matchComplex,
5490
+ measureRendered,
5491
+ measureStory,
5492
+ measuredLayout,
5493
+ measuredToSpec,
3889
5494
  mediaApplies,
3890
5495
  mergeText,
3891
5496
  motionNotes,
3892
5497
  openingTransitions,
3893
5498
  originRepo,
3894
5499
  overridesDirOf,
5500
+ I as pairParts,
3895
5501
  parseCssModule,
5502
+ c_ as parseMeasuredSpecsFile,
3896
5503
  parseSelector,
3897
5504
  parseTransitions,
5505
+ pickStoriesToMeasure,
3898
5506
  repoSpecOptions,
3899
5507
  resolveDuration,
3900
5508
  resolveEasing,
5509
+ resolveTokenValues,
3901
5510
  runAudit,
3902
5511
  sentenceCase,
3903
5512
  serializeComponentSpecs,
5513
+ sharedTokenPrefix,
3904
5514
  shorthandOf,
3905
5515
  showFile,
3906
5516
  specDrawsSomething,
5517
+ splitInstances,
3907
5518
  splitTop,
3908
5519
  substituteVars,
3909
5520
  tokenCssIndex,
3910
- transitionBetween
5521
+ tokenVariablePath,
5522
+ transitionBetween,
5523
+ H as withoutAddedWrappers
3911
5524
  };
3912
5525
  //# sourceMappingURL=index.js.map