@cardenelabs/dragon 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1754,6 +1754,135 @@ var \u90E8\u54C1\u306E\u7D44\u306E\u8868 = {
1754
1754
  }
1755
1755
  };
1756
1756
 
1757
+ // src/v05/input-table.generated.ts
1758
+ var \u3064\u307E\u307F\u306E\u8868 = {
1759
+ color: {
1760
+ \u5FC5\u9808: ["defaultValue"],
1761
+ \u6B04: {
1762
+ defaultValue: "\u6587\u5B57\u5217",
1763
+ label: "\u6587\u5B57\u5217"
1764
+ }
1765
+ },
1766
+ datetime: {
1767
+ \u5FC5\u9808: ["defaultValue"],
1768
+ \u6B04: {
1769
+ defaultValue: "\u6587\u5B57\u5217",
1770
+ label: "\u6587\u5B57\u5217"
1771
+ }
1772
+ },
1773
+ dropdown: {
1774
+ \u5FC5\u9808: ["options", "defaultValue"],
1775
+ \u6B04: {
1776
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1777
+ defaultValue: "\u6587\u5B57\u5217",
1778
+ label: "\u6587\u5B57\u5217"
1779
+ }
1780
+ },
1781
+ "multi-select": {
1782
+ \u5FC5\u9808: ["options", "defaultValues"],
1783
+ \u6B04: {
1784
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1785
+ defaultValues: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1786
+ label: "\u6587\u5B57\u5217"
1787
+ }
1788
+ },
1789
+ number: {
1790
+ \u5FC5\u9808: ["defaultValue"],
1791
+ \u6B04: {
1792
+ min: "\u6570",
1793
+ max: "\u6570",
1794
+ defaultValue: "\u6570",
1795
+ label: "\u6587\u5B57\u5217"
1796
+ }
1797
+ },
1798
+ radio: {
1799
+ \u5FC5\u9808: ["options", "defaultValue"],
1800
+ \u6B04: {
1801
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1802
+ defaultValue: "\u6587\u5B57\u5217",
1803
+ label: "\u6587\u5B57\u5217"
1804
+ }
1805
+ },
1806
+ range: {
1807
+ \u5FC5\u9808: ["min", "max", "defaultLo", "defaultHi"],
1808
+ \u6B04: {
1809
+ min: "\u6570",
1810
+ max: "\u6570",
1811
+ step: "\u6570",
1812
+ defaultLo: "\u6570",
1813
+ defaultHi: "\u6570",
1814
+ label: "\u6587\u5B57\u5217"
1815
+ }
1816
+ },
1817
+ slider: {
1818
+ \u5FC5\u9808: ["min", "max", "defaultValue"],
1819
+ \u6B04: {
1820
+ min: "\u6570",
1821
+ max: "\u6570",
1822
+ step: "\u6570",
1823
+ defaultValue: "\u6570",
1824
+ label: "\u6587\u5B57\u5217"
1825
+ }
1826
+ },
1827
+ stepper: {
1828
+ \u5FC5\u9808: ["defaultValue"],
1829
+ \u6B04: {
1830
+ min: "\u6570",
1831
+ max: "\u6570",
1832
+ step: "\u6570",
1833
+ defaultValue: "\u6570",
1834
+ label: "\u6587\u5B57\u5217"
1835
+ }
1836
+ },
1837
+ tabs: {
1838
+ \u5FC5\u9808: ["options", "defaultValue"],
1839
+ \u6B04: {
1840
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1841
+ defaultValue: "\u6587\u5B57\u5217",
1842
+ label: "\u6587\u5B57\u5217"
1843
+ }
1844
+ },
1845
+ text: {
1846
+ \u5FC5\u9808: ["defaultValue"],
1847
+ \u6B04: {
1848
+ defaultValue: "\u6587\u5B57\u5217",
1849
+ placeholder: "\u6587\u5B57\u5217",
1850
+ maxLength: "\u6570",
1851
+ label: "\u6587\u5B57\u5217"
1852
+ }
1853
+ },
1854
+ timeline: {
1855
+ \u5FC5\u9808: ["duration"],
1856
+ \u6B04: {
1857
+ duration: "\u6570",
1858
+ autoplay: "\u771F\u507D",
1859
+ loop: "\u771F\u507D",
1860
+ speeds: "\u6570\u306E\u4E26\u3073",
1861
+ defaultSpeedIdx: "\u6570",
1862
+ label: "\u6587\u5B57\u5217"
1863
+ }
1864
+ },
1865
+ toggle: {
1866
+ \u5FC5\u9808: ["defaultValue"],
1867
+ \u6B04: {
1868
+ defaultValue: "\u771F\u507D",
1869
+ label: "\u6587\u5B57\u5217"
1870
+ }
1871
+ },
1872
+ xypad: {
1873
+ \u5FC5\u9808: ["xMin", "xMax", "yMin", "yMax", "defaultX", "defaultY"],
1874
+ \u6B04: {
1875
+ xMin: "\u6570",
1876
+ xMax: "\u6570",
1877
+ yMin: "\u6570",
1878
+ yMax: "\u6570",
1879
+ defaultX: "\u6570",
1880
+ defaultY: "\u6570",
1881
+ label: "\u6587\u5B57\u5217"
1882
+ }
1883
+ }
1884
+ };
1885
+
1757
1886
  // src/v05/parser.ts
1758
1887
  var EDGE_SIDE_VALUES = ["top", "right", "bottom", "left"];
1759
1888
  var TOP_LEVEL_KEYS = [
@@ -1772,7 +1901,15 @@ var TOP_LEVEL_KEYS = [
1772
1901
  // 2 軸で仕分ける図の軸の名前 (#1251)
1773
1902
  "axes",
1774
1903
  // 値を見せる部品 (#1374)
1775
- "readouts"
1904
+ "readouts",
1905
+ // 読む人が動かすつまみ (#1389)
1906
+ "inputs",
1907
+ // つまみの値から決まる値 (#1391)
1908
+ "formulas",
1909
+ // 押下などの出来事で動く仕掛け (#1393)
1910
+ "events",
1911
+ // 巻き上げに応じて進む値 (#1393)
1912
+ "scrolls"
1776
1913
  ];
1777
1914
  var LANE_ID_ENTRY = /^([\p{L}\p{N}_-]+)\s*:\s*\{([^}]*)\}\s*$/u;
1778
1915
  function \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(\u884C) {
@@ -1810,6 +1947,39 @@ function \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(\u884C) {
1810
1947
  }
1811
1948
  return void 0;
1812
1949
  }
1950
+ function \u672B\u5C3E\u306E\u4E2D\u62EC\u5F27\u3092\u5207\u308A\u51FA\u3059(rest) {
1951
+ const t = rest.trimEnd();
1952
+ if (!t.endsWith("}")) return void 0;
1953
+ let \u6DF1\u3055 = 0;
1954
+ let \u5F15\u7528 = null;
1955
+ let \u76F4\u524D = null;
1956
+ let \u59CB = -1;
1957
+ for (let i = 0; i < t.length; i += 1) {
1958
+ const c = t[i];
1959
+ if (\u5F15\u7528 !== null) {
1960
+ if (\u5F15\u7528 === '"' && c === "\\" && i + 1 < t.length) {
1961
+ i += 1;
1962
+ continue;
1963
+ }
1964
+ if (c === \u5F15\u7528) \u5F15\u7528 = null;
1965
+ continue;
1966
+ }
1967
+ if ((c === '"' || c === "'") && (\u76F4\u524D === null || ":,{[".includes(\u76F4\u524D))) {
1968
+ \u5F15\u7528 = c;
1969
+ \u76F4\u524D = c;
1970
+ continue;
1971
+ }
1972
+ if (c === "{") {
1973
+ if (\u6DF1\u3055 === 0) \u59CB = i;
1974
+ \u6DF1\u3055 += 1;
1975
+ } else if (c === "}") {
1976
+ \u6DF1\u3055 -= 1;
1977
+ if (\u6DF1\u3055 === 0 && i === t.length - 1) return { \u524D: t.slice(0, \u59CB), \u4E2D\u8EAB: t.slice(\u59CB + 1, i) };
1978
+ }
1979
+ if (!/\s/u.test(c)) \u76F4\u524D = c;
1980
+ }
1981
+ return void 0;
1982
+ }
1813
1983
  function isTopLevelKey(key) {
1814
1984
  return TOP_LEVEL_KEYS.includes(key);
1815
1985
  }
