tsquare 0.12.4 → 0.13.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.
@@ -7675,16 +7675,16 @@ function FDEF(state) {
7675
7675
  state.ip = ip;
7676
7676
  state.funcs[fn] = prog.slice(ipBegin + 1, ip);
7677
7677
  }
7678
- function MDAP(round, state) {
7678
+ function MDAP(round2, state) {
7679
7679
  var pi = state.stack.pop();
7680
7680
  var p = state.z0[pi];
7681
7681
  var fv = state.fv;
7682
7682
  var pv = state.pv;
7683
7683
  if (exports.DEBUG) {
7684
- console.log(state.step, "MDAP[" + round + "]", pi);
7684
+ console.log(state.step, "MDAP[" + round2 + "]", pi);
7685
7685
  }
7686
7686
  var d2 = pv.distance(p, HPZero);
7687
- if (round) {
7687
+ if (round2) {
7688
7688
  d2 = state.round(d2);
7689
7689
  }
7690
7690
  fv.setRelative(p, HPZero, d2, pv);
@@ -7887,7 +7887,7 @@ function RTDG(state) {
7887
7887
  }
7888
7888
  state.round = roundToDoubleGrid;
7889
7889
  }
7890
- function MIAP(round, state) {
7890
+ function MIAP(round2, state) {
7891
7891
  var stack = state.stack;
7892
7892
  var n = stack.pop();
7893
7893
  var pi = stack.pop();
@@ -7898,7 +7898,7 @@ function MIAP(round, state) {
7898
7898
  if (exports.DEBUG) {
7899
7899
  console.log(
7900
7900
  state.step,
7901
- "MIAP[" + round + "]",
7901
+ "MIAP[" + round2 + "]",
7902
7902
  n,
7903
7903
  "(",
7904
7904
  cv,
@@ -7907,7 +7907,7 @@ function MIAP(round, state) {
7907
7907
  );
7908
7908
  }
7909
7909
  var d2 = pv.distance(p, HPZero);
7910
- if (round) {
7910
+ if (round2) {
7911
7911
  if (Math.abs(d2 - cv) < state.cvCutIn) {
7912
7912
  d2 = cv;
7913
7913
  }
@@ -20659,6 +20659,7 @@ function markRoot(root, color) {
20659
20659
  const kids = Children.toArray(node.props.children);
20660
20660
  return cloneElement(node, {}, ...kids, /* @__PURE__ */ jsx3(Marker, { color }, "__marker"));
20661
20661
  }
20662
+ var MARKS_ITSELF = /* @__PURE__ */ new Set(["Screen", "Modal", "Drawer", "Toast"]);
20662
20663
  function withMarkers(reg) {
20663
20664
  return Object.fromEntries(
20664
20665
  Object.entries(reg).map(([name, C]) => [
@@ -20666,7 +20667,7 @@ function withMarkers(reg) {
20666
20667
  (props) => {
20667
20668
  const root = C(props);
20668
20669
  const color = props.element?.props?.__mark;
20669
- return color && name !== "Screen" ? markRoot(root, color) : root;
20670
+ return color && !MARKS_ITSELF.has(name) ? markRoot(root, color) : root;
20670
20671
  }
20671
20672
  ])
20672
20673
  );
@@ -20840,19 +20841,22 @@ function Screen({ element, children }) {
20840
20841
  s.chrome && s.device === "desktop" ? /* @__PURE__ */ jsx3(BrowserBar, {}) : null,
20841
20842
  /* @__PURE__ */ jsxs(Box, { style: { position: "relative", flexGrow: 1, flexBasis: "0px", flexDirection: "column", overflow: "hidden" }, children: [
20842
20843
  top,
20843
- /* @__PURE__ */ jsx3(Box, { style: { flexGrow: 1, flexBasis: "0px", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsx3(
20844
- Box,
20845
- {
20846
- style: {
20847
- flexGrow: 1,
20848
- flexShrink: 0,
20849
- flexDirection: "column",
20850
- padding: s.padding,
20851
- gap: p.gap ?? 14
20852
- },
20853
- children: withDir(body, "column")
20854
- }
20855
- ) }),
20844
+ /* @__PURE__ */ jsxs(Box, { style: { flexGrow: 1, flexBasis: "0px", flexDirection: "column", overflow: "hidden" }, children: [
20845
+ /* @__PURE__ */ jsx3(
20846
+ Box,
20847
+ {
20848
+ style: {
20849
+ flexGrow: 1,
20850
+ flexShrink: 0,
20851
+ flexDirection: "column",
20852
+ padding: s.padding,
20853
+ gap: p.gap ?? 14
20854
+ },
20855
+ children: withDir(body, "column")
20856
+ }
20857
+ ),
20858
+ p.__markBody ? /* @__PURE__ */ jsx3(Marker, { color: p.__markBody }) : null
20859
+ ] }),
20856
20860
  bottom,
20857
20861
  overlays.map((o2) => isValidElement(o2) ? cloneElement(o2, { aboveTabBar: bottom.length > 0 }) : o2),
20858
20862
  p.__mark ? /* @__PURE__ */ jsx3(Marker, { color: p.__mark }) : null
@@ -21118,9 +21122,9 @@ function Chart({ element, dir }) {
21118
21122
  const kind = p.kind ?? "line";
21119
21123
  const h2 = p.height ?? 180;
21120
21124
  const w2 = p.width ?? (dir === "row" ? void 0 : "100%");
21121
- const round = kind === "pie" || kind === "donut";
21125
+ const round2 = kind === "pie" || kind === "donut";
21122
21126
  const plot = (() => {
21123
- if (round) {
21127
+ if (round2) {
21124
21128
  const slice = (from, to2, fill, k) => {
21125
21129
  const a0 = from / 100 * 2 * Math.PI - Math.PI / 2, a1 = to2 / 100 * 2 * Math.PI - Math.PI / 2;
21126
21130
  const x0 = 50 + 46 * Math.cos(a0), y0 = 50 + 46 * Math.sin(a0), x1 = 50 + 46 * Math.cos(a1), y1 = 50 + 46 * Math.sin(a1);
@@ -21150,7 +21154,7 @@ function Chart({ element, dir }) {
21150
21154
  })();
21151
21155
  return /* @__PURE__ */ jsxs(Box, { style: { flexDirection: "column", gap: 10, width: w2, height: h2, flexShrink: 0, ...dir === "row" ? { flexGrow: 1, flexBasis: "0px" } : {} }, children: [
21152
21156
  p.title ? /* @__PURE__ */ jsx3(Box, { style: { fontSize: 13, fontWeight: 600, color: theme.text }, children: p.title }) : null,
21153
- /* @__PURE__ */ jsx3(Box, { style: { flexGrow: 1, borderBottom: round ? void 0 : `1.5px solid ${theme.line}`, justifyContent: round ? "center" : void 0, alignItems: round ? "center" : void 0 }, children: plot })
21157
+ /* @__PURE__ */ jsx3(Box, { style: { flexGrow: 1, borderBottom: round2 ? void 0 : `1.5px solid ${theme.line}`, justifyContent: round2 ? "center" : void 0, alignItems: round2 ? "center" : void 0 }, children: plot })
21154
21158
  ] });
21155
21159
  }
21156
21160
  function AvatarCircle({ initials, size = 40 }) {
@@ -21315,7 +21319,7 @@ function Select({ element, dir }) {
21315
21319
  ] })
21316
21320
  ] });
21317
21321
  }
21318
- function CheckMark({ checked, round = false, c: c2 = GRAY }) {
21322
+ function CheckMark({ checked, round: round2 = false, c: c2 = GRAY }) {
21319
21323
  return /* @__PURE__ */ jsx3(
21320
21324
  Box,
21321
21325
  {
@@ -21323,13 +21327,13 @@ function CheckMark({ checked, round = false, c: c2 = GRAY }) {
21323
21327
  width: 20,
21324
21328
  height: 20,
21325
21329
  flexShrink: 0,
21326
- borderRadius: round ? 10 : 5,
21327
- border: `1.5px solid ${checked && !round ? c2.accent : theme.lineStrong}`,
21328
- backgroundColor: checked && !round ? c2.accent : theme.paper,
21330
+ borderRadius: round2 ? 10 : 5,
21331
+ border: `1.5px solid ${checked && !round2 ? c2.accent : theme.lineStrong}`,
21332
+ backgroundColor: checked && !round2 ? c2.accent : theme.paper,
21329
21333
  alignItems: "center",
21330
21334
  justifyContent: "center"
21331
21335
  },
21332
- children: checked ? round ? /* @__PURE__ */ jsx3(Box, { style: { width: 10, height: 10, borderRadius: 5, backgroundColor: c2.accent } }) : /* @__PURE__ */ jsx3(IconGlyph, { name: "check", size: 14, color: c2.onAccent, strokeWidth: 3 }) : null
21336
+ children: checked ? round2 ? /* @__PURE__ */ jsx3(Box, { style: { width: 10, height: 10, borderRadius: 5, backgroundColor: c2.accent } }) : /* @__PURE__ */ jsx3(IconGlyph, { name: "check", size: 14, color: c2.onAccent, strokeWidth: 3 }) : null
21333
21337
  }
21334
21338
  );
21335
21339
  }
@@ -21469,7 +21473,7 @@ function Calendar({ element, dir, aligned, colors: c2 = GRAY }) {
21469
21473
  /* @__PURE__ */ jsx3(Box, { children: ["S", "M", "T", "W", "T", "F", "S"].map((d2, i2) => /* @__PURE__ */ jsx3(Box, { style: { width: CELL, justifyContent: "center", fontSize: 12, color: theme.muted }, children: d2 }, i2)) }),
21470
21474
  weeks.map((week, w2) => /* @__PURE__ */ jsx3(Box, { children: week.map((d2, i2) => {
21471
21475
  const end = d2 != null && (d2 === from || d2 === to2) && from > 0;
21472
- const inside = d2 != null && from > 0 && d2 > from && d2 < to2;
21476
+ const inside2 = d2 != null && from > 0 && d2 > from && d2 < to2;
21473
21477
  const band = d2 != null && from > 0 && to2 > from && d2 >= from && d2 <= to2;
21474
21478
  return /* @__PURE__ */ jsxs(Box, { style: { width: CELL, height: CELL, alignItems: "center", justifyContent: "center", position: "relative" }, children: [
21475
21479
  band ? /* @__PURE__ */ jsx3(Box, { style: { position: "absolute", top: 4, bottom: 4, left: d2 === from ? CELL / 2 : 0, right: d2 === to2 ? CELL / 2 : 0, backgroundColor: theme.fill } }) : null,
@@ -21485,7 +21489,7 @@ function Calendar({ element, dir, aligned, colors: c2 = GRAY }) {
21485
21489
  justifyContent: "center",
21486
21490
  fontSize: 14,
21487
21491
  backgroundColor: end ? c2.accent : void 0,
21488
- color: end ? c2.onAccent : inside ? theme.ink : theme.text,
21492
+ color: end ? c2.onAccent : inside2 ? theme.ink : theme.text,
21489
21493
  fontWeight: end ? 600 : 400
21490
21494
  },
21491
21495
  children: [
@@ -21707,7 +21711,8 @@ function Modal({ element, children }) {
21707
21711
  },
21708
21712
  children: [
21709
21713
  p.title ? /* @__PURE__ */ jsx3(Box, { style: { fontSize: 18, fontWeight: 600 }, children: p.title }) : null,
21710
- withDir(children, "column")
21714
+ withDir(children, "column"),
21715
+ p.__mark ? /* @__PURE__ */ jsx3(Marker, { color: p.__mark }) : null
21711
21716
  ]
21712
21717
  }
21713
21718
  ) });
@@ -21742,7 +21747,8 @@ function Drawer({ element, children }) {
21742
21747
  /* @__PURE__ */ jsx3(Box, { style: { fontSize: 18, fontWeight: 600 }, children: p.title }),
21743
21748
  /* @__PURE__ */ jsx3(IconGlyph, { name: "x", size: 22, color: theme.muted })
21744
21749
  ] }) : null,
21745
- withDir(children, "column")
21750
+ withDir(children, "column"),
21751
+ p.__mark ? /* @__PURE__ */ jsx3(Marker, { color: p.__mark }) : null
21746
21752
  ]
21747
21753
  }
21748
21754
  ) });
@@ -21755,7 +21761,8 @@ function Toast({ element, aboveTabBar }) {
21755
21761
  return /* @__PURE__ */ jsx3(Box, { style: { position: "absolute", left: 16, right: 16, justifyContent: side, ...top ? { top: 16 } : { bottom: aboveTabBar ? 92 : 24 } }, children: /* @__PURE__ */ jsxs(Box, { style: { alignItems: "center", gap: 12, padding: "12px 16px", borderRadius: 12, backgroundColor: theme.ink, color: theme.onPrimary, fontSize: 14, boxShadow: "0 6px 20px rgba(0,0,0,0.22)", maxWidth: 420 }, children: [
21756
21762
  p.icon ? /* @__PURE__ */ jsx3(IconGlyph, { name: p.icon, size: 18, color: theme.onPrimary }) : null,
21757
21763
  /* @__PURE__ */ jsx3(Box, { style: { flexShrink: 1 }, children: p.text ?? "" }),
21758
- p.action ? /* @__PURE__ */ jsx3(Box, { style: { fontWeight: 700, marginLeft: 8, flexShrink: 0 }, children: p.action }) : null
21764
+ p.action ? /* @__PURE__ */ jsx3(Box, { style: { fontWeight: 700, marginLeft: 8, flexShrink: 0 }, children: p.action }) : null,
21765
+ p.__mark ? /* @__PURE__ */ jsx3(Marker, { color: p.__mark }) : null
21759
21766
  ] }) });
21760
21767
  }
21761
21768
  function Flow() {
@@ -21832,22 +21839,23 @@ function findAnchors(spec) {
21832
21839
  return [...out, ...tips];
21833
21840
  }
21834
21841
  var MARK = (i2) => `#fe${(i2 >> 8).toString(16).padStart(2, "0")}${(i2 & 255).toString(16).padStart(2, "0")}`;
21835
- function tagForMeasuring(spec, anchors) {
21842
+ function tagForMeasuring(spec, anchors, bodies = []) {
21836
21843
  const tagged = structuredClone(spec);
21837
21844
  const colors = /* @__PURE__ */ new Map();
21838
21845
  let n = 1;
21839
- const tag = (id, field) => {
21840
- const key = field ? `${id}#field` : id;
21846
+ const tag = (id, part) => {
21847
+ const key = part ? `${id}#${part}` : id;
21841
21848
  if (colors.has(key)) return;
21842
21849
  const color = MARK(n++);
21843
21850
  colors.set(key, color);
21844
21851
  const el2 = tagged.elements[id];
21845
- el2.props = { ...el2.props ?? {}, [field ? "__markField" : "__mark"]: color };
21852
+ el2.props = { ...el2.props ?? {}, [part === "field" ? "__markField" : part === "body" ? "__markBody" : "__mark"]: color };
21846
21853
  };
21847
21854
  for (const a of anchors) {
21848
- tag(a.screen, false);
21849
- tag(a.id, a.field);
21855
+ tag(a.screen, "");
21856
+ tag(a.id, a.field ? "field" : "");
21850
21857
  }
21858
+ for (const id of bodies) tag(id, "body");
21851
21859
  return { tagged, colors };
21852
21860
  }
21853
21861
  function readMarkers(svg, colors) {
@@ -21906,35 +21914,54 @@ function tooltipSize(text2) {
21906
21914
  const lines = Math.max(1, Math.ceil(text2.length * 7.4 / 216));
21907
21915
  return { w: width, h: lines * 18 + 12 + 6 };
21908
21916
  }
21917
+ function placeOverlay(spec, a, boxes) {
21918
+ const screen = boxes[a.screen];
21919
+ const anchor = boxes[a.field ? `${a.id}#field` : a.id];
21920
+ if (!screen || !anchor) return null;
21921
+ const p = propsOf(spec.elements, a.id);
21922
+ if (a.kind === "options") {
21923
+ const options = p.options?.length ? p.options : [p.value ?? "Option 1", "Option 2", "Option 3"];
21924
+ const size2 = { w: anchor.w, h: options.length * ROW + 8 };
21925
+ return { screen, anchor, size: size2, pos: place(anchor, size2, screen, { prefer: "below", align: "start", gap: 4 }), options };
21926
+ }
21927
+ if (a.kind === "menu") {
21928
+ const items = p.menu.map((i2) => typeof i2 === "string" ? { label: i2 } : i2);
21929
+ const width = a.end ? 200 : Math.max(180, anchor.w);
21930
+ const inRightHalf = anchor.x + anchor.w / 2 > screen.x + screen.w / 2;
21931
+ const size2 = { w: width, h: items.length * ROW + 8 };
21932
+ return { screen, anchor, size: size2, pos: place(anchor, size2, screen, { prefer: "below", align: a.end || inRightHalf ? "end" : "start", gap: a.end ? -6 : 4 }), items };
21933
+ }
21934
+ if (a.kind === "calendar") {
21935
+ const date = parseDate(p.value);
21936
+ const { start, days } = monthGrid(date?.month);
21937
+ const weeks = Math.ceil((start + days) / 7);
21938
+ const size2 = { w: 296, h: 92 + weeks * 38 };
21939
+ return { screen, anchor, size: size2, pos: place(anchor, size2, screen, { prefer: "below", align: "start", gap: 4 }), date };
21940
+ }
21941
+ const size = tooltipSize(p.tooltip);
21942
+ return { screen, anchor, size, pos: place(anchor, size, screen, { prefer: "above", align: "center", gap: 4 }) };
21943
+ }
21944
+ function overlayBoxes(spec, anchors, boxes) {
21945
+ return anchors.flatMap((a) => {
21946
+ const o2 = placeOverlay(spec, a, boxes);
21947
+ return o2 ? [{ id: a.id, box: { x: o2.screen.x + o2.pos.x, y: o2.screen.y + o2.pos.y, w: o2.size.w, h: o2.size.h } }] : [];
21948
+ });
21949
+ }
21909
21950
  function overlayLayer(spec, anchors, boxes, c2, Calendar2) {
21910
21951
  const byScreen = /* @__PURE__ */ new Map();
21911
21952
  for (const a of anchors) {
21912
- const screen = boxes[a.screen];
21913
- const anchor = boxes[a.field ? `${a.id}#field` : a.id];
21914
- if (!screen || !anchor) continue;
21953
+ const o2 = placeOverlay(spec, a, boxes);
21954
+ if (!o2) continue;
21955
+ const { screen, anchor, size, pos } = o2;
21915
21956
  const p = propsOf(spec.elements, a.id);
21916
21957
  let node = null;
21917
- let pos = null;
21918
21958
  if (a.kind === "options") {
21919
- const options = p.options?.length ? p.options : [p.value ?? "Option 1", "Option 2", "Option 3"];
21920
- const size = { w: anchor.w, h: options.length * ROW + 8 };
21921
- pos = place(anchor, size, screen, { prefer: "below", align: "start", gap: 4 });
21922
- node = /* @__PURE__ */ jsx4(ListCard, { items: options.map((label) => ({ label })), width: size.w, selected: p.value, c: c2 });
21959
+ node = /* @__PURE__ */ jsx4(ListCard, { items: o2.options.map((label) => ({ label })), width: size.w, selected: p.value, c: c2 });
21923
21960
  } else if (a.kind === "menu") {
21924
- const items = p.menu.map((i2) => typeof i2 === "string" ? { label: i2 } : i2);
21925
- const width = a.end ? 200 : Math.max(180, anchor.w);
21926
- const inRightHalf = anchor.x + anchor.w / 2 > screen.x + screen.w / 2;
21927
- pos = place(anchor, { w: width, h: items.length * ROW + 8 }, screen, { prefer: "below", align: a.end || inRightHalf ? "end" : "start", gap: a.end ? -6 : 4 });
21928
- node = /* @__PURE__ */ jsx4(ListCard, { items, width, c: c2 });
21961
+ node = /* @__PURE__ */ jsx4(ListCard, { items: o2.items, width: size.w, c: c2 });
21929
21962
  } else if (a.kind === "calendar") {
21930
- const date = parseDate(p.value);
21931
- const { start, days } = monthGrid(date?.month);
21932
- const weeks = Math.ceil((start + days) / 7);
21933
- pos = place(anchor, { w: 296, h: 92 + weeks * 38 }, screen, { prefer: "below", align: "start", gap: 4 });
21934
- node = /* @__PURE__ */ jsx4("div", { style: { display: "flex", boxShadow: "0 8px 24px rgba(0,0,0,0.18)", borderRadius: 12 }, children: Calendar2({ element: { type: "Calendar", props: { month: date?.month ?? "Month", selected: date?.day } }, colors: c2 }) });
21963
+ node = /* @__PURE__ */ jsx4("div", { style: { display: "flex", boxShadow: "0 8px 24px rgba(0,0,0,0.18)", borderRadius: 12 }, children: Calendar2({ element: { type: "Calendar", props: { month: o2.date?.month ?? "Month", selected: o2.date?.day } }, colors: c2 }) });
21935
21964
  } else {
21936
- const size = tooltipSize(p.tooltip);
21937
- pos = place(anchor, size, screen, { prefer: "above", align: "center", gap: 4 });
21938
21965
  node = /* @__PURE__ */ jsx4(Tooltip, { text: p.tooltip, side: pos.side, width: size.w, arrowX: anchor.x + anchor.w / 2 - (screen.x + pos.x) });
21939
21966
  }
21940
21967
  const list = byScreen.get(a.screen) ?? [];
@@ -22076,9 +22103,7 @@ function flowColor(color, palette) {
22076
22103
  const s = String(color);
22077
22104
  return ACCENTS[s] ?? s;
22078
22105
  }
22079
- function flowLayer(spec, flows, screens, gap, palette, size) {
22080
- const shapes = [];
22081
- const labels = [];
22106
+ function layoutFlows(spec, flows, screens, gap, palette) {
22082
22107
  const placed = [];
22083
22108
  const drawn = [];
22084
22109
  const tips = flows.flatMap(({ ends: ends2 }) => {
@@ -22097,20 +22122,16 @@ function flowLayer(spec, flows, screens, gap, palette, size) {
22097
22122
  return r;
22098
22123
  });
22099
22124
  const ends = routes.flatMap((r) => [r.points[0], r.points[r.points.length - 1]]);
22100
- flows.forEach(({ key }, i2) => {
22125
+ return flows.map(({ key }, i2) => {
22101
22126
  const r = routes[i2];
22102
22127
  const p = spec.elements[key].props ?? {};
22103
- const color = flowColor(p.color, palette);
22104
22128
  const start = p.start ?? "none", end = p.end ?? "arrow";
22105
22129
  const pts = [...r.points];
22106
22130
  pts[0] = add(pts[0], DIR[r.from], INSET[start]);
22107
22131
  pts[pts.length - 1] = add(pts[pts.length - 1], DIR[r.to], INSET[end]);
22108
- const { d: d2, at } = linePath(r, pts, p.line ?? "rounded");
22109
- shapes.push(
22110
- /* @__PURE__ */ jsx5("path", { d: d2, fill: "none", stroke: color, strokeWidth: 2, strokeLinejoin: "round", strokeLinecap: "round", ...p.dashed ? { strokeDasharray: "7 6" } : {} }, `${key}-line`),
22111
- marker(start, r.points[0], DIR[r.from], color, `${key}-start`),
22112
- marker(end, r.points[r.points.length - 1], DIR[r.to], color, `${key}-end`)
22113
- );
22132
+ const line = p.line ?? "rounded";
22133
+ const { d: d2, at } = linePath(r, pts, line);
22134
+ const out = { key, route: r, points: pts, d: d2, color: flowColor(p.color, palette), start, end, line, dashed: !!p.dashed };
22114
22135
  if (p.label) {
22115
22136
  const w2 = flowLabelWidth(String(p.label));
22116
22137
  const covers = (c2) => placed.filter((q) => c2.x - w2 / 2 < q.x + q.w && q.x < c2.x + w2 / 2 && c2.y - 14 < q.y + q.h && q.y < c2.y + 14).length + ends.filter((q) => Math.abs(q.x - c2.x) < w2 / 2 + 12 && Math.abs(q.y - c2.y) < 24).length;
@@ -22120,13 +22141,58 @@ function flowLayer(spec, flows, screens, gap, palette, size) {
22120
22141
  const c2 = at(t), n = covers(c2);
22121
22142
  if (n < best) [mid, best] = [c2, n];
22122
22143
  }
22123
- const top = mid.y - 12;
22124
- placed.push({ x: mid.x - w2 / 2, y: top, w: w2, h: 24 });
22144
+ const box = { x: mid.x - w2 / 2, y: mid.y - 12, w: w2, h: 24 };
22145
+ placed.push(box);
22146
+ out.label = { text: String(p.label), ...box };
22147
+ }
22148
+ return out;
22149
+ });
22150
+ }
22151
+ function flowPolyline(f) {
22152
+ const r = f.route, pts = f.points;
22153
+ const s0 = pts[0], e0 = pts[pts.length - 1];
22154
+ let out;
22155
+ if (r.lane == null && f.line === "straight") out = [s0, e0];
22156
+ else if (r.lane == null && f.line === "curved") {
22157
+ const { at } = linePath(r, pts, f.line);
22158
+ out = Array.from({ length: 25 }, (_, i2) => at(i2 / 24));
22159
+ } else {
22160
+ const radius = f.line === "curved" ? 40 : f.line === "rounded" ? 14 : 0;
22161
+ const q = simplify(pts);
22162
+ out = [q[0]];
22163
+ for (let i2 = 1; i2 < q.length; i2++) {
22164
+ const p = q[i2];
22165
+ if (radius > 0 && i2 < q.length - 1) {
22166
+ const prev = q[i2 - 1], next = q[i2 + 1];
22167
+ const rr2 = Math.min(radius, Math.hypot(p.x - prev.x, p.y - prev.y) / 2, Math.hypot(next.x - p.x, next.y - p.y) / 2);
22168
+ const into = { x: Math.sign(p.x - prev.x), y: Math.sign(p.y - prev.y) }, outd = { x: Math.sign(next.x - p.x), y: Math.sign(next.y - p.y) };
22169
+ const a = { x: p.x - into.x * rr2, y: p.y - into.y * rr2 }, b = { x: p.x + outd.x * rr2, y: p.y + outd.y * rr2 };
22170
+ for (let k = 0; k <= 6; k++) {
22171
+ const t = k / 6;
22172
+ out.push({ x: (1 - t) ** 2 * a.x + 2 * (1 - t) * t * p.x + t ** 2 * b.x, y: (1 - t) ** 2 * a.y + 2 * (1 - t) * t * p.y + t ** 2 * b.y });
22173
+ }
22174
+ } else out.push(p);
22175
+ }
22176
+ }
22177
+ const first = r.points[0], last = r.points[r.points.length - 1];
22178
+ return [first, ...out, last].filter((p, i2, all) => i2 === 0 || Math.hypot(p.x - all[i2 - 1].x, p.y - all[i2 - 1].y) >= 0.01);
22179
+ }
22180
+ function flowLayer(layout, size) {
22181
+ const shapes = [];
22182
+ const labels = [];
22183
+ for (const f of layout) {
22184
+ const r = f.route, { key, color } = f;
22185
+ shapes.push(
22186
+ /* @__PURE__ */ jsx5("path", { d: f.d, fill: "none", stroke: color, strokeWidth: 2, strokeLinejoin: "round", strokeLinecap: "round", ...f.dashed ? { strokeDasharray: "7 6" } : {} }, `${key}-line`),
22187
+ marker(f.start, r.points[0], DIR[r.from], color, `${key}-start`),
22188
+ marker(f.end, r.points[r.points.length - 1], DIR[r.to], color, `${key}-end`)
22189
+ );
22190
+ if (f.label) {
22125
22191
  labels.push(
22126
- /* @__PURE__ */ jsx5("div", { style: { position: "absolute", left: mid.x - w2 / 2, top, width: w2, height: 24, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: 12, backgroundColor: theme.paper, border: `1.5px solid ${color}`, color, fontSize: 12, fontWeight: 600 }, children: p.label }, `${key}-label`)
22192
+ /* @__PURE__ */ jsx5("div", { style: { position: "absolute", left: f.label.x, top: f.label.y, width: f.label.w, height: 24, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: 12, backgroundColor: theme.paper, border: `1.5px solid ${color}`, color, fontSize: 12, fontWeight: 600 }, children: f.label.text }, `${key}-label`)
22127
22193
  );
22128
22194
  }
22129
- });
22195
+ }
22130
22196
  return /* @__PURE__ */ jsxs3("div", { style: { position: "absolute", top: 0, left: 0, width: size.width, height: size.height, display: "flex" }, children: [
22131
22197
  /* @__PURE__ */ jsx5("svg", { width: size.width, height: size.height, viewBox: `0 0 ${size.width} ${size.height}`, style: { position: "absolute", top: 0, left: 0 }, children: shapes }),
22132
22198
  labels
@@ -22917,10 +22983,8 @@ async function renderWireframeSvg(spec, opts = {}) {
22917
22983
  if (issues.length) throw new SpecError(issues);
22918
22984
  }
22919
22985
  const flowsOn = opts.flows !== false;
22920
- const { width, height, gap } = boardLayout(spec, { flows: opts.flows });
22921
- const board = spec.elements[spec.root];
22922
- if ((board.props ?? {}).gap == null && gap !== BOARD_GAP)
22923
- spec = { ...spec, elements: { ...spec.elements, [spec.root]: { ...board, props: { ...board.props, gap } } } };
22986
+ const { width, height } = boardLayout(spec, { flows: opts.flows });
22987
+ spec = withBoardGap(spec, opts.flows);
22924
22988
  const palette = paletteFor(spec.elements[spec.root]?.props?.accent);
22925
22989
  const registry2 = withPalette(palette);
22926
22990
  const draw = async (s, reg) => renderToSvg(s, { registry: reg, includeStandard: false, fonts: await loadFonts(), width, height });
@@ -22928,13 +22992,17 @@ async function renderWireframeSvg(spec, opts = {}) {
22928
22992
  const { anchors, boxes } = await measureAnchors(spec, flows?.measure ?? []);
22929
22993
  if (!anchors.length && !flows?.list.length) return draw(spec, registry2);
22930
22994
  const layers = [];
22931
- if (flows?.list.length) {
22932
- const resolved = flows.list.map(({ key, from, to: to2 }) => ({ key, ends: { from: flows.box(from, boxes) ?? flows.screenBox(from), to: flows.box(to2, boxes) ?? flows.screenBox(to2), fromScreen: flows.screenBox(from), toScreen: flows.screenBox(to2) } })).filter((f) => !!(f.ends.from && f.ends.to && f.ends.fromScreen && f.ends.toScreen));
22933
- layers.push(flowLayer(spec, resolved, flows.screens, flows.gap, palette, { width, height }));
22934
- }
22995
+ if (flows?.list.length) layers.push(flowLayer(layoutFlows(spec, flows.resolve(boxes), flows.screens, flows.gap, palette), { width, height }));
22935
22996
  if (anchors.length) layers.push(overlayLayer(spec, anchors, boxes, palette, registry2.Calendar));
22936
22997
  return draw(spec, withTopLayer(registry2, layers));
22937
22998
  }
22999
+ function withBoardGap(spec, flows) {
23000
+ const { gap } = boardLayout(spec, { flows });
23001
+ const board = spec.elements[spec.root];
23002
+ if ((board.props ?? {}).gap == null && gap !== BOARD_GAP)
23003
+ return { ...spec, elements: { ...spec.elements, [spec.root]: { ...board, props: { ...board.props, gap } } } };
23004
+ return spec;
23005
+ }
22938
23006
  function flowEnds(spec) {
22939
23007
  const els = spec.elements;
22940
23008
  const byId = /* @__PURE__ */ new Map();
@@ -22962,9 +23030,12 @@ function flowEnds(spec) {
22962
23030
  list,
22963
23031
  measure,
22964
23032
  screens: [...screenRects.values()],
22965
- screenBox: (key) => screenRects.get(screenOf(key) ?? ""),
22966
23033
  gap: (els[spec.root].props ?? {}).gap ?? BOARD_GAP,
22967
- box: (key, boxes) => els[key].type === "Screen" ? screenRects.get(key) : boxes[key]
23034
+ resolve(boxes) {
23035
+ const box = (key) => els[key].type === "Screen" ? screenRects.get(key) : boxes[key];
23036
+ const screenBox = (key) => screenRects.get(screenOf(key) ?? "");
23037
+ return list.map(({ key, from, to: to2 }) => ({ key, ends: { from: box(from) ?? screenBox(from), to: box(to2) ?? screenBox(to2), fromScreen: screenBox(from), toScreen: screenBox(to2) } })).filter((f) => !!(f.ends.from && f.ends.to && f.ends.fromScreen && f.ends.toScreen));
23038
+ }
22968
23039
  };
22969
23040
  }
22970
23041
  async function measureAnchors(spec, extra = []) {
@@ -23008,7 +23079,7 @@ function compileWireframe(source) {
23008
23079
  return true;
23009
23080
  });
23010
23081
  unique.sort((a, b) => a.line - b.line);
23011
- return { spec: parsed.spec, issues: unique };
23082
+ return { spec: parsed.spec, issues: unique, lines: parsed.lines };
23012
23083
  }
23013
23084
  function formatIssues(issues) {
23014
23085
  return issues.map((i2) => `line ${i2.line}: ${i2.message}`).join("\n");
@@ -23471,6 +23542,150 @@ function addStyles(doc) {
23471
23542
  doc.head.append(style);
23472
23543
  }
23473
23544
 
23545
+ // src/measure.ts
23546
+ var isFlow = (e) => e.type === "Flow";
23547
+ var COVERS_SCREEN = /* @__PURE__ */ new Set(["Modal", "Drawer"]);
23548
+ var OVERLAYS = /* @__PURE__ */ new Set(["Modal", "Drawer", "Toast"]);
23549
+ var CONTAINERS = new Set(Object.entries(componentDefinitions).filter(([, d2]) => d2.slots.length).map(([name]) => name));
23550
+ var BARS = /* @__PURE__ */ new Set(["NavBar", "TabBar"]);
23551
+ var toBox = (r) => ({ x: round(r.x), y: round(r.y), width: round(r.w), height: round(r.h) });
23552
+ var round = (n) => Math.round(n * 100) / 100;
23553
+ function clip(r, to2) {
23554
+ if (!to2) return r;
23555
+ const x3 = Math.max(r.x, to2.x), y = Math.max(r.y, to2.y);
23556
+ const w2 = Math.min(r.x + r.w, to2.x + to2.w) - x3, h2 = Math.min(r.y + r.h, to2.y + to2.h) - y;
23557
+ return w2 >= 0 && h2 >= 0 && (w2 > 0 || r.w === 0) && (h2 > 0 || r.h === 0) ? { x: x3, y, w: w2, h: h2 } : null;
23558
+ }
23559
+ async function measureElements(spec, lines, opts = {}) {
23560
+ upgradeSpec(spec);
23561
+ if (!opts.skipValidation) {
23562
+ const issues = checkSpec(spec);
23563
+ if (issues.length) throw new SpecError(issues);
23564
+ }
23565
+ const { width, height } = boardLayout(spec, { flows: opts.flows });
23566
+ spec = withBoardGap(spec, opts.flows);
23567
+ const els = spec.elements;
23568
+ const anchors = findAnchors(spec);
23569
+ const every = Object.keys(els).filter((k) => !["Board", "Screen", "Flow"].includes(els[k].type)).map((id) => ({ id, screen: id, kind: "tooltip", field: false }));
23570
+ const screens = Object.keys(els).filter((k) => els[k].type === "Screen");
23571
+ const { tagged, colors } = tagForMeasuring(spec, [...anchors, ...every], screens);
23572
+ const svg = await renderToSvg(tagged, { registry: withMarkers(withPalette(paletteFor())), includeStandard: false, fonts: await loadFonts(), width, height });
23573
+ const boxes = readMarkers(svg, colors);
23574
+ const { items } = boardLayout(spec, { flows: opts.flows });
23575
+ const laidOut = (els[spec.root].children ?? []).filter((k) => els[k]?.type === "Screen" || els[k]?.type === "Note");
23576
+ const frames = /* @__PURE__ */ new Map(), bands = /* @__PURE__ */ new Map();
23577
+ laidOut.forEach((k, i2) => {
23578
+ const it = items[i2];
23579
+ if (!it || els[k].type !== "Screen") return;
23580
+ frames.set(k, { x: it.x, y: it.y + LABEL_H, w: it.width, h: it.height - LABEL_H });
23581
+ bands.set(k, { x: it.x, y: it.y, w: it.width, h: LABEL_H });
23582
+ });
23583
+ const overlays = /* @__PURE__ */ new Map();
23584
+ for (const o2 of overlayBoxes(spec, anchors, boxes)) overlays.set(o2.id, [...overlays.get(o2.id) ?? [], o2.box]);
23585
+ const lineOf = (k) => k == null ? null : lines[k] ?? 0;
23586
+ const endLine = (k) => Math.max(lines[k] ?? 0, ...(els[k].children ?? []).filter((c2) => els[c2]).map(endLine));
23587
+ const labelOf = (k) => {
23588
+ const p = els[k].props ?? {};
23589
+ const v2 = p[PRIMARY_PROP[els[k].type] ?? ""];
23590
+ return typeof v2 === "string" ? v2 : void 0;
23591
+ };
23592
+ const out = [];
23593
+ const visit = (k, parent, screen, cut) => {
23594
+ const el2 = els[k];
23595
+ if (!el2 || el2.type === "Flow") return;
23596
+ const p = el2.props ?? {};
23597
+ const base = { line: lineOf(k), endLine: endLine(k), ...typeof p.id === "string" ? { id: p.id } : {}, type: el2.type, ...labelOf(k) != null ? { label: labelOf(k) } : {}, screenLine: lineOf(screen), parentLine: lineOf(parent) };
23598
+ let entry = null;
23599
+ if (el2.type === "Board") entry = { ...base, box: { x: 0, y: 0, width, height } };
23600
+ else if (el2.type === "Screen") {
23601
+ const frame = frames.get(k);
23602
+ if (frame) entry = { ...base, box: toBox(frame), labelBox: toBox(bands.get(k)) };
23603
+ } else {
23604
+ const r = boxes[k];
23605
+ const seen = r && clip(r, cut);
23606
+ if (seen) {
23607
+ const view = screen ? boxes[screen] ?? frames.get(screen) : void 0;
23608
+ const os3 = (overlays.get(k) ?? []).map((o2) => clip(o2, view)).filter((o2) => !!o2 && o2.w > 0 && o2.h > 0);
23609
+ entry = { ...base, box: toBox(seen), ...os3.length ? { overlays: os3.map(toBox) } : {}, ...COVERS_SCREEN.has(el2.type) ? { scrim: p.scrim ?? true } : {} };
23610
+ }
23611
+ }
23612
+ if (entry) out.push(entry);
23613
+ const inScreen = el2.type === "Screen" ? k : screen;
23614
+ const kids = el2.children ?? [];
23615
+ if (el2.type === "Screen") {
23616
+ const frame = frames.get(k) ?? null;
23617
+ const body = clip(boxes[`${k}#body`] ?? frame, frame);
23618
+ const over = (c2) => OVERLAYS.has(els[c2]?.type);
23619
+ for (const c2 of [...kids.filter((c3) => !over(c3)), ...kids.filter(over)]) visit(c2, k, k, BARS.has(els[c2]?.type) || over(c2) ? frame : body);
23620
+ } else {
23621
+ const inner = el2.type === "Drawer" && boxes[k] ? clip(boxes[k], cut) : cut;
23622
+ for (const c2 of kids) visit(c2, k, inScreen, inner);
23623
+ }
23624
+ };
23625
+ visit(spec.root, null, null, null);
23626
+ if (opts.flows !== false) {
23627
+ const flows = flowEnds(spec);
23628
+ const resolved = flows.resolve(boxes);
23629
+ const ends = new Map(flows.list.map((f) => [f.key, f]));
23630
+ layoutFlows(spec, resolved, flows.screens, flows.gap, paletteFor()).forEach((f) => {
23631
+ const p = els[f.key].props ?? {};
23632
+ const e = ends.get(f.key);
23633
+ out.push({
23634
+ line: lineOf(f.key),
23635
+ endLine: lineOf(f.key),
23636
+ type: "Flow",
23637
+ ...f.label ? { label: f.label.text } : {},
23638
+ from: String(p.from),
23639
+ to: String(p.to),
23640
+ fromLine: lineOf(e.from),
23641
+ toLine: lineOf(e.to),
23642
+ path: flowPolyline(f).map((q) => [round(q.x), round(q.y)]),
23643
+ ...f.label ? { labelBox: toBox(f.label) } : {}
23644
+ });
23645
+ });
23646
+ }
23647
+ return out;
23648
+ }
23649
+ var inside = (b, x3, y) => !!b && b.width > 0 && b.height > 0 && x3 >= b.x && x3 <= b.x + b.width && y >= b.y && y <= b.y + b.height;
23650
+ var center = (b) => [b.x + b.width / 2, b.y + b.height / 2];
23651
+ function distanceToPath(path, x3, y) {
23652
+ let best = Infinity;
23653
+ for (let i2 = 1; i2 < path.length; i2++) {
23654
+ const [ax, ay] = path[i2 - 1], [bx, by] = path[i2];
23655
+ const dx = bx - ax, dy = by - ay, len = dx * dx + dy * dy;
23656
+ const t = len ? Math.max(0, Math.min(1, ((x3 - ax) * dx + (y - ay) * dy) / len)) : 0;
23657
+ best = Math.min(best, Math.hypot(x3 - ax - t * dx, y - ay - t * dy));
23658
+ }
23659
+ return best;
23660
+ }
23661
+ var isContainer = (e) => CONTAINERS.has(e.type);
23662
+ function elementsAt(elements, x3, y, opts = {}) {
23663
+ const tolerance = opts.tolerance ?? 6;
23664
+ const order = new Map(elements.map((e, i2) => [e, i2]));
23665
+ const topFirst = (a, b) => order.get(b) - order.get(a);
23666
+ const covered = /* @__PURE__ */ new Set();
23667
+ const screens = elements.filter((e) => e.type === "Screen");
23668
+ const screenAround = (b) => screens.find((s) => inside(s.box, ...center(b)));
23669
+ for (const [i2, m2] of elements.entries()) {
23670
+ if (isFlow(m2) || !OVERLAYS.has(m2.type)) continue;
23671
+ const screen = screenAround(m2.box);
23672
+ if (!screen || !inside(m2.box, x3, y) && !(m2.scrim && inside(screen.box, x3, y))) continue;
23673
+ for (const e of elements.slice(0, i2)) if (!isFlow(e) && e.type !== "Screen" && e.type !== "Board" && screenAround(e.box) === screen) covered.add(e);
23674
+ }
23675
+ const owners = [], labels = [], leaves = [], lines = [], containers = [];
23676
+ for (const e of elements) {
23677
+ if (isFlow(e)) {
23678
+ if (inside(e.labelBox, x3, y)) labels.push(e);
23679
+ else if (distanceToPath(e.path, x3, y) <= tolerance) lines.push(e);
23680
+ } else if (e.overlays?.some((o2) => inside(o2, x3, y))) owners.push(e);
23681
+ else if (!covered.has(e) && (inside(e.box, x3, y) || inside(e.labelBox, x3, y))) (isContainer(e) ? containers : leaves).push(e);
23682
+ }
23683
+ return [owners, labels, leaves, lines, containers].flatMap((g2) => g2.sort(topFirst));
23684
+ }
23685
+ function elementsAtLine(elements, line) {
23686
+ return elements.filter((e) => e.line > 0 && e.line <= line && line <= e.endLine).sort((a, b) => b.line - a.line);
23687
+ }
23688
+
23474
23689
  // src/playground/language-data.ts
23475
23690
  function unwrap4(t) {
23476
23691
  let cur = t;
@@ -23539,11 +23754,14 @@ export {
23539
23754
  compileWireframe,
23540
23755
  componentDefinitions,
23541
23756
  decodeWireframe,
23757
+ elementsAt,
23758
+ elementsAtLine,
23542
23759
  encodeWireframe,
23543
23760
  formatIssues,
23544
23761
  printWireframeText as formatWireframe,
23545
23762
  languageData,
23546
23763
  mcpTools,
23764
+ measureElements,
23547
23765
  parseWireframeText,
23548
23766
  registry,
23549
23767
  renderAll,
@@ -6,7 +6,7 @@ import {
6
6
  componentDefinitions,
7
7
  iconNames,
8
8
  takesUniversalProps
9
- } from "./chunk-BSE346UI.js";
9
+ } from "./chunk-YOZFCNSK.js";
10
10
 
11
11
  // src/playground/language-data.ts
12
12
  function unwrap(t) {