@@ -1903,6 +2073,11 @@ function parseTextDslV05(src) {
1903
2073
  let viewport = void 0;
1904
2074
  let lanesMap = void 0;
1905
2075
  let readoutsList = void 0;
2076
+ let inputsList = void 0;
2077
+ let formulasList = void 0;
2078
+ let eventsList = void 0;
2079
+ let scrollsList = void 0;
2080
+ let scrollLines = /* @__PURE__ */ new Map();
1906
2081
  let groupsMap = void 0;
1907
2082
  let i = 0;
1908
2083
  while (i < lines.length) {
@@ -2162,6 +2337,112 @@ function parseTextDslV05(src) {
2162
2337
  i = next;
2163
2338
  continue;
2164
2339
  }
2340
+ if (head.key === "inputs") {
2341
+ if (head.value !== null && head.value.trim() !== "") {
2342
+ errors.push({
2343
+ line: line.no,
2344
+ message: "inputs \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2345
+ hint: "\u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `value: { kind: slider, min: 0, max: 100, defaultValue: 50 }` \u306E\u5F62\u3067\u4E26\u3079\u308B"
2346
+ });
2347
+ i += 1;
2348
+ continue;
2349
+ }
2350
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2351
+ inputsList = [];
2352
+ for (const it of items) {
2353
+ const m = \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(it.trimmed);
2354
+ if (m) {
2355
+ const \u8AAD\u3081\u305F = \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(m[0], m[1], it.no, errors);
2356
+ if (\u8AAD\u3081\u305F) inputsList.push(\u8AAD\u3081\u305F);
2357
+ } else {
2358
+ errors.push({
2359
+ line: it.no,
2360
+ message: `invalid input entry: "${it.trimmed}"`,
2361
+ hint: "use `id: { kind: slider, min: 0, max: 100, defaultValue: 50 }`"
2362
+ });
2363
+ }
2364
+ }
2365
+ i = next;
2366
+ continue;
2367
+ }
2368
+ if (head.key === "formulas") {
2369
+ if (head.value !== null && head.value.trim() !== "") {
2370
+ errors.push({
2371
+ line: line.no,
2372
+ message: "formulas \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2373
+ hint: '\u5F0F\u306B `,` \u304C\u5165\u308B\u305F\u3081\u3002 \u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `doubled: "input * 2"` \u306E\u5F62\u3067\u4E26\u3079\u308B'
2374
+ });
2375
+ i += 1;
2376
+ continue;
2377
+ }
2378
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2379
+ formulasList = [];
2380
+ for (const it of items) {
2381
+ const f = \u5F0F\u3068\u3057\u3066\u8AAD\u3080(it.trimmed.replace(/^-\s*/, ""), it.no, errors);
2382
+ if (f) formulasList.push(f);
2383
+ }
2384
+ i = next;
2385
+ continue;
2386
+ }
2387
+ if (head.key === "events") {
2388
+ if (head.value !== null && head.value.trim() !== "") {
2389
+ errors.push({
2390
+ line: line.no,
2391
+ message: "events \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2392
+ hint: "\u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `- { on: click, box: Button, handler: toggle }` \u306E\u5F62\u3067\u4E26\u3079\u308B"
2393
+ });
2394
+ i += 1;
2395
+ continue;
2396
+ }
2397
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2398
+ eventsList = [];
2399
+ for (const it of items) {
2400
+ const e = \u51FA\u6765\u4E8B\u3068\u3057\u3066\u8AAD\u3080(it.trimmed.replace(/^-\s*/, ""), it.no, errors);
2401
+ if (e) eventsList.push(e);
2402
+ }
2403
+ i = next;
2404
+ continue;
2405
+ }
2406
+ if (head.key === "scrolls") {
2407
+ if (head.value !== null && head.value.trim() !== "") {
2408
+ errors.push({
2409
+ line: line.no,
2410
+ message: "scrolls \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2411
+ hint: "\u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `intro: { start: 0.9, end: 0.1 }` \u306E\u5F62\u3067\u4E26\u3079\u308B"
2412
+ });
2413
+ i += 1;
2414
+ continue;
2415
+ }
2416
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2417
+ scrollsList = [];
2418
+ scrollLines = /* @__PURE__ */ new Map();
2419
+ for (const it of items) {
2420
+ const m = \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(it.trimmed);
2421
+ if (m) {
2422
+ const \u8AAD\u3081\u305F = \u5DFB\u304D\u4E0A\u3052\u3068\u3057\u3066\u8AAD\u3080(m[0], m[1], it.no, errors);
2423
+ if (\u8AAD\u3081\u305F) {
2424
+ if (scrollLines.has(\u8AAD\u3081\u305F.id)) {
2425
+ errors.push({
2426
+ line: it.no,
2427
+ message: `\u5DFB\u304D\u4E0A\u3052\u306E\u540D\u524D "${\u8AAD\u3081\u305F.id}" \u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059`,
2428
+ hint: "scrolls \u306E\u540D\u524D\u306F 1 \u5EA6\u3060\u3051\u66F8\u304F"
2429
+ });
2430
+ } else {
2431
+ scrollsList.push(\u8AAD\u3081\u305F);
2432
+ scrollLines.set(\u8AAD\u3081\u305F.id, it.no);
2433
+ }
2434
+ }
2435
+ } else {
2436
+ errors.push({
2437
+ line: it.no,
2438
+ message: `invalid scroll entry: "${it.trimmed}"`,
2439
+ hint: "use `id: { start: 0.9, end: 0.1, scrub: 1 }`"
2440
+ });
2441
+ }
2442
+ }
2443
+ i = next;
2444
+ continue;
2445
+ }
2165
2446
  if (head.key === "groups") {
2166
2447
  const { items, next } = collectIndentedList(lines, i + 1, line.indent);
2167
2448
  groupsMap = {};
@@ -2198,6 +2479,18 @@ function parseTextDslV05(src) {
2198
2479
  message: "type is required",
2199
2480
  hint: "add `type: sequence|flow|swimlane|er|state|topology|solidity|gantt|class|pie|c4|mind`"
2200
2481
  });
2482
+ const \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D = /* @__PURE__ */ new Set([
2483
+ ...(inputsList ?? []).map((input) => input.id),
2484
+ ...(formulasList ?? []).map((formula) => formula.id)
2485
+ ]);
2486
+ for (const scroll of scrollsList ?? []) {
2487
+ if (!\u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.has(scroll.id)) continue;
2488
+ errors.push({
2489
+ line: scrollLines.get(scroll.id) ?? 1,
2490
+ message: `\u5DFB\u304D\u4E0A\u3052\u306E\u540D\u524D "${scroll.id}" \u304C inputs \u307E\u305F\u306F formulas \u3068\u91CD\u306A\u3063\u3066\u3044\u307E\u3059`,
2491
+ hint: "inputs / formulas / scrolls \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
2492
+ });
2493
+ }
2201
2494
  if (errors.length > 0) return { ok: false, errors };
2202
2495
  return {
2203
2496
  ok: true,
@@ -2213,6 +2506,10 @@ function parseTextDslV05(src) {
2213
2506
  viewport,
2214
2507
  lanes: lanesMap,
2215
2508
  readouts: readoutsList,
2509
+ inputs: inputsList,
2510
+ formulas: formulasList,
2511
+ events: eventsList,
2512
+ scrolls: scrollsList,
2216
2513
  groups: groupsMap,
2217
2514
  pos: { line: 1 }
2218
2515
  }
@@ -2565,6 +2862,18 @@ function \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, \u63A5\u
2565
2862
  out[\u6B04] = n !== void 0 ? n : \u5024;
2566
2863
  } else if (\u5F62 === "\u6587\u5B57\u5217\u306E\u4E26\u3073") {
2567
2864
  out[\u6B04] = \u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2865
+ } else if (\u5F62 === "\u6570\u306E\u4E26\u3073") {
2866
+ const \u751F = \u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2867
+ const \u6570 = \u751F.map((x) => numberOrUndef(x));
2868
+ if (\u6570.some((n) => n === void 0)) {
2869
+ errors.push({
2870
+ line,
2871
+ message: `${\u63A5\u982D}${\u6B04} \u306B\u6570\u3067\u306A\u3044\u5024\u304C\u3042\u308A\u307E\u3059: "${\u5024}"`,
2872
+ hint: "`[0.5, 1, 2, 4]` \u306E\u5F62\u3067\u6570\u3060\u3051\u3092\u4E26\u3079\u308B"
2873
+ });
2874
+ } else {
2875
+ out[\u6B04] = \u6570;
2876
+ }
2568
2877
  } else if (\u5F62 === "\u7D44\u306E\u4E26\u3073") {
2569
2878
  const \u7D44 = \u7D44\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2570
2879
  if (\u7D44 !== void 0) out[\u6B04] = \u7D44;
@@ -2621,11 +2930,49 @@ function \u51FA\u3059\u6761\u4EF6\u3068\u3057\u3066\u8AAD\u3080(raw, line, error
2621
2930
  }
2622
2931
  return \u5024;
2623
2932
  }
2933
+ function \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(raw, \u63A5\u982D, line, errors) {
2934
+ if (raw === void 0) return void 0;
2935
+ const \u5024 = raw.trim();
2936
+ if (\u5024 === "") {
2937
+ errors.push({
2938
+ line,
2939
+ message: `${\u63A5\u982D}\u304C\u7A7A\u3067\u3059`,
2940
+ hint: '`{\u72B6\u614B\u306E\u540D\u524D}` \u304B\u6570\u3092\u66F8\u304F (\u4F8B `opacity: "{fade}"` / `opacity: 0.5`)'
2941
+ });
2942
+ return void 0;
2943
+ }
2944
+ const n = numberOrUndef(\u5024);
2945
+ return n !== void 0 ? n : \u5024;
2946
+ }
2947
+ function \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(raw, \u63A5\u982D, line, errors) {
2948
+ if (raw === void 0) return void 0;
2949
+ const \u5024 = raw.trim();
2950
+ if (\u5024 === "") {
2951
+ errors.push({
2952
+ line,
2953
+ message: `${\u63A5\u982D}\u304C\u7A7A\u3067\u3059`,
2954
+ hint: '`{\u72B6\u614B\u306E\u540D\u524D}` \u3092\u66F8\u304F (\u4F8B `wBind: "{barW}"`)'
2955
+ });
2956
+ return void 0;
2957
+ }
2958
+ return \u5024;
2959
+ }
2960
+ var \u5024\u306B\u8FFD\u968F\u3059\u308B\u7BB1\u306E\u6B04 = [
2961
+ "wBind",
2962
+ "hBind",
2963
+ "opacity",
2964
+ "renderOffsetX",
2965
+ "renderOffsetY"
2966
+ ];
2967
+ var \u7A7A\u3092\u77E5\u3089\u305B\u308B\u7BB1\u306E\u6B04 = new Set(\u5024\u306B\u8FFD\u968F\u3059\u308B\u7BB1\u306E\u6B04);
2968
+ function \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u8868, kind) {
2969
+ return Object.hasOwn(\u8868, kind) ? \u8868[kind] : void 0;
2970
+ }
2624
2971
  function \u56F3\u5F62\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
2625
2972
  const \u4E2D\u8EAB = raw.trim().replace(/^\{|\}$/g, "");
2626
2973
  const opts = parseInlineMapping(\u4E2D\u8EAB);
2627
2974
  const kind = (opts.kind ?? "").toLowerCase();
2628
- const \u5B9A\u7FA9 = \u56F3\u5F62\u306E\u8868[kind];
2975
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u56F3\u5F62\u306E\u8868, kind);
2629
2976
  if (\u5B9A\u7FA9 === void 0) {
2630
2977
  errors.push({
2631
2978
  line,
@@ -2641,7 +2988,7 @@ function \u56F3\u5F62\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
2641
2988
  function \u90E8\u54C1\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
2642
2989
  const opts = parseInlineMapping(raw);
2643
2990
  const kind = (opts.kind ?? "").toLowerCase();
2644
- const \u5B9A\u7FA9 = \u90E8\u54C1\u306E\u8868[kind];
2991
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u90E8\u54C1\u306E\u8868, kind);
2645
2992
  if (\u5B9A\u7FA9 === void 0) {
2646
2993
  errors.push({
2647
2994
  line,
@@ -2655,6 +3002,194 @@ function \u90E8\u54C1\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
2655
3002
  for (const \u6B04 of \u5B9A\u7FA9.\u5FC5\u9808) if (\u8AAD\u3081\u305F[\u6B04] === void 0) return void 0;
2656
3003
  return { id, kind, ...\u8AAD\u3081\u305F };
2657
3004
  }
3005
+ var EVENT_KINDS = [
3006
+ "click",
3007
+ "hover",
3008
+ "double-click",
3009
+ "long-press",
3010
+ "drag",
3011
+ "drop",
3012
+ "keydown",
3013
+ "focus",
3014
+ "blur"
3015
+ ];
3016
+ var EVENT_TARGET_KEYS = ["box", "lane", "arrow", "diagram"];
3017
+ function \u51FA\u6765\u4E8B\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
3018
+ const t = raw.trim();
3019
+ if (!t.startsWith("{") || !t.endsWith("}")) {
3020
+ errors.push({
3021
+ line,
3022
+ message: `\u51FA\u6765\u4E8B\u306E\u884C\u304C\u8AAD\u3081\u307E\u305B\u3093: "${t}"`,
3023
+ hint: "`- { on: click, box: Button, handler: toggle }` \u306E\u5F62\u3067\u66F8\u304F"
3024
+ });
3025
+ return void 0;
3026
+ }
3027
+ const opts = parseInlineMapping(t.slice(1, -1));
3028
+ for (const k of Object.keys(opts)) {
3029
+ if (k === "on" || k === "handler" || EVENT_TARGET_KEYS.includes(k))
3030
+ continue;
3031
+ errors.push({
3032
+ line,
3033
+ message: `\u51FA\u6765\u4E8B\u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${k}"`,
3034
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = on, handler, ${EVENT_TARGET_KEYS.join(", ")}`
3035
+ });
3036
+ return void 0;
3037
+ }
3038
+ const on = opts.on ?? "";
3039
+ if (!EVENT_KINDS.includes(on)) {
3040
+ errors.push({
3041
+ line,
3042
+ message: `\u51FA\u6765\u4E8B\u306E\u7A2E\u985E\u304C\u8AAD\u3081\u307E\u305B\u3093: "${on}"`,
3043
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${EVENT_KINDS.join(", ")}`
3044
+ });
3045
+ return void 0;
3046
+ }
3047
+ const handlerId = (opts.handler ?? "").trim();
3048
+ if (handlerId === "") {
3049
+ errors.push({
3050
+ line,
3051
+ message: "\u51FA\u6765\u4E8B\u306E handler \u304C\u7A7A\u3067\u3059",
3052
+ hint: "`handler: toggle-active` \u306E\u3088\u3046\u306B\u3001\u547C\u3073\u51FA\u3059\u4ED5\u639B\u3051\u306E\u540D\u524D\u3092\u66F8\u304F"
3053
+ });
3054
+ return void 0;
3055
+ }
3056
+ const \u66F8\u3044\u305F\u76F8\u624B = EVENT_TARGET_KEYS.filter((k) => opts[k] !== void 0);
3057
+ if (\u66F8\u3044\u305F\u76F8\u624B.length !== 1) {
3058
+ errors.push({
3059
+ line,
3060
+ message: \u66F8\u3044\u305F\u76F8\u624B.length === 0 ? "\u51FA\u6765\u4E8B\u306E\u76F8\u624B\u304C\u66F8\u304B\u308C\u3066\u3044\u307E\u305B\u3093" : `\u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092 2 \u3064\u4EE5\u4E0A\u66F8\u3044\u3066\u3044\u307E\u3059: ${\u66F8\u3044\u305F\u76F8\u624B.join(", ")}`,
3061
+ hint: `${EVENT_TARGET_KEYS.join(" / ")} \u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u3092\u66F8\u304F`
3062
+ });
3063
+ return void 0;
3064
+ }
3065
+ const \u9375 = \u66F8\u3044\u305F\u76F8\u624B[0];
3066
+ const \u5024 = (opts[\u9375] ?? "").trim();
3067
+ let target;
3068
+ if (\u9375 === "diagram") {
3069
+ if (\u5024 !== "true") {
3070
+ errors.push({
3071
+ line,
3072
+ message: `\u51FA\u6765\u4E8B\u306E diagram \u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u5024}"`,
3073
+ hint: "\u56F3\u5168\u4F53\u3092\u6307\u3059\u6642\u306F `diagram: true` \u3068\u66F8\u304F"
3074
+ });
3075
+ return void 0;
3076
+ }
3077
+ target = { kind: "diagram" };
3078
+ } else if (\u9375 === "arrow") {
3079
+ const m = \u5024.split("->");
3080
+ if (m.length !== 2 || m[0].trim() === "" || m[1].trim() === "") {
3081
+ errors.push({
3082
+ line,
3083
+ message: `\u51FA\u6765\u4E8B\u306E\u77E2\u5370\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u5024}"`,
3084
+ hint: "`arrow: A -> B` \u306E\u5F62\u3067\u3001\u77E2\u5370\u306E\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
3085
+ });
3086
+ return void 0;
3087
+ }
3088
+ target = { kind: "edge", from: stripQuotes(m[0].trim()), to: stripQuotes(m[1].trim()) };
3089
+ } else {
3090
+ if (\u5024 === "") {
3091
+ errors.push({
3092
+ line,
3093
+ message: `\u51FA\u6765\u4E8B\u306E ${\u9375} \u304C\u7A7A\u3067\u3059`,
3094
+ hint: "\u6307\u3059\u76F8\u624B\u306E\u540D\u524D\u3092\u66F8\u304F"
3095
+ });
3096
+ return void 0;
3097
+ }
3098
+ target = { kind: \u9375 === "box" ? "node" : "lane", name: stripQuotes(\u5024) };
3099
+ }
3100
+ return { event: on, target, handlerId, pos: { line } };
3101
+ }
3102
+ var SCROLL_VALUE_KINDS = {
3103
+ start: "\u6570",
3104
+ end: "\u6570",
3105
+ scrub: "\u6570"
3106
+ };
3107
+ function \u5DFB\u304D\u4E0A\u3052\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
3108
+ if (!isValueName(id)) {
3109
+ errors.push({ line, ...valueNameIssue(id) });
3110
+ return void 0;
3111
+ }
3112
+ const opts = parseInlineMapping(raw);
3113
+ const \u4F7F\u3048\u308B = [...Object.keys(SCROLL_VALUE_KINDS), "label"];
3114
+ for (const k of Object.keys(opts)) {
3115
+ if (\u4F7F\u3048\u308B.includes(k)) continue;
3116
+ errors.push({
3117
+ line,
3118
+ message: `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${k}"`,
3119
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")}`
3120
+ });
3121
+ return void 0;
3122
+ }
3123
+ const \u6570 = \u8868\u3067\u8AAD\u3080(SCROLL_VALUE_KINDS, opts, `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E `, line, errors);
3124
+ for (const \u6B04 of ["start", "end", "scrub"]) {
3125
+ const \u5024 = \u6570[\u6B04];
3126
+ if (\u5024 === void 0 || \u5024 >= 0 && \u5024 <= 1) continue;
3127
+ errors.push({
3128
+ line,
3129
+ message: `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E ${\u6B04} \u306F 0 \u304B\u3089 1 \u306E\u9593\u3067\u66F8\u304D\u307E\u3059: "${\u5024}"`,
3130
+ hint: "0 \u306F\u753B\u9762\u306E\u4E0A\u7AEF\u307E\u305F\u306F\u6BB5\u968E\u7684\u306A\u8FFD\u968F\u30011 \u306F\u4E0B\u7AEF\u307E\u305F\u306F\u9023\u7D9A\u8FFD\u968F"
3131
+ });
3132
+ }
3133
+ return {
3134
+ id,
3135
+ ...\u6570.start !== void 0 ? { start: \u6570.start } : {},
3136
+ ...\u6570.end !== void 0 ? { end: \u6570.end } : {},
3137
+ ...\u6570.scrub !== void 0 ? { scrub: \u6570.scrub } : {},
3138
+ ...opts.label !== void 0 ? { label: opts.label } : {}
3139
+ };
3140
+ }
3141
+ function \u5F0F\u3068\u3057\u3066\u8AAD\u3080(\u884C, line, errors) {
3142
+ const c = \u884C.indexOf(":");
3143
+ if (c < 0) {
3144
+ errors.push({
3145
+ line,
3146
+ message: `\u5F0F\u306E\u884C\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u884C}"`,
3147
+ hint: '`\u540D\u524D: "\u5F0F"` \u306E\u5F62\u3067\u66F8\u304F (\u4F8B `doubled: "input * 2"`)'
3148
+ });
3149
+ return void 0;
3150
+ }
3151
+ const \u540D\u524D = \u884C.slice(0, c).trim();
3152
+ const \u5F0F = stripQuotes(\u884C.slice(c + 1).trim());
3153
+ if (!isValueName(\u540D\u524D)) {
3154
+ errors.push({ line, ...valueNameIssue(\u540D\u524D) });
3155
+ return void 0;
3156
+ }
3157
+ if (\u5F0F === "") {
3158
+ errors.push({
3159
+ line,
3160
+ message: `\u5F0F "${\u540D\u524D}" \u304C\u7A7A\u3067\u3059`,
3161
+ hint: '`doubled: "input * 2"` \u306E\u3088\u3046\u306B\u5F0F\u3092\u66F8\u304F'
3162
+ });
3163
+ return void 0;
3164
+ }
3165
+ try {
3166
+ cdl.parseFormula(\u5F0F);
3167
+ } catch (e) {
3168
+ errors.push({
3169
+ line,
3170
+ message: `\u5F0F "${\u540D\u524D}" \u3092\u8AAD\u3081\u307E\u305B\u3093: ${e.message}`,
3171
+ hint: "\u4F7F\u3048\u308B\u306E\u306F\u56DB\u5247\u3068\u62EC\u5F27\u3001\u6BD4\u8F03\u3001\u4E09\u9805 (`a > 1 ? 2 : 3`)\u3001`Math.min` \u306A\u3069\u306E\u95A2\u6570"
3172
+ });
3173
+ return void 0;
3174
+ }
3175
+ return { id: \u540D\u524D, expression: \u5F0F, pos: { line } };
3176
+ }
3177
+ function \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
3178
+ const opts = parseInlineMapping(raw);
3179
+ const kind = (opts.kind ?? "").toLowerCase();
3180
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u3064\u307E\u307F\u306E\u8868, kind);
3181
+ if (\u5B9A\u7FA9 === void 0) {
3182
+ errors.push({
3183
+ line,
3184
+ message: `\u3064\u307E\u307F\u306E\u7A2E\u985E\u304C\u8AAD\u3081\u307E\u305B\u3093: "${opts.kind ?? ""}"`,
3185
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${Object.keys(\u3064\u307E\u307F\u306E\u8868).join(", ")}`
3186
+ });
3187
+ return void 0;
3188
+ }
3189
+ const \u8AAD\u3081\u305F = \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, `\u3064\u307E\u307F ${id} \u306E `, line, errors);
3190
+ for (const \u6B04 of \u5B9A\u7FA9.\u5FC5\u9808) if (\u8AAD\u3081\u305F[\u6B04] === void 0) return void 0;
3191
+ return { id, kind, ...\u8AAD\u3081\u305F };
3192
+ }
2658
3193
  var ACTOR_NODE_VALUE_KINDS = {
2659
3194
  posX: "\u6570",
2660
3195
  posY: "\u6570",
@@ -2854,6 +3389,7 @@ function applyContinuationLines(actor, rest, errors) {
2854
3389
  const scaleLines = /* @__PURE__ */ new Map();
2855
3390
  const \u56F3\u7A2E\u3054\u3068\u306E\u6B04 = /* @__PURE__ */ new Map();
2856
3391
  const unknownKeys = [];
3392
+ const \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024 = /* @__PURE__ */ new Map();
2857
3393
  for (const ln of rest) {
2858
3394
  const idx = ln.trimmed.indexOf(":");
2859
3395
  if (idx < 0) continue;
@@ -2866,7 +3402,7 @@ function applyContinuationLines(actor, rest, errors) {
2866
3402
  unknownKeys.push({ key, line: ln.no });
2867
3403
  continue;
2868
3404
  }
2869
- if (!raw) continue;
3405
+ if (!raw && !\u7A7A\u3092\u77E5\u3089\u305B\u308B\u7BB1\u306E\u6B04.has(key)) continue;
2870
3406
  if (COLOR_KEYS.has(key)) {
2871
3407
  const { tone, hex } = splitColorValue(raw);
2872
3408
  if (tone) out.tone = tone;
@@ -2905,6 +3441,23 @@ function applyContinuationLines(actor, rest, errors) {
2905
3441
  case "\u984C":
2906
3442
  out.title = stripQuotes(raw);
2907
3443
  break;
3444
+ /*
3445
+ * 値に追随する 5 欄 (#1392)。 日本語の別名は置かない = 描画側の欄名がそのまま
3446
+ * 状態の名前と並ぶ場所なので、英字 1 種に絞って書き方の揺れを作らない。
3447
+ *
3448
+ * **ここでは読まずに書かれた字だけを控える**。 見本 (parts) では同じ名前が状態の
3449
+ * 上書きになり、中括弧の形は生の字を `coerceStateValue` に通す。 ここで先に読むと
3450
+ * `wBind: 120` が中括弧では数、縦に並べると文字列になって書き方で割れる。
3451
+ * 見本かどうかは `kind` で決まり、それが後ろの行に書かれることがあるため、
3452
+ * 全行を読み終えてから振り分ける。
3453
+ */
3454
+ case "wBind":
3455
+ case "hBind":
3456
+ case "opacity":
3457
+ case "renderOffsetX":
3458
+ case "renderOffsetY":
3459
+ \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024.set(key, { \u5024: stripQuotes(raw), line: ln.no });
3460
+ break;
2908
3461
  case "rows":
2909
3462
  case "\u884C":
2910
3463
  out.rows = raw.replace(/^\[|\]$/g, "").split(/,(?![^[]*\])/).map((x) => stripQuotes(x.trim())).filter(Boolean);
@@ -2992,9 +3545,20 @@ function applyContinuationLines(actor, rest, errors) {
2992
3545
  else out.end = v;
2993
3546
  }
2994
3547
  if (out.partId !== void 0) {
3548
+ for (const [\u6B04, { \u5024 }] of \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024) {
3549
+ state[\u6B04] = coerceStateValue(\u5024);
3550
+ touchedState = true;
3551
+ }
2995
3552
  if (touchedState) out.stateOverride = state;
2996
3553
  return out;
2997
3554
  }
3555
+ for (const [\u6B04, { \u5024, line }] of \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024) {
3556
+ if (\u6B04 === "wBind" || \u6B04 === "hBind") {
3557
+ out[\u6B04] = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(\u5024, `\u7BB1\u306E ${\u6B04} `, line, errors);
3558
+ } else if (\u6B04 === "opacity" || \u6B04 === "renderOffsetX" || \u6B04 === "renderOffsetY") {
3559
+ out[\u6B04] = \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(\u5024, `\u7BB1\u306E ${\u6B04} `, line, errors);
3560
+ }
3561
+ }
2998
3562
  for (const u of unknownKeys) {
2999
3563
  errors.push({
3000
3564
  line: u.line,
@@ -3023,6 +3587,12 @@ var ACTOR_ITEM_KEYS = /* @__PURE__ */ new Set([
3023
3587
  // 箱に出す題 (#1381)
3024
3588
  "title",
3025
3589
  "\u984C",
3590
+ // 値に追随する 5 欄 (#1392)
3591
+ "wBind",
3592
+ "hBind",
3593
+ "opacity",
3594
+ "renderOffsetX",
3595
+ "renderOffsetY",
3026
3596
  "\u4F4D\u7F6E",
3027
3597
  "pos",
3028
3598
  "posX",
@@ -3274,6 +3844,12 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
3274
3844
  "visibleIf",
3275
3845
  // 箱に出す題 (#1381)。 名前と切り離して書ける
3276
3846
  "title",
3847
+ // 値に追随する 5 欄 (#1392)
3848
+ "wBind",
3849
+ "hBind",
3850
+ "opacity",
3851
+ "renderOffsetX",
3852
+ "renderOffsetY",
3277
3853
  // 倍率は別経路 (`reportScaleOnNonPart`) が知らせる。 ここでも読める扱いにしないと
3278
3854
  // 同じ名前で 2 度知らせることになる
3279
3855
  "scale",
@@ -3281,12 +3857,24 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
3281
3857
  // 英語が読める欄の日本語別名 (#1301)。 一覧は `INLINE_ACTOR_ALIASES` が持つ
3282
3858
  ...Object.keys(INLINE_ACTOR_ALIASES)
3283
3859
  ]);
3860
+ var EDGE_BIND_INLINE_READERS = {
3861
+ widthBind: (v) => v,
3862
+ strokeBind: (v) => v,
3863
+ dashOffsetBind: (v) => v
3864
+ };
3284
3865
  var FLOW_INLINE_READERS = {
3285
3866
  sub: (v) => v,
3286
3867
  guard: (v) => v,
3287
3868
  cardinality: (v) => v,
3288
3869
  // 矢印がどの辺から出るか (#1385)。 描画側は 4 方向を取り、書かなければ自動で選ぶ
3289
3870
  side: (v) => v !== void 0 && EDGE_SIDE_VALUES.includes(v) ? v : void 0,
3871
+ /*
3872
+ * 矢印を値に追随させる 3 欄 (#1396)。 箱の `wBind` (#1392) と同じく文字列だけを取る。
3873
+ *
3874
+ * ここでは字をそのまま通し、空かどうかは呼出側が知らせる (表の読み手は行番号を
3875
+ * 持たないため、知らせを出せる場所で見る)。
3876
+ */
3877
+ ...EDGE_BIND_INLINE_READERS,
3290
3878
  // 数と真偽の欄は `FLOW_INLINE_VALUE_KINDS` の表が読む (#1306)。 ここでは名前だけを持つ =
3291
3879
  // 読める欄の一覧 (`FLOW_INLINE_KEYS`) は本表から導くため、載せないと欄ごと消える
3292
3880
  labelOffsetX: null,
@@ -3352,6 +3940,13 @@ function parseActor2(line, errors) {
3352
3940
  visibleIf: isPart ? void 0 : \u51FA\u3059\u6761\u4EF6\u3068\u3057\u3066\u8AAD\u3080(opts.visibleIf, line.no, errors),
3353
3941
  // 箱に出す題 (#1381)。 空文字も意味を持つ (題を出さない箱) ため undefined と分ける
3354
3942
  title: isPart ? void 0 : opts.title,
3943
+ // 値に追随する 5 欄 (#1392)。 図形や出す条件と同じく、パーツでは状態の上書きとして
3944
+ // 意味を持つため横取りしない
3945
+ wBind: isPart ? void 0 : \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(opts.wBind, "\u7BB1\u306E wBind ", line.no, errors),
3946
+ hBind: isPart ? void 0 : \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(opts.hBind, "\u7BB1\u306E hBind ", line.no, errors),
3947
+ opacity: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.opacity, "\u7BB1\u306E opacity ", line.no, errors),
3948
+ renderOffsetX: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.renderOffsetX, "\u7BB1\u306E renderOffsetX ", line.no, errors),
3949
+ renderOffsetY: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.renderOffsetY, "\u7BB1\u306E renderOffsetY ", line.no, errors),
3355
3950
  ...\u8868\u3067\u8AAD\u3080(ACTOR_INLINE_VALUE_KINDS, opts, "\u7BB1\u306E ", line.no, errors),
3356
3951
  // parts では `tone` を状態の上書きとして従来から使えるため、 色として横取りしない
3357
3952
  tone: isPart ? void 0 : resolveTone(opts.tone),
@@ -3410,10 +4005,17 @@ function parseFlowStep(line, no, errors) {
3410
4005
  let tone;
3411
4006
  let style;
3412
4007
  const \u4E2D\u62EC\u5F27 = {};
3413
- const mapMatch = rest.match(/\s*\{([^}]*)\}\s*$/);
4008
+ const \u584A = \u672B\u5C3E\u306E\u4E2D\u62EC\u5F27\u3092\u5207\u308A\u51FA\u3059(rest);
3414
4009
  let \u6570\u3068\u771F\u507D;
3415
- if (mapMatch) {
3416
- const opts = parseInlineMapping(mapMatch[1]);
4010
+ if (\u584A) {
4011
+ const opts = parseInlineMapping(\u584A.\u4E2D\u8EAB);
4012
+ for (const field of splitInlineFields(\u584A.\u4E2D\u8EAB)) {
4013
+ const idx = field.indexOf(":");
4014
+ if (idx < 0) continue;
4015
+ const key = field.slice(0, idx).trim();
4016
+ if (!Object.hasOwn(EDGE_BIND_INLINE_READERS, key)) continue;
4017
+ opts[key] = stripQuotes(field.slice(idx + 1).trim());
4018
+ }
3417
4019
  for (const k of FLOW_INLINE_KEYS) {
3418
4020
  const \u8AAD\u307F\u624B = FLOW_INLINE_READERS[k];
3419
4021
  if (\u8AAD\u307F\u624B === null) continue;
@@ -3427,12 +4029,30 @@ function parseFlowStep(line, no, errors) {
3427
4029
  });
3428
4030
  }
3429
4031
  \u6570\u3068\u771F\u507D = \u8868\u3067\u8AAD\u3080(FLOW_INLINE_VALUE_KINDS, opts, "\u77E2\u5370\u306E ", line.no, errors);
3430
- rest = rest.slice(0, mapMatch.index ?? 0).trim();
4032
+ rest = \u584A.\u524D.trim();
3431
4033
  }
3432
4034
  const sub = \u4E2D\u62EC\u5F27.sub;
3433
4035
  const guard = \u4E2D\u62EC\u5F27.guard;
3434
4036
  const cardinality = \u4E2D\u62EC\u5F27.cardinality;
3435
4037
  const side = \u4E2D\u62EC\u5F27.side;
4038
+ const widthBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4039
+ \u4E2D\u62EC\u5F27.widthBind,
4040
+ "\u77E2\u5370\u306E widthBind ",
4041
+ line.no,
4042
+ errors
4043
+ );
4044
+ const strokeBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4045
+ \u4E2D\u62EC\u5F27.strokeBind,
4046
+ "\u77E2\u5370\u306E strokeBind ",
4047
+ line.no,
4048
+ errors
4049
+ );
4050
+ const dashOffsetBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4051
+ \u4E2D\u62EC\u5F27.dashOffsetBind,
4052
+ "\u77E2\u5370\u306E dashOffsetBind ",
4053
+ line.no,
4054
+ errors
4055
+ );
3436
4056
  const labelOffsetX = \u6570\u3068\u771F\u507D?.labelOffsetX;
3437
4057
  const labelOffsetY = \u6570\u3068\u771F\u507D?.labelOffsetY;
3438
4058
  const overlay = \u6570\u3068\u771F\u507D?.overlay;
@@ -3484,6 +4104,9 @@ function parseFlowStep(line, no, errors) {
3484
4104
  guard,
3485
4105
  cardinality,
3486
4106
  side,
4107
+ widthBind,
4108
+ strokeBind,
4109
+ dashOffsetBind,
3487
4110
  labelOffsetX,
3488
4111
  labelOffsetY,
3489
4112
  overlay,
@@ -4041,14 +4664,22 @@ var PAINT_KEYS = /* @__PURE__ */ new Set([
4041
4664
  var SAFE_PAINT = "none";
4042
4665
  function stripExternalPaint(diagram2) {
4043
4666
  const stripped = [];
4044
- walk(diagram2, "", false, stripped);
4667
+ walk(diagram2, "", false, stripped, false);
4045
4668
  return stripped;
4046
4669
  }
4047
- function walk(node, path, inStateValue, out) {
4670
+ var INPUT_VALUE_KEYS = /* @__PURE__ */ new Set(["defaultvalue", "defaultvalues", "options"]);
4671
+ function walk(node, path, inStateValue, out, inInputs) {
4048
4672
  if (node === null || typeof node !== "object") return;
4049
4673
  if (Array.isArray(node)) {
4050
4674
  for (let i = 0; i < node.length; i++) {
4051
- walk(node[i], `${path}[${i}]`, inStateValue, out);
4675
+ const here = `${path}[${i}]`;
4676
+ const value = node[i];
4677
+ if (inStateValue && typeof value === "string" && pointsOutside(value)) {
4678
+ node[i] = SAFE_PAINT;
4679
+ out.push({ path: here, value });
4680
+ } else {
4681
+ walk(value, here, inStateValue, out, inInputs);
4682
+ }
4052
4683
  }
4053
4684
  return;
4054
4685
  }
@@ -4056,7 +4687,8 @@ function walk(node, path, inStateValue, out) {
4056
4687
  for (const [key, value] of Object.entries(obj)) {
4057
4688
  const here = path ? `${path}.${key}` : key;
4058
4689
  const lower = key.toLowerCase();
4059
- const nextInState = inStateValue || lower === "states" || lower === "sets" || lower === "tweens";
4690
+ const nextInState = inStateValue || lower === "states" || lower === "sets" || lower === "tweens" || inInputs && INPUT_VALUE_KEYS.has(lower);
4691
+ const nextInInputs = inInputs || lower === "inputs";
4060
4692
  if (typeof value === "string") {
4061
4693
  const isPaint = PAINT_KEYS.has(lower) || nextInState && (lower === "initial" || lower === "to" || lower === "from" || !isReservedStateKey(lower));
4062
4694
  if (isPaint && pointsOutside(value)) {
@@ -4065,7 +4697,7 @@ function walk(node, path, inStateValue, out) {
4065
4697
  }
4066
4698
  continue;
4067
4699
  }
4068
- walk(value, here, nextInState, out);
4700
+ walk(value, here, nextInState, out, nextInInputs);
4069
4701
  }
4070
4702
  }
4071
4703
  function isReservedStateKey(lowerKey) {
@@ -4083,7 +4715,15 @@ function countDocElements(doc) {
4083
4715
  );
4084
4716
  return doc.actors.length + doc.flow.length + phases.length + phaseChildren + (doc.animate?.states.length ?? 0) + (doc.values?.length ?? 0) + // 値を見せる部品も描画時に 1 widget ずつ展開される (#1374)。 数えないと、 actors が
4085
4717
  // 少ないまま readouts だけを大量に並べた入力が組み立て前の上限をすり抜ける。
4086
- (doc.readouts?.length ?? 0) + (doc.groups ? Object.keys(doc.groups).length : 0) + (doc.lanes ? Object.keys(doc.lanes).length : 0);
4718
+ (doc.readouts?.length ?? 0) + // 読む人が動かすつまみも 1 widget ずつ展開される (#1389) readouts と同じ上限で守る。
4719
+ (doc.inputs?.length ?? 0) + /*
4720
+ * 式 (#1391) と、押下 / 巻き上げ (#1393) も数える。
4721
+ *
4722
+ * **図の側 (`countDiagramElements`) は既に数えている**。 記法側だけ数えないと、
4723
+ * 箱が少ないままこれらを大量に並べた入力が組み立て前の上限をすり抜け、
4724
+ * 組み立て終わってから (= 時間をかけてから) 図の側で弾かれる。
4725
+ */
4726
+ (doc.formulas?.length ?? 0) + (doc.events?.length ?? 0) + (doc.scrolls?.length ?? 0) + (doc.groups ? Object.keys(doc.groups).length : 0) + (doc.lanes ? Object.keys(doc.lanes).length : 0);
4087
4727
  }
4088
4728
  function countDiagramElements(diagram2) {
4089
4729
  const phases = Array.isArray(diagram2.phases) ? diagram2.phases : [];
@@ -4114,6 +4754,21 @@ function describeOversizeSource(src) {
4114
4754
  }
4115
4755
 
4116
4756
  // src/compile.ts
4757
+ var \u8A18\u6CD5\u3060\u3051\u306E\u7A2E\u985E\u306E\u8AAD\u307F\u66FF\u3048 = {
4758
+ entity: "storage",
4759
+ state: "card",
4760
+ contract: "card",
4761
+ proxy: "card",
4762
+ library: "card",
4763
+ interface: "card",
4764
+ eoa: "person",
4765
+ multisig: "signer"
4766
+ };
4767
+ function \u63CF\u3051\u308B\u7A2E\u5225(kind) {
4768
+ if (kind === void 0) return "actor";
4769
+ const \u8AAD\u307F\u66FF\u3048\u5148 = \u8A18\u6CD5\u3060\u3051\u306E\u7A2E\u985E\u306E\u8AAD\u307F\u66FF\u3048[kind];
4770
+ return \u8AAD\u307F\u66FF\u3048\u5148 ?? kind;
4771
+ }
4117
4772
  function compileToCdl(doc, opts) {
4118
4773
  const oversize = describeOversize({ elements: countDocElements(doc), bytes: 0 });
4119
4774
  if (oversize) throw new Error(oversize);
@@ -4229,6 +4884,100 @@ function compileToCdl(doc, opts) {
4229
4884
  );
4230
4885
  merged.readouts = [...merged.readouts ?? [], ...ownReadouts];
4231
4886
  }
4887
+ if (doc.inputs && doc.inputs.length > 0) {
4888
+ const ownInputs = doc.inputs.map(
4889
+ (input) => deepRewriteStrings(input, (value) => value)
4890
+ );
4891
+ merged.inputs = [...merged.inputs ?? [], ...ownInputs];
4892
+ }
4893
+ if (doc.formulas && doc.formulas.length > 0) {
4894
+ const ownFormulas = doc.formulas.map((formula) => ({
4895
+ id: formula.id,
4896
+ expression: formula.expression,
4897
+ line: formula.pos?.line ?? 0
4898
+ }));
4899
+ const \u3064\u307E\u307F = new Map((merged.inputs ?? []).map((input) => [input.id, input]));
4900
+ const \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F = new Set((merged.formulas ?? []).map((formula) => formula.id));
4901
+ const \u8F09\u305B\u308B\u5F0F = [...merged.formulas ?? []];
4902
+ for (const formula of ownFormulas) {
4903
+ if (\u3064\u307E\u307F.has(formula.id) || \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(formula.id)) {
4904
+ opts?.onNotice?.({
4905
+ kind: "formula-unresolved",
4906
+ actor: formula.id,
4907
+ line: formula.line,
4908
+ message: `\u5F0F "${formula.id}" \u306E\u540D\u524D\u304C\u3001\u5148\u306B\u66F8\u304B\u308C\u305F\u3064\u307E\u307F\u307E\u305F\u306F\u5F0F\u3068\u91CD\u306A\u3063\u3066\u3044\u307E\u3059`,
4909
+ hint: "`inputs:` \u3068 `formulas:` \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
4910
+ });
4911
+ continue;
4912
+ }
4913
+ let \u540D\u524D\u305F\u3061;
4914
+ try {
4915
+ \u540D\u524D\u305F\u3061 = cdl.extractIdentifiers(cdl.parseFormula(formula.expression));
4916
+ } catch {
4917
+ continue;
4918
+ }
4919
+ let \u89E3\u3051\u306A\u3044 = false;
4920
+ for (const \u540D of \u540D\u524D\u305F\u3061) {
4921
+ if (\u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(\u540D)) continue;
4922
+ const input = \u3064\u307E\u307F.get(\u540D);
4923
+ if (input) {
4924
+ const \u521D\u671F\u5024 = cdl.inputDefaultValue(input);
4925
+ if (typeof \u521D\u671F\u5024 === "number" || typeof \u521D\u671F\u5024 === "boolean") continue;
4926
+ \u89E3\u3051\u306A\u3044 = true;
4927
+ opts?.onNotice?.({
4928
+ kind: "formula-unresolved",
4929
+ actor: formula.id,
4930
+ line: formula.line,
4931
+ message: `\u5F0F "${formula.id}" \u304C\u3001\u6570\u3067\u3082\u771F\u507D\u3067\u3082\u306A\u3044\u3064\u307E\u307F "${\u540D}" \u3092\u8AAD\u3093\u3067\u3044\u307E\u3059`,
4932
+ hint: "\u5F0F\u304C\u8AAD\u3081\u308B\u3064\u307E\u307F\u306F slider / number / stepper / timeline / toggle"
4933
+ });
4934
+ continue;
4935
+ }
4936
+ \u89E3\u3051\u306A\u3044 = true;
4937
+ opts?.onNotice?.({
4938
+ kind: "formula-unresolved",
4939
+ actor: formula.id,
4940
+ line: formula.line,
4941
+ message: `\u5F0F "${formula.id}" \u304C\u3001\u3064\u307E\u307F\u307E\u305F\u306F\u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F\u3067\u306F\u306A\u3044\u540D\u524D "${\u540D}" \u3092\u8AAD\u3093\u3067\u3044\u307E\u3059`,
4942
+ hint: "`inputs:` \u306B\u66F8\u304F\u304B\u3001\u53C2\u7167\u3055\u308C\u308B\u5F0F\u3092\u3053\u306E\u5F0F\u3088\u308A\u524D\u306B\u66F8\u304F"
4943
+ });
4944
+ }
4945
+ if (\u89E3\u3051\u306A\u3044) continue;
4946
+ \u8F09\u305B\u308B\u5F0F.push({ id: formula.id, expression: formula.expression });
4947
+ \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.add(formula.id);
4948
+ }
4949
+ if (\u8F09\u305B\u308B\u5F0F.length > 0) merged.formulas = \u8F09\u305B\u308B\u5F0F;
4950
+ else delete merged.formulas;
4951
+ }
4952
+ if (doc.events && doc.events.length > 0) {
4953
+ const \u8F09\u305B\u308B = [...merged.eventBindings ?? []];
4954
+ for (const e of doc.events) {
4955
+ const \u76F8\u624B = \u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092\u89E3\u304F(merged, doc, e);
4956
+ if (\u76F8\u624B === void 0) {
4957
+ opts?.onNotice?.({
4958
+ kind: "event-target-missing",
4959
+ actor: e.handlerId,
4960
+ line: e.pos.line,
4961
+ message: `\u51FA\u6765\u4E8B "${e.handlerId}" \u304C\u6307\u3059\u76F8\u624B\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`,
4962
+ hint: "box \u306F\u7BB1\u306E\u540D\u524D\u3001 lane \u306F\u7E26\u5217\u306E\u540D\u524D\u3001 arrow \u306F `A -> B` \u3067\u66F8\u304F"
4963
+ });
4964
+ continue;
4965
+ }
4966
+ \u8F09\u305B\u308B.push({
4967
+ id: `evt-${\u8F09\u305B\u308B.length + 1}`,
4968
+ event: e.event,
4969
+ target: \u76F8\u624B,
4970
+ handlerId: e.handlerId
4971
+ });
4972
+ }
4973
+ if (\u8F09\u305B\u308B.length > 0) merged.eventBindings = \u8F09\u305B\u308B;
4974
+ }
4975
+ if (doc.scrolls && doc.scrolls.length > 0) {
4976
+ merged.scrollTriggers = [
4977
+ ...merged.scrollTriggers ?? [],
4978
+ ...doc.scrolls.map((x) => ({ ...x }))
4979
+ ];
4980
+ }
4232
4981
  const \u5916\u3057\u305F\u90E8\u54C1\u306E\u914D\u8272 = stripExternalReadoutPalettes(merged);
4233
4982
  for (const dropped of [...stripExternalPaint(merged), ...\u5916\u3057\u305F\u90E8\u54C1\u306E\u914D\u8272]) {
4234
4983
  opts?.onNotice?.({
@@ -4563,6 +5312,23 @@ function disambiguateActorIds(doc, onNotice) {
4563
5312
  const from = \u76F4\u3059(s.from);
4564
5313
  const to = \u76F4\u3059(s.to);
4565
5314
  return from === s.from && to === s.to ? s : { ...s, from, to };
5315
+ }),
5316
+ events: doc.events?.map((event) => {
5317
+ const target = event.target;
5318
+ if (target.kind === "node") {
5319
+ const name = \u76F4\u3059(target.name);
5320
+ return name === target.name ? event : { ...event, target: { ...target, name } };
5321
+ }
5322
+ if (target.kind === "edge") {
5323
+ const from = \u76F4\u3059(target.from);
5324
+ const to = \u76F4\u3059(target.to);
5325
+ return from === target.from && to === target.to ? event : { ...event, target: { ...target, from, to } };
5326
+ }
5327
+ if (target.kind === "lane" && (doc.type === "sequence" || doc.type === "solidity")) {
5328
+ const name = \u76F4\u3059(target.name);
5329
+ return name === target.name ? event : { ...event, target: { ...target, name } };
5330
+ }
5331
+ return event;
4566
5332
  })
4567
5333
  };
4568
5334
  if (\u6B21.animate) {
@@ -5604,6 +6370,35 @@ function applyEdgeInlineOptions(diagram2, doc, sourceLines) {
5604
6370
  \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc);
5605
6371
  });
5606
6372
  }
6373
+ function \u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092\u89E3\u304F(diagram2, doc, e) {
6374
+ if (e.target.kind === "diagram") return { kind: "diagram" };
6375
+ if (e.target.kind === "edge") {
6376
+ const from = slugify(e.target.from);
6377
+ const to = slugify(e.target.to);
6378
+ let \u77E2\u5370;
6379
+ if (doc.type === "sequence" || doc.type === "solidity") {
6380
+ const stepIdx = doc.flow.findIndex(
6381
+ (step) => slugify(step.from) === from && slugify(step.to) === to
6382
+ );
6383
+ if (stepIdx >= 0) {
6384
+ \u77E2\u5370 = diagram2.edges.find(
6385
+ (x) => (x.from === `s${stepIdx}-${from}` || x.from === from) && (x.to === `s${stepIdx}-${to}` || x.from === x.to)
6386
+ );
6387
+ }
6388
+ } else {
6389
+ \u77E2\u5370 = diagram2.edges.find((x) => x.from === from && x.to === to);
6390
+ }
6391
+ return \u77E2\u5370 ? { kind: "edge", id: \u77E2\u5370.id } : void 0;
6392
+ }
6393
+ const \u540D = e.target.name;
6394
+ const slug = slugify(\u540D);
6395
+ if (e.target.kind === "node") {
6396
+ const \u7BB1 = diagram2.nodes.find((n) => n.id === slug || n.id === \u540D || n.title === \u540D);
6397
+ return \u7BB1 ? { kind: "node", id: \u7BB1.id } : void 0;
6398
+ }
6399
+ const \u5217 = (diagram2.lanes ?? []).find((l) => l.id === slug || l.id === \u540D || l.label === \u540D);
6400
+ return \u5217 ? { kind: "lane", id: \u5217.id } : void 0;
6401
+ }
5607
6402
  function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
5608
6403
  if (s.sub !== void 0) target.sub = s.sub;
5609
6404
  if (s.guard !== void 0) {
@@ -5620,6 +6415,9 @@ function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
5620
6415
  if (s.labelOffsetX !== void 0) target.labelOffsetX = s.labelOffsetX;
5621
6416
  if (s.labelOffsetY !== void 0) target.labelOffsetY = s.labelOffsetY;
5622
6417
  if (s.overlay !== void 0) target.overlay = s.overlay;
6418
+ if (s.widthBind !== void 0) target.widthBind = s.widthBind;
6419
+ if (s.strokeBind !== void 0) target.strokeBind = s.strokeBind;
6420
+ if (s.dashOffsetBind !== void 0) target.dashOffsetBind = s.dashOffsetBind;
5623
6421
  }
5624
6422
  function \u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc) {
5625
6423
  if (doc.type !== "flow") return false;
@@ -6789,7 +7587,7 @@ function compileC4(doc) {
6789
7587
  b.node(x.id, {
6790
7588
  lane: lid,
6791
7589
  stack,
6792
- kind: x.actor.kind,
7590
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(x.actor.kind),
6793
7591
  title: x.actor.name
6794
7592
  });
6795
7593
  }
@@ -6834,7 +7632,12 @@ var \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u306E\u540D\u524D = {
6834
7632
  nodes: "\u4E2D\u306E\u7BB1\u3054\u3068\u306E\u6307\u5B9A",
6835
7633
  layoutPos: "\u914D\u7F6E\u306E\u305A\u3089\u3057",
6836
7634
  shape: "\u7BB1\u306E\u4E2D\u306E\u56F3\u5F62",
6837
- visibleIf: "\u51FA\u3059\u6761\u4EF6"
7635
+ visibleIf: "\u51FA\u3059\u6761\u4EF6",
7636
+ wBind: "\u5024\u306B\u8FFD\u968F\u3059\u308B\u5927\u304D\u3055",
7637
+ hBind: "\u5024\u306B\u8FFD\u968F\u3059\u308B\u5927\u304D\u3055",
7638
+ opacity: "\u6FC3\u3055",
7639
+ renderOffsetX: "\u63CF\u304F\u6642\u306E\u305A\u3089\u3057",
7640
+ renderOffsetY: "\u63CF\u304F\u6642\u306E\u305A\u3089\u3057"
6838
7641
  };
6839
7642
  function \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u3092\u66F8\u3044\u305F\u304B(a, \u6B04) {
6840
7643
  if (\u6B04 === "kind") return a.kindWritten === true;
@@ -7079,6 +7882,11 @@ function applyV05Extensions(diagram2, doc, \u8FFD\u52A0\u3057\u305F\u7E26\u5217o
7079
7882
  if (footer) footer.visibleIf = a.visibleIf;
7080
7883
  }
7081
7884
  }
7885
+ if (a.wBind !== void 0) node.wBind = a.wBind;
7886
+ if (a.hBind !== void 0) node.hBind = a.hBind;
7887
+ if (a.opacity !== void 0) node.opacity = a.opacity;
7888
+ if (a.renderOffsetX !== void 0) node.renderOffsetX = a.renderOffsetX;
7889
+ if (a.renderOffsetY !== void 0) node.renderOffsetY = a.renderOffsetY;
7082
7890
  }
7083
7891
  }
7084
7892
  alignSeqHeaderHeights(diagram2, doc);
@@ -7363,7 +8171,7 @@ function compileFlow(doc) {
7363
8171
  flowBuilder.step(
7364
8172
  {
7365
8173
  id: slugify(a.name),
7366
- kind: a.kind,
8174
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
7367
8175
  title: \u7BB1\u306E\u984C(a)
7368
8176
  },
7369
8177
  edgeLabel
@@ -7393,7 +8201,7 @@ function compileSwimlane(doc) {
7393
8201
  swim.node(nodeId, {
7394
8202
  lane: laneId,
7395
8203
  stack,
7396
- kind: actor?.kind ?? "actor",
8204
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(actor?.kind),
7397
8205
  title: actorName
7398
8206
  });
7399
8207
  laneStackCount.set(laneId, stack + 1);
@@ -7415,7 +8223,7 @@ function compileSwimlane(doc) {
7415
8223
  swim.node(slugify(a.name), {
7416
8224
  lane: swim.laneId(a.name),
7417
8225
  stack: 0,
7418
- kind: a.kind ?? "actor",
8226
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
7419
8227
  title: \u7BB1\u306E\u984C(a)
7420
8228
  });
7421
8229
  });
@@ -7504,7 +8312,7 @@ function compileTopology(doc) {
7504
8312
  for (const a of doc.actors) {
7505
8313
  groupBuilder.add({
7506
8314
  id: slugify(a.name),
7507
- kind: a.kind,
8315
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
7508
8316
  title: \u7BB1\u306E\u984C(a)
7509
8317
  });
7510
8318
  }
@@ -7537,22 +8345,45 @@ function compileGenericWithAnimate(doc, opts) {
7537
8345
  const { kind, laneWidth } = opts;
7538
8346
  const actorToNodeId = /* @__PURE__ */ new Map();
7539
8347
  if (\u66F8\u3044\u305F\u7E26\u5217\u306B\u7F6E\u304F(kind, doc)) {
7540
- const \u4E26\u3073 = [];
8348
+ const \u4F7F\u3063\u305F = [];
7541
8349
  for (const a of doc.actors) {
7542
8350
  const lid = a.lane;
7543
- if (lid !== void 0 && !\u4E26\u3073.includes(lid)) \u4E26\u3073.push(lid);
8351
+ if (lid !== void 0 && !\u4F7F\u3063\u305F.includes(lid)) \u4F7F\u3063\u305F.push(lid);
7544
8352
  }
8353
+ const \u66F8\u3044\u305F\u9806 = doc.lanes ? Object.keys(doc.lanes) : [];
8354
+ const \u4E26\u3073 = [
8355
+ ...\u66F8\u3044\u305F\u9806.filter((lid) => \u4F7F\u3063\u305F.includes(lid)),
8356
+ ...\u4F7F\u3063\u305F.filter((lid) => !\u66F8\u3044\u305F\u9806.includes(lid))
8357
+ ];
7545
8358
  for (const lid of \u4E26\u3073) {
7546
8359
  b.lane(lid, { width: laneWidth, ...kind === "topology" ? { contain: true } : {} });
7547
8360
  }
7548
- const \u7A4D\u3093\u3060\u6570 = /* @__PURE__ */ new Map();
8361
+ const \u57CB\u307E\u3063\u305F\u6BB5 = /* @__PURE__ */ new Map();
8362
+ const \u57CB\u3081\u308B = (lid, stack) => {
8363
+ const \u96C6\u5408 = \u57CB\u307E\u3063\u305F\u6BB5.get(lid) ?? /* @__PURE__ */ new Set();
8364
+ \u96C6\u5408.add(stack);
8365
+ \u57CB\u307E\u3063\u305F\u6BB5.set(lid, \u96C6\u5408);
8366
+ };
8367
+ for (const a of doc.actors) {
8368
+ if (a.lane !== void 0 && a.stack !== void 0) \u57CB\u3081\u308B(a.lane, a.stack);
8369
+ }
7549
8370
  doc.actors.forEach((a, idx) => {
7550
8371
  const id = slugify(a.name);
7551
8372
  actorToNodeId.set(a.name, id);
7552
8373
  const lid = a.lane;
7553
- const stack = \u7A4D\u3093\u3060\u6570.get(lid) ?? 0;
7554
- \u7A4D\u3093\u3060\u6570.set(lid, stack + 1);
7555
- b.node(id, { lane: lid, stack, kind: a.kind, title: \u7BB1\u306E\u984C(a) });
8374
+ let stack = a.stack;
8375
+ if (stack === void 0) {
8376
+ stack = 0;
8377
+ const \u96C6\u5408 = \u57CB\u307E\u3063\u305F\u6BB5.get(lid);
8378
+ while (\u96C6\u5408?.has(stack)) stack += 1;
8379
+ \u57CB\u3081\u308B(lid, stack);
8380
+ }
8381
+ b.node(id, {
8382
+ lane: lid,
8383
+ stack,
8384
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
8385
+ title: \u7BB1\u306E\u984C(a)
8386
+ });
7556
8387
  });
7557
8388
  } else if (kind === "flow" || kind === "topology") {
7558
8389
  const lid = opts.laneId ?? "main";
@@ -7564,7 +8395,12 @@ function compileGenericWithAnimate(doc, opts) {
7564
8395
  doc.actors.forEach((a, idx) => {
7565
8396
  const id = slugify(a.name);
7566
8397
  actorToNodeId.set(a.name, id);
7567
- b.node(id, { lane: lid, stack: idx, kind: a.kind, title: \u7BB1\u306E\u984C(a) });
8398
+ b.node(id, {
8399
+ lane: lid,
8400
+ stack: idx,
8401
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
8402
+ title: \u7BB1\u306E\u984C(a)
8403
+ });
7568
8404
  });
7569
8405
  } else {
7570
8406
  const \u898B\u51FA\u3057\u3092\u4ED8\u3051\u308B = kind === "swimlane";
@@ -7579,7 +8415,7 @@ function compileGenericWithAnimate(doc, opts) {
7579
8415
  b.node(id, {
7580
8416
  lane: lid,
7581
8417
  stack: 0,
7582
- kind: a.kind,
8418
+ kind: \u63CF\u3051\u308B\u7A2E\u5225(a.kind),
7583
8419
  title: \u7BB1\u306E\u984C(a),
7584
8420
  ...isInitial ? { eyebrow: "\u521D\u671F" } : {},
7585
8421
  ...isFinal ? { eyebrow: "\u6700\u7D42" } : {}
@@ -8269,8 +9105,6 @@ function \u533A\u9593\u306B\u5E83\u3052\u308B(src, tokens) {
8269
9105
  if (\u4F4D\u7F6E < src.length) out.push({ \u6587\u5B57: src.slice(\u4F4D\u7F6E) });
8270
9106
  return out;
8271
9107
  }
8272
-
8273
- // src/json-parser.ts
8274
9108
  var VALID_KIND_SET = NODE_KIND_VALID;
8275
9109
  var VALID_PRESETS = [...PRESET_TYPES];
8276
9110
  var ACCEPTED_KEYS = {
@@ -8288,7 +9122,14 @@ var ACCEPTED_KEYS = {
8288
9122
  "lanes",
8289
9123
  "groups",
8290
9124
  // 値を見せる部品 (#1374)
8291
- "readouts"
9125
+ "readouts",
9126
+ // 読む人が動かすつまみ (#1389)
9127
+ "inputs",
9128
+ // つまみの値から決まる値 (#1391)
9129
+ "formulas",
9130
+ // 押下などの出来事で動く仕掛けと、巻き上げに応じて進む値 (#1393)
9131
+ "events",
9132
+ "scrolls"
8292
9133
  ],
8293
9134
  actor: [
8294
9135
  "name",
@@ -8320,7 +9161,13 @@ var ACCEPTED_KEYS = {
8320
9161
  // その箱を出すかどうかの条件 (#1381)
8321
9162
  "visibleIf",
8322
9163
  // 箱に出す題 (#1381)
8323
- "title"
9164
+ "title",
9165
+ // 値に追随する 5 欄 (#1392)
9166
+ "wBind",
9167
+ "hBind",
9168
+ "opacity",
9169
+ "renderOffsetX",
9170
+ "renderOffsetY"
8324
9171
  ],
8325
9172
  step: [
8326
9173
  "from",
@@ -8333,6 +9180,10 @@ var ACCEPTED_KEYS = {
8333
9180
  "style",
8334
9181
  "guard",
8335
9182
  "cardinality",
9183
+ // 値に追随する 3 欄 (#1396)
9184
+ "widthBind",
9185
+ "strokeBind",
9186
+ "dashOffsetBind",
8336
9187
  "labelOffsetX",
8337
9188
  "labelOffsetY",
8338
9189
  "overlay",
@@ -8363,7 +9214,14 @@ var \u6B04\u306E\u578B\u8868 = {
8363
9214
  lanes: "object",
8364
9215
  groups: "object",
8365
9216
  // 値を見せる部品 (#1374)。 中身は下の検査が種類ごとに見る
8366
- readouts: "\u4E26\u3073"
9217
+ readouts: "\u4E26\u3073",
9218
+ // 読む人が動かすつまみ (#1389)。 部品と同じく中身は下の検査が種類ごとに見る
9219
+ inputs: "\u4E26\u3073",
9220
+ // つまみの値から決まる値 (#1391)。 中身は下の検査が式ごとに見る
9221
+ formulas: "object",
9222
+ // 押下と巻き上げ (#1393)。 中身は下の検査が 1 件ずつ見る
9223
+ events: "\u4E26\u3073",
9224
+ scrolls: "object"
8367
9225
  },
8368
9226
  actor: {
8369
9227
  name: "\u5FC5\u9808\u306E\u975E\u7A7A\u6587\u5B57\u5217",
@@ -8395,7 +9253,13 @@ var \u6B04\u306E\u578B\u8868 = {
8395
9253
  // その箱を出すかどうかの条件 (#1381)
8396
9254
  visibleIf: "\u6587\u5B57\u5217",
8397
9255
  // 箱に出す題 (#1381)
8398
- title: "\u6587\u5B57\u5217"
9256
+ title: "\u6587\u5B57\u5217",
9257
+ // 値に追随する 5 欄 (#1392)。 大きさは文字列だけ、濃さとずらしは数も受ける
9258
+ wBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9259
+ hBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9260
+ opacity: "\u6570\u304B\u6587\u5B57\u5217",
9261
+ renderOffsetX: "\u6570\u304B\u6587\u5B57\u5217",
9262
+ renderOffsetY: "\u6570\u304B\u6587\u5B57\u5217"
8399
9263
  },
8400
9264
  step: {
8401
9265
  from: "\u5FC5\u9808\u306E\u6587\u5B57\u5217",
@@ -8408,6 +9272,10 @@ var \u6B04\u306E\u578B\u8868 = {
8408
9272
  style: "\u7DDA\u7A2E",
8409
9273
  guard: "\u6587\u5B57\u5217",
8410
9274
  cardinality: "\u6587\u5B57\u5217",
9275
+ // 値に追随する 3 欄 (#1396)。 描画側は文字列だけを取る
9276
+ widthBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9277
+ strokeBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9278
+ dashOffsetBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
8411
9279
  labelOffsetX: "\u6570",
8412
9280
  labelOffsetY: "\u6570",
8413
9281
  overlay: "\u771F\u507D",
@@ -8468,7 +9336,13 @@ var \u898B\u672C\u306B\u52B9\u304B\u306A\u3044\u6B04 = [
8468
9336
  // その箱を出すかどうかの条件 (#1381)。 見本は自分の出方を持つ
8469
9337
  "visibleIf",
8470
9338
  // 箱に出す題 (#1381)。 見本は自分の題を持つ
8471
- "title"
9339
+ "title",
9340
+ // 値に追随する 5 欄 (#1392)。 見本は自分の大きさと出方を持つ
9341
+ "wBind",
9342
+ "hBind",
9343
+ "opacity",
9344
+ "renderOffsetX",
9345
+ "renderOffsetY"
8472
9346
  ];
8473
9347
  function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8474
9348
  const \u578B\u9055\u3044 = (\u671F\u5F85, \u88DC\u8DB3) => {
@@ -8487,7 +9361,7 @@ function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8487
9361
  return;
8488
9362
  case "\u975E\u7A7A\u306E\u6587\u5B57\u5217":
8489
9363
  if (v === void 0) return;
8490
- if (typeof v !== "string" || v.length === 0) \u578B\u9055\u3044("a non-empty string if present");
9364
+ if (typeof v !== "string" || v.trim().length === 0) \u578B\u9055\u3044("a non-empty string if present");
8491
9365
  return;
8492
9366
  case "\u6587\u5B57\u5217":
8493
9367
  if (v === void 0) return;
@@ -8523,6 +9397,19 @@ function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8523
9397
  \u578B\u9055\u3044("a finite number", typeof v === "number" ? `got ${String(v)}` : void 0);
8524
9398
  }
8525
9399
  return;
9400
+ case "\u6570\u304B\u6587\u5B57\u5217":
9401
+ if (v === void 0) return;
9402
+ if (typeof v === "string") {
9403
+ if (v.trim().length === 0) \u578B\u9055\u3044("a non-empty string if present");
9404
+ return;
9405
+ }
9406
+ if (typeof v !== "number" || !Number.isFinite(v)) {
9407
+ \u578B\u9055\u3044(
9408
+ "a finite number or a non-empty string if present",
9409
+ typeof v === "number" ? `got ${String(v)}` : void 0
9410
+ );
9411
+ }
9412
+ return;
8526
9413
  case "\u771F\u507D":
8527
9414
  if (v === void 0) return;
8528
9415
  if (typeof v !== "boolean") \u578B\u9055\u3044("true or false if present");
@@ -8700,7 +9587,7 @@ function validateViewport(v, errors) {
8700
9587
  }
8701
9588
  function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path, \u4F55, errors) {
8702
9589
  const kind = typeof o.kind === "string" ? o.kind : "";
8703
- const \u5B9A\u7FA9 = \u8868[kind];
9590
+ const \u5B9A\u7FA9 = Object.hasOwn(\u8868, kind) ? \u8868[kind] : void 0;
8704
9591
  if (\u5B9A\u7FA9 === void 0) {
8705
9592
  errors.push({
8706
9593
  path: `${path}.kind`,
@@ -8722,7 +9609,7 @@ function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path,
8722
9609
  });
8723
9610
  continue;
8724
9611
  }
8725
- const \u578B\u304C\u5408\u3046 = \u5F62 === "\u6570" ? typeof \u5024 === "number" && Number.isFinite(\u5024) : \u5F62 === "\u6570\u304B\u6587\u5B57\u5217" ? typeof \u5024 === "number" && Number.isFinite(\u5024) || typeof \u5024 === "string" : \u5F62 === "\u6587\u5B57\u5217\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.every((x) => typeof x === "string") : \u5F62 === "\u771F\u507D" ? typeof \u5024 === "boolean" : \u5F62 === "\u7D44\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.length > 0 && \u5024.every(
9612
+ const \u578B\u304C\u5408\u3046 = \u5F62 === "\u6570" ? typeof \u5024 === "number" && Number.isFinite(\u5024) : \u5F62 === "\u6570\u304B\u6587\u5B57\u5217" ? typeof \u5024 === "number" && Number.isFinite(\u5024) || typeof \u5024 === "string" : \u5F62 === "\u6587\u5B57\u5217\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.every((x) => typeof x === "string") : \u5F62 === "\u6570\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.every((x) => typeof x === "number" && Number.isFinite(x)) : \u5F62 === "\u771F\u507D" ? typeof \u5024 === "boolean" : \u5F62 === "\u7D44\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.length > 0 && \u5024.every(
8726
9613
  (x) => typeof x === "object" && x !== null && !Array.isArray(x) && Object.keys(x).length > 0 && Object.values(x).every(
8727
9614
  (y) => typeof y === "string" || typeof y === "number" && Number.isFinite(y)
8728
9615
  )
@@ -8803,6 +9690,238 @@ function validateReadouts(v, errors) {
8803
9690
  }
8804
9691
  });
8805
9692
  }
9693
+ function validateInputs(v, errors) {
9694
+ if (v === void 0) return;
9695
+ if (!Array.isArray(v)) {
9696
+ errors.push({
9697
+ path: "$.inputs",
9698
+ message: "inputs must be an array of input objects",
9699
+ hint: `got ${v === null ? "null" : typeof v}`
9700
+ });
9701
+ return;
9702
+ }
9703
+ v.forEach((r, i) => {
9704
+ const path = `$.inputs[${i}]`;
9705
+ if (!r || typeof r !== "object" || Array.isArray(r)) {
9706
+ errors.push({ path, message: "input must be a plain object", hint: `got ${typeof r}` });
9707
+ return;
9708
+ }
9709
+ const o = r;
9710
+ if (typeof o.id !== "string" || o.id === "") {
9711
+ errors.push({ path: `${path}.id`, message: "id is required", hint: "\u7A7A\u3067\u306A\u3044\u6587\u5B57\u5217\u3067\u66F8\u304F" });
9712
+ }
9713
+ \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u3064\u307E\u307F\u306E\u8868, path, "input", errors);
9714
+ });
9715
+ }
9716
+ function validateFormulas(v, inputs, errors) {
9717
+ if (v === void 0) return;
9718
+ if (!v || typeof v !== "object" || Array.isArray(v)) {
9719
+ errors.push({
9720
+ path: "$.formulas",
9721
+ message: "formulas must be an object of name to expression",
9722
+ hint: `got ${v === null ? "null" : Array.isArray(v) ? "array" : typeof v}`
9723
+ });
9724
+ return;
9725
+ }
9726
+ const \u3064\u307E\u307F = /* @__PURE__ */ new Map();
9727
+ if (Array.isArray(inputs)) {
9728
+ for (const input of inputs) {
9729
+ if (input && typeof input === "object" && !Array.isArray(input)) {
9730
+ const candidate = input;
9731
+ if (typeof candidate.id === "string" && typeof candidate.kind === "string") {
9732
+ \u3064\u307E\u307F.set(candidate.id, candidate.kind);
9733
+ }
9734
+ }
9735
+ }
9736
+ }
9737
+ const \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F = /* @__PURE__ */ new Set();
9738
+ for (const [\u540D\u524D, \u5F0F] of Object.entries(v)) {
9739
+ const path = `$.formulas.${\u540D\u524D}`;
9740
+ if (!isValueName(\u540D\u524D)) {
9741
+ errors.push({ path, ...valueNameIssue(\u540D\u524D) });
9742
+ continue;
9743
+ }
9744
+ if (typeof \u5F0F !== "string" || \u5F0F.trim() === "") {
9745
+ errors.push({
9746
+ path,
9747
+ message: `${\u540D\u524D} must be a non-empty expression string`,
9748
+ hint: `got ${Array.isArray(\u5F0F) ? "array" : \u5F0F === null ? "null" : typeof \u5F0F}`
9749
+ });
9750
+ continue;
9751
+ }
9752
+ try {
9753
+ const names = cdl.extractIdentifiers(cdl.parseFormula(\u5F0F));
9754
+ if (\u3064\u307E\u307F.has(\u540D\u524D) || \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(\u540D\u524D)) {
9755
+ errors.push({
9756
+ path,
9757
+ message: `${\u540D\u524D} collides with an input or an earlier formula`,
9758
+ hint: "inputs \u3068 formulas \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
9759
+ });
9760
+ continue;
9761
+ }
9762
+ let valid = true;
9763
+ for (const name of names) {
9764
+ if (\u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(name)) continue;
9765
+ const kind = \u3064\u307E\u307F.get(name);
9766
+ if (["slider", "number", "stepper", "timeline", "toggle"].includes(kind ?? "")) continue;
9767
+ valid = false;
9768
+ errors.push({
9769
+ path,
9770
+ message: `${\u540D\u524D} references an unavailable formula identifier`,
9771
+ hint: `${name} \u306F\u6570\u5024/\u771F\u507D\u306E input \u306B\u3059\u308B\u304B\u3001\u3053\u306E\u5F0F\u3088\u308A\u524D\u306E formula \u306B\u66F8\u304F`
9772
+ });
9773
+ }
9774
+ if (valid) \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.add(\u540D\u524D);
9775
+ } catch (e) {
9776
+ errors.push({
9777
+ path,
9778
+ message: `${\u540D\u524D} is not a readable expression`,
9779
+ hint: e.message
9780
+ });
9781
+ }
9782
+ }
9783
+ }
9784
+ function validateEvents(v, errors) {
9785
+ if (v === void 0) return;
9786
+ if (!Array.isArray(v)) {
9787
+ errors.push({
9788
+ path: "$.events",
9789
+ message: "events must be an array of event objects",
9790
+ hint: `got ${v === null ? "null" : typeof v}`
9791
+ });
9792
+ return;
9793
+ }
9794
+ const \u76F8\u624B\u306E\u9375 = ["box", "lane", "arrow", "diagram"];
9795
+ v.forEach((e, i) => {
9796
+ const path = `$.events[${i}]`;
9797
+ if (!e || typeof e !== "object" || Array.isArray(e)) {
9798
+ errors.push({ path, message: "event must be a plain object", hint: `got ${typeof e}` });
9799
+ return;
9800
+ }
9801
+ const o = e;
9802
+ for (const k of Object.keys(o)) {
9803
+ if (k === "on" || k === "handler" || \u76F8\u624B\u306E\u9375.includes(k)) continue;
9804
+ errors.push({
9805
+ path: `${path}.${k}`,
9806
+ message: `unknown key "${k}"`,
9807
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = on, handler, ${\u76F8\u624B\u306E\u9375.join(", ")}`
9808
+ });
9809
+ }
9810
+ if (typeof o.on !== "string" || !EVENT_KINDS.includes(o.on)) {
9811
+ errors.push({
9812
+ path: `${path}.on`,
9813
+ message: "on must be a known event kind",
9814
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${EVENT_KINDS.join(", ")}`
9815
+ });
9816
+ }
9817
+ if (typeof o.handler !== "string" || o.handler.trim() === "") {
9818
+ errors.push({
9819
+ path: `${path}.handler`,
9820
+ message: "handler is required",
9821
+ hint: "\u7A7A\u3067\u306A\u3044\u6587\u5B57\u5217\u3067\u66F8\u304F"
9822
+ });
9823
+ }
9824
+ const \u66F8\u3044\u305F = \u76F8\u624B\u306E\u9375.filter((k) => o[k] !== void 0);
9825
+ if (\u66F8\u3044\u305F.length !== 1) {
9826
+ errors.push({
9827
+ path,
9828
+ message: \u66F8\u3044\u305F.length === 0 ? "event target is required" : "event target must be written once",
9829
+ hint: `${\u76F8\u624B\u306E\u9375.join(" / ")} \u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u3092\u66F8\u304F`
9830
+ });
9831
+ return;
9832
+ }
9833
+ const \u9375 = \u66F8\u3044\u305F[0];
9834
+ if (\u9375 === "diagram") {
9835
+ if (o.diagram !== true) {
9836
+ errors.push({
9837
+ path: `${path}.diagram`,
9838
+ message: "diagram must be true",
9839
+ hint: "\u56F3\u5168\u4F53\u3092\u6307\u3059\u6642\u3060\u3051\u66F8\u304F"
9840
+ });
9841
+ }
9842
+ return;
9843
+ }
9844
+ if (typeof o[\u9375] !== "string" || o[\u9375].trim() === "") {
9845
+ errors.push({ path: `${path}.${\u9375}`, message: `${\u9375} must be a non-empty string` });
9846
+ return;
9847
+ }
9848
+ if (\u9375 === "arrow") {
9849
+ const \u4E21\u7AEF = o.arrow.split("->");
9850
+ if (\u4E21\u7AEF.length !== 2 || \u4E21\u7AEF.some((x) => x.trim() === "")) {
9851
+ errors.push({
9852
+ path: `${path}.arrow`,
9853
+ message: "arrow must be `A -> B`",
9854
+ hint: "\u77E2\u5370\u306E\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
9855
+ });
9856
+ }
9857
+ }
9858
+ });
9859
+ }
9860
+ function validateScrolls(v, inputs, formulas, errors) {
9861
+ if (v === void 0) return;
9862
+ if (!v || typeof v !== "object" || Array.isArray(v)) {
9863
+ errors.push({
9864
+ path: "$.scrolls",
9865
+ message: "scrolls must be an object of name to spec",
9866
+ hint: `got ${v === null ? "null" : Array.isArray(v) ? "array" : typeof v}`
9867
+ });
9868
+ return;
9869
+ }
9870
+ const \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D = /* @__PURE__ */ new Set();
9871
+ if (Array.isArray(inputs)) {
9872
+ for (const input of inputs) {
9873
+ if (!input || typeof input !== "object" || Array.isArray(input)) continue;
9874
+ const id = input.id;
9875
+ if (typeof id === "string") \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.add(id);
9876
+ }
9877
+ }
9878
+ if (formulas && typeof formulas === "object" && !Array.isArray(formulas)) {
9879
+ for (const id of Object.keys(formulas)) \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.add(id);
9880
+ }
9881
+ for (const [\u540D\u524D, spec] of Object.entries(v)) {
9882
+ const path = `$.scrolls.${\u540D\u524D}`;
9883
+ if (!isValueName(\u540D\u524D)) {
9884
+ errors.push({ path, ...valueNameIssue(\u540D\u524D) });
9885
+ continue;
9886
+ }
9887
+ if (\u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.has(\u540D\u524D)) {
9888
+ errors.push({
9889
+ path,
9890
+ message: `${\u540D\u524D} collides with an input or formula`,
9891
+ hint: "inputs / formulas / scrolls \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
9892
+ });
9893
+ }
9894
+ if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
9895
+ errors.push({ path, message: `${\u540D\u524D} must be a plain object`, hint: `got ${typeof spec}` });
9896
+ continue;
9897
+ }
9898
+ for (const [k, x] of Object.entries(spec)) {
9899
+ if (k === "label") {
9900
+ if (typeof x !== "string") {
9901
+ errors.push({ path: `${path}.label`, message: "label must be a string" });
9902
+ }
9903
+ continue;
9904
+ }
9905
+ if (k !== "start" && k !== "end" && k !== "scrub") {
9906
+ errors.push({
9907
+ path: `${path}.${k}`,
9908
+ message: `unknown key "${k}"`,
9909
+ hint: "\u4F7F\u3048\u308B\u9805\u76EE = start, end, scrub, label"
9910
+ });
9911
+ continue;
9912
+ }
9913
+ if (typeof x !== "number" || !Number.isFinite(x)) {
9914
+ errors.push({ path: `${path}.${k}`, message: `${k} must be a finite number` });
9915
+ } else if (x < 0 || x > 1) {
9916
+ errors.push({
9917
+ path: `${path}.${k}`,
9918
+ message: `${k} must be between 0 and 1`,
9919
+ hint: "0 \u3068 1 \u3092\u542B\u3080\u7BC4\u56F2\u3067\u66F8\u304F"
9920
+ });
9921
+ }
9922
+ }
9923
+ }
9924
+ }
8806
9925
  function validateActorShape(v, path, errors) {
8807
9926
  if (v === void 0) return;
8808
9927
  if (!v || typeof v !== "object" || Array.isArray(v)) {
@@ -8977,6 +10096,10 @@ function validateJson(json) {
8977
10096
  const j = \u5199\u3057.value;
8978
10097
  checkUnknownKeys(j, "root", "$", errors);
8979
10098
  validateReadouts(j.readouts, errors);
10099
+ validateInputs(j.inputs, errors);
10100
+ validateFormulas(j.formulas, j.inputs, errors);
10101
+ validateEvents(j.events, errors);
10102
+ validateScrolls(j.scrolls, j.inputs, j.formulas, errors);
8980
10103
  \u8868\u3067\u691C\u67FB(j, "root", "$", "", errors);
8981
10104
  if (!Array.isArray(j.actors) || j.actors.length === 0) {
8982
10105
  errors.push({ path: "$.actors", message: "actors must be a non-empty array" });
@@ -9213,6 +10336,12 @@ function jsonToDoc(json) {
9213
10336
  shape: isPart ? void 0 : a.shape,
9214
10337
  visibleIf: isPart ? void 0 : a.visibleIf,
9215
10338
  title: isPart ? void 0 : a.title,
10339
+ // 値に追随する 5 欄 (#1392)。 記法と同じく見本には渡さない
10340
+ wBind: isPart ? void 0 : a.wBind,
10341
+ hBind: isPart ? void 0 : a.hBind,
10342
+ opacity: isPart ? void 0 : a.opacity,
10343
+ renderOffsetX: isPart ? void 0 : a.renderOffsetX,
10344
+ renderOffsetY: isPart ? void 0 : a.renderOffsetY,
9216
10345
  // 普通の箱にしか効かない欄は見本では落とす。 落とす欄の一覧は `見本に効かない欄` が
9217
10346
  // 唯一の出どころで、検査 (#1308) も同じ表を見る = 「検査は通すが組み立てが捨てる」
9218
10347
  // 状態が作れない
@@ -9260,6 +10389,10 @@ function jsonToDoc(json) {
9260
10389
  style: s.style,
9261
10390
  guard: s.guard,
9262
10391
  cardinality: s.cardinality,
10392
+ // 値に追随する 3 欄 (#1396)
10393
+ widthBind: s.widthBind,
10394
+ strokeBind: s.strokeBind,
10395
+ dashOffsetBind: s.dashOffsetBind,
9263
10396
  labelOffsetX: s.labelOffsetX,
9264
10397
  labelOffsetY: s.labelOffsetY,
9265
10398
  overlay: s.overlay,
@@ -9268,6 +10401,19 @@ function jsonToDoc(json) {
9268
10401
  pos: p0
9269
10402
  }));
9270
10403
  const readouts = json.readouts ? [...json.readouts] : void 0;
10404
+ const inputs = json.inputs ? [...json.inputs] : void 0;
10405
+ const events = json.events?.map((e) => ({
10406
+ event: e.on,
10407
+ target: e.diagram === true ? { kind: "diagram" } : e.arrow !== void 0 ? {
10408
+ kind: "edge",
10409
+ from: e.arrow.split("->")[0]?.trim() ?? "",
10410
+ to: e.arrow.split("->")[1]?.trim() ?? ""
10411
+ } : e.lane !== void 0 ? { kind: "lane", name: e.lane } : { kind: "node", name: e.box ?? "" },
10412
+ handlerId: e.handler.trim(),
10413
+ pos: p0
10414
+ }));
10415
+ const scrolls = json.scrolls ? Object.entries(json.scrolls).map(([id, spec]) => ({ id, ...spec })) : void 0;
10416
+ const formulas = json.formulas ? Object.entries(json.formulas).map(([id, expression]) => ({ id, expression, pos: p0 })) : void 0;
9271
10417
  const states = Object.entries(json.states ?? {}).map(([name, initial]) => ({
9272
10418
  name,
9273
10419
  initial,
@@ -9325,6 +10471,10 @@ function jsonToDoc(json) {
9325
10471
  ])
9326
10472
  ) : void 0,
9327
10473
  readouts,
10474
+ inputs,
10475
+ formulas,
10476
+ events,
10477
+ scrolls,
9328
10478
  pos: p0
9329
10479
  };
9330
10480
  }
@@ -9713,6 +10863,36 @@ var diagram_default = {
9713
10863
  required: ["sides"]
9714
10864
  }
9715
10865
  ]
10866
+ },
10867
+ wBind: {
10868
+ type: "string",
10869
+ minLength: 1,
10870
+ pattern: "\\S",
10871
+ description: "\u7BB1\u306E\u5E45\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 \u72B6\u614B\u306E\u540D\u524D\u3092 {\u540D\u524D} \u306E\u5F62\u3067\u66F8\u304F\u3002 \u914D\u7F6E\u8A08\u7B97\u306F\u8FFD\u968F\u524D\u306E\u5927\u304D\u3055\u3092\u4F7F\u3046"
10872
+ },
10873
+ hBind: {
10874
+ type: "string",
10875
+ minLength: 1,
10876
+ pattern: "\\S",
10877
+ description: "\u7BB1\u306E\u9AD8\u3055\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 wBind \u3068\u540C\u3058\u8AAD\u307F\u65B9"
10878
+ },
10879
+ opacity: {
10880
+ type: ["number", "string"],
10881
+ minLength: 1,
10882
+ pattern: "\\S",
10883
+ description: "\u7BB1\u306E\u6FC3\u3055\u3002 0 \u304B\u3089 1 \u306E\u6570\u304B\u3001\u72B6\u614B\u306E\u540D\u524D\u3002 \u66F8\u304B\u306A\u3051\u308C\u3070\u5B8C\u5168\u306B\u898B\u3048\u308B"
10884
+ },
10885
+ renderOffsetX: {
10886
+ type: ["number", "string"],
10887
+ minLength: 1,
10888
+ pattern: "\\S",
10889
+ description: "\u63CF\u304F\u6642\u3060\u3051\u7BB1\u3092\u6A2A\u3078\u305A\u3089\u3059\u91CF\u3002 \u914D\u7F6E\u8A08\u7B97\u3068\u77E2\u5370\u306F\u305A\u3089\u3059\u524D\u306E\u4F4D\u7F6E\u3092\u4F7F\u3046"
10890
+ },
10891
+ renderOffsetY: {
10892
+ type: ["number", "string"],
10893
+ minLength: 1,
10894
+ pattern: "\\S",
10895
+ description: "\u63CF\u304F\u6642\u3060\u3051\u7BB1\u3092\u7E26\u3078\u305A\u3089\u3059\u91CF\u3002 renderOffsetX \u3068\u540C\u3058\u8AAD\u307F\u65B9"
9716
10896
  }
9717
10897
  }
9718
10898
  }
@@ -9804,6 +10984,24 @@ var diagram_default = {
9804
10984
  type: "number"
9805
10985
  }
9806
10986
  }
10987
+ },
10988
+ widthBind: {
10989
+ type: "string",
10990
+ minLength: 1,
10991
+ pattern: "\\S",
10992
+ description: "\u7DDA\u306E\u592A\u3055\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 \u72B6\u614B\u3084\u3064\u307E\u307F\u306E\u540D\u524D\u3092 {\u540D\u524D} \u306E\u5F62\u3067\u66F8\u304F"
10993
+ },
10994
+ strokeBind: {
10995
+ type: "string",
10996
+ minLength: 1,
10997
+ pattern: "\\S",
10998
+ description: "\u7DDA\u306E\u8272\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 widthBind \u3068\u540C\u3058\u8AAD\u307F\u65B9"
10999
+ },
11000
+ dashOffsetBind: {
11001
+ type: "string",
11002
+ minLength: 1,
11003
+ pattern: "\\S",
11004
+ description: "\u7834\u7DDA\u306E\u4F4D\u7F6E\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B (\u6D41\u308C\u3066\u3044\u308B\u3088\u3046\u306B\u898B\u305B\u308B)\u3002 widthBind \u3068\u540C\u3058\u8AAD\u307F\u65B9"
9807
11005
  }
9808
11006
  }
9809
11007
  }
@@ -10830,6 +12028,314 @@ var diagram_default = {
10830
12028
  }
10831
12029
  ]
10832
12030
  }
12031
+ },
12032
+ inputs: {
12033
+ type: "array",
12034
+ description: "\u8AAD\u3080\u4EBA\u304C\u52D5\u304B\u3059\u3064\u307E\u307F\u3002 \u5024\u3092\u63E1\u308A\u3001\u7BB1\u306E\u6587\u5B57\u3084\u90E8\u54C1\u304C\u305D\u306E\u5024\u3092\u8FFD\u3044\u304B\u3051\u308B\u3002 \u7BB1\u3067\u306F\u306A\u3044\u306E\u3067\u7E26\u5217\u306B\u8F09\u3089\u305A\u3001\u56F3\u5168\u4F53\u306B 1 \u3064\u306E\u4E26\u3073\u3068\u3057\u3066\u6301\u3064\u3002",
12035
+ items: {
12036
+ type: "object",
12037
+ required: ["id", "kind"],
12038
+ additionalProperties: false,
12039
+ properties: {
12040
+ id: {
12041
+ type: "string",
12042
+ minLength: 1
12043
+ },
12044
+ kind: {
12045
+ type: "string",
12046
+ enum: [
12047
+ "color",
12048
+ "datetime",
12049
+ "dropdown",
12050
+ "multi-select",
12051
+ "number",
12052
+ "radio",
12053
+ "range",
12054
+ "slider",
12055
+ "stepper",
12056
+ "tabs",
12057
+ "text",
12058
+ "timeline",
12059
+ "toggle",
12060
+ "xypad"
12061
+ ]
12062
+ },
12063
+ autoplay: {
12064
+ type: "boolean"
12065
+ },
12066
+ defaultHi: {
12067
+ type: "number"
12068
+ },
12069
+ defaultLo: {
12070
+ type: "number"
12071
+ },
12072
+ defaultSpeedIdx: {
12073
+ type: "number"
12074
+ },
12075
+ defaultValue: {
12076
+ type: ["boolean", "number", "string"]
12077
+ },
12078
+ defaultValues: {
12079
+ type: "array",
12080
+ items: {
12081
+ type: "string"
12082
+ }
12083
+ },
12084
+ defaultX: {
12085
+ type: "number"
12086
+ },
12087
+ defaultY: {
12088
+ type: "number"
12089
+ },
12090
+ duration: {
12091
+ type: "number"
12092
+ },
12093
+ label: {
12094
+ type: "string"
12095
+ },
12096
+ loop: {
12097
+ type: "boolean"
12098
+ },
12099
+ max: {
12100
+ type: "number"
12101
+ },
12102
+ maxLength: {
12103
+ type: "number"
12104
+ },
12105
+ min: {
12106
+ type: "number"
12107
+ },
12108
+ options: {
12109
+ type: "array",
12110
+ items: {
12111
+ type: "string"
12112
+ }
12113
+ },
12114
+ placeholder: {
12115
+ type: "string"
12116
+ },
12117
+ speeds: {
12118
+ type: "array",
12119
+ items: {
12120
+ type: "number"
12121
+ }
12122
+ },
12123
+ step: {
12124
+ type: "number"
12125
+ },
12126
+ xMax: {
12127
+ type: "number"
12128
+ },
12129
+ xMin: {
12130
+ type: "number"
12131
+ },
12132
+ yMax: {
12133
+ type: "number"
12134
+ },
12135
+ yMin: {
12136
+ type: "number"
12137
+ }
12138
+ },
12139
+ oneOf: [
12140
+ {
12141
+ properties: {
12142
+ kind: {
12143
+ enum: ["color", "datetime", "text"]
12144
+ },
12145
+ defaultValue: {
12146
+ type: "string"
12147
+ }
12148
+ },
12149
+ required: ["defaultValue"]
12150
+ },
12151
+ {
12152
+ properties: {
12153
+ kind: {
12154
+ enum: ["dropdown", "radio", "tabs"]
12155
+ },
12156
+ defaultValue: {
12157
+ type: "string"
12158
+ }
12159
+ },
12160
+ required: ["options", "defaultValue"]
12161
+ },
12162
+ {
12163
+ properties: {
12164
+ kind: {
12165
+ enum: ["multi-select"]
12166
+ }
12167
+ },
12168
+ required: ["options", "defaultValues"]
12169
+ },
12170
+ {
12171
+ properties: {
12172
+ kind: {
12173
+ enum: ["number", "stepper"]
12174
+ },
12175
+ defaultValue: {
12176
+ type: "number"
12177
+ }
12178
+ },
12179
+ required: ["defaultValue"]
12180
+ },
12181
+ {
12182
+ properties: {
12183
+ kind: {
12184
+ enum: ["range"]
12185
+ }
12186
+ },
12187
+ required: ["min", "max", "defaultLo", "defaultHi"]
12188
+ },
12189
+ {
12190
+ properties: {
12191
+ kind: {
12192
+ enum: ["slider"]
12193
+ },
12194
+ defaultValue: {
12195
+ type: "number"
12196
+ }
12197
+ },
12198
+ required: ["min", "max", "defaultValue"]
12199
+ },
12200
+ {
12201
+ properties: {
12202
+ kind: {
12203
+ enum: ["timeline"]
12204
+ }
12205
+ },
12206
+ required: ["duration"]
12207
+ },
12208
+ {
12209
+ properties: {
12210
+ kind: {
12211
+ enum: ["toggle"]
12212
+ },
12213
+ defaultValue: {
12214
+ type: "boolean"
12215
+ }
12216
+ },
12217
+ required: ["defaultValue"]
12218
+ },
12219
+ {
12220
+ properties: {
12221
+ kind: {
12222
+ enum: ["xypad"]
12223
+ }
12224
+ },
12225
+ required: ["xMin", "xMax", "yMin", "yMax", "defaultX", "defaultY"]
12226
+ }
12227
+ ]
12228
+ }
12229
+ },
12230
+ formulas: {
12231
+ type: "object",
12232
+ description: '\u3064\u307E\u307F\u306E\u5024\u304B\u3089\u6C7A\u307E\u308B\u5024\u3002 \u540D\u524D\u3092\u9375\u3001\u5F0F\u3092\u5024\u306B\u66F8\u304F\u3002 `values` \u3068\u306F\u7D4C\u8DEF\u304C\u5225\u3067\u3001\u5F0F\u306F\u540D\u524D\u3092\u4E2D\u62EC\u5F27\u3067\u56F2\u308F\u306A\u3044 (\u4F8B "input * 2")\u3002',
12233
+ additionalProperties: {
12234
+ type: "string",
12235
+ minLength: 1,
12236
+ pattern: "\\S"
12237
+ },
12238
+ propertyNames: {
12239
+ pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
12240
+ }
12241
+ },
12242
+ events: {
12243
+ type: "array",
12244
+ description: "\u62BC\u4E0B\u306A\u3069\u306E\u51FA\u6765\u4E8B\u3067\u52D5\u304F\u4ED5\u639B\u3051\u3002 \u76F8\u624B\u306F\u540D\u524D\u3067\u6307\u3059 (box / lane / arrow / diagram \u306E\u3069\u308C\u304B 1 \u3064)\u3002",
12245
+ items: {
12246
+ type: "object",
12247
+ required: ["on", "handler"],
12248
+ additionalProperties: false,
12249
+ properties: {
12250
+ on: {
12251
+ type: "string",
12252
+ enum: [
12253
+ "click",
12254
+ "hover",
12255
+ "double-click",
12256
+ "long-press",
12257
+ "drag",
12258
+ "drop",
12259
+ "keydown",
12260
+ "focus",
12261
+ "blur"
12262
+ ]
12263
+ },
12264
+ handler: {
12265
+ type: "string",
12266
+ minLength: 1,
12267
+ pattern: "\\S"
12268
+ },
12269
+ box: {
12270
+ type: "string",
12271
+ minLength: 1,
12272
+ description: "\u7BB1\u306E\u540D\u524D"
12273
+ },
12274
+ lane: {
12275
+ type: "string",
12276
+ minLength: 1,
12277
+ description: "\u7E26\u5217\u306E\u540D\u524D"
12278
+ },
12279
+ arrow: {
12280
+ type: "string",
12281
+ minLength: 1,
12282
+ pattern: "^(?!.*->.*->)\\s*\\S(?:.*\\S)?\\s*->\\s*\\S(?:.*\\S)?\\s*$",
12283
+ description: "\u77E2\u5370\u3002 `A -> B` \u306E\u5F62\u3067\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
12284
+ },
12285
+ diagram: {
12286
+ const: true,
12287
+ description: "\u56F3\u5168\u4F53\u3092\u6307\u3059"
12288
+ }
12289
+ },
12290
+ oneOf: [
12291
+ {
12292
+ required: ["box"]
12293
+ },
12294
+ {
12295
+ required: ["lane"]
12296
+ },
12297
+ {
12298
+ required: ["arrow"]
12299
+ },
12300
+ {
12301
+ required: ["diagram"]
12302
+ }
12303
+ ]
12304
+ }
12305
+ },
12306
+ scrolls: {
12307
+ type: "object",
12308
+ description: "\u5DFB\u304D\u4E0A\u3052\u306B\u5FDC\u3058\u3066\u9032\u3080\u5024\u3002 \u753B\u9762\u3092\u5DFB\u304D\u4E0A\u3052\u305F\u91CF\u304B\u3089 0 \u304B\u3089 1 \u306E\u9032\u307F\u5177\u5408\u3092\u4F5C\u308B\u3002",
12309
+ propertyNames: {
12310
+ pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
12311
+ },
12312
+ additionalProperties: {
12313
+ type: "object",
12314
+ additionalProperties: false,
12315
+ properties: {
12316
+ start: {
12317
+ type: "number",
12318
+ minimum: 0,
12319
+ maximum: 1,
12320
+ description: "\u9032\u307F\u5177\u5408\u304C 0 \u306B\u306A\u308B\u753B\u9762\u4E0A\u306E\u4F4D\u7F6E (0 \u304C\u4E0A\u7AEF\u30011 \u304C\u4E0B\u7AEF)"
12321
+ },
12322
+ end: {
12323
+ type: "number",
12324
+ minimum: 0,
12325
+ maximum: 1,
12326
+ description: "\u9032\u307F\u5177\u5408\u304C 1 \u306B\u306A\u308B\u753B\u9762\u4E0A\u306E\u4F4D\u7F6E"
12327
+ },
12328
+ scrub: {
12329
+ type: "number",
12330
+ minimum: 0,
12331
+ maximum: 1,
12332
+ description: "\u5DFB\u304D\u4E0A\u3052\u3078\u306E\u8FFD\u968F\u5EA6\u5408\u3044 (0 \u304C\u6BB5\u968E\u7684\u30011 \u304C\u9023\u7D9A)"
12333
+ },
12334
+ label: {
12335
+ type: "string"
12336
+ }
12337
+ }
12338
+ }
10833
12339
  }
10834
12340
  }
10835
12341
  };