@cardenelabs/dragon 0.13.0 → 0.14.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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NODE_KINDS, TONES, layout, applyDerivedValues, diagram, rendersRows, requiredRowsHeight, requiredRowsWidth, sequence, flow, swimlane, er, stateMachine, topology, parseFormula } from '@cardenelabs/cdl';
1
+ import { NODE_KINDS, TONES, parseFormula, extractIdentifiers, inputDefaultValue, layout, applyDerivedValues, diagram, rendersRows, requiredRowsHeight, requiredRowsWidth, sequence, flow, swimlane, er, stateMachine, topology } from '@cardenelabs/cdl';
2
2
 
3
3
  // src/keywords.ts
4
4
  var HEADERS = {
@@ -1752,6 +1752,135 @@ var \u90E8\u54C1\u306E\u7D44\u306E\u8868 = {
1752
1752
  }
1753
1753
  };
1754
1754
 
1755
+ // src/v05/input-table.generated.ts
1756
+ var \u3064\u307E\u307F\u306E\u8868 = {
1757
+ color: {
1758
+ \u5FC5\u9808: ["defaultValue"],
1759
+ \u6B04: {
1760
+ defaultValue: "\u6587\u5B57\u5217",
1761
+ label: "\u6587\u5B57\u5217"
1762
+ }
1763
+ },
1764
+ datetime: {
1765
+ \u5FC5\u9808: ["defaultValue"],
1766
+ \u6B04: {
1767
+ defaultValue: "\u6587\u5B57\u5217",
1768
+ label: "\u6587\u5B57\u5217"
1769
+ }
1770
+ },
1771
+ dropdown: {
1772
+ \u5FC5\u9808: ["options", "defaultValue"],
1773
+ \u6B04: {
1774
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1775
+ defaultValue: "\u6587\u5B57\u5217",
1776
+ label: "\u6587\u5B57\u5217"
1777
+ }
1778
+ },
1779
+ "multi-select": {
1780
+ \u5FC5\u9808: ["options", "defaultValues"],
1781
+ \u6B04: {
1782
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1783
+ defaultValues: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1784
+ label: "\u6587\u5B57\u5217"
1785
+ }
1786
+ },
1787
+ number: {
1788
+ \u5FC5\u9808: ["defaultValue"],
1789
+ \u6B04: {
1790
+ min: "\u6570",
1791
+ max: "\u6570",
1792
+ defaultValue: "\u6570",
1793
+ label: "\u6587\u5B57\u5217"
1794
+ }
1795
+ },
1796
+ radio: {
1797
+ \u5FC5\u9808: ["options", "defaultValue"],
1798
+ \u6B04: {
1799
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1800
+ defaultValue: "\u6587\u5B57\u5217",
1801
+ label: "\u6587\u5B57\u5217"
1802
+ }
1803
+ },
1804
+ range: {
1805
+ \u5FC5\u9808: ["min", "max", "defaultLo", "defaultHi"],
1806
+ \u6B04: {
1807
+ min: "\u6570",
1808
+ max: "\u6570",
1809
+ step: "\u6570",
1810
+ defaultLo: "\u6570",
1811
+ defaultHi: "\u6570",
1812
+ label: "\u6587\u5B57\u5217"
1813
+ }
1814
+ },
1815
+ slider: {
1816
+ \u5FC5\u9808: ["min", "max", "defaultValue"],
1817
+ \u6B04: {
1818
+ min: "\u6570",
1819
+ max: "\u6570",
1820
+ step: "\u6570",
1821
+ defaultValue: "\u6570",
1822
+ label: "\u6587\u5B57\u5217"
1823
+ }
1824
+ },
1825
+ stepper: {
1826
+ \u5FC5\u9808: ["defaultValue"],
1827
+ \u6B04: {
1828
+ min: "\u6570",
1829
+ max: "\u6570",
1830
+ step: "\u6570",
1831
+ defaultValue: "\u6570",
1832
+ label: "\u6587\u5B57\u5217"
1833
+ }
1834
+ },
1835
+ tabs: {
1836
+ \u5FC5\u9808: ["options", "defaultValue"],
1837
+ \u6B04: {
1838
+ options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1839
+ defaultValue: "\u6587\u5B57\u5217",
1840
+ label: "\u6587\u5B57\u5217"
1841
+ }
1842
+ },
1843
+ text: {
1844
+ \u5FC5\u9808: ["defaultValue"],
1845
+ \u6B04: {
1846
+ defaultValue: "\u6587\u5B57\u5217",
1847
+ placeholder: "\u6587\u5B57\u5217",
1848
+ maxLength: "\u6570",
1849
+ label: "\u6587\u5B57\u5217"
1850
+ }
1851
+ },
1852
+ timeline: {
1853
+ \u5FC5\u9808: ["duration"],
1854
+ \u6B04: {
1855
+ duration: "\u6570",
1856
+ autoplay: "\u771F\u507D",
1857
+ loop: "\u771F\u507D",
1858
+ speeds: "\u6570\u306E\u4E26\u3073",
1859
+ defaultSpeedIdx: "\u6570",
1860
+ label: "\u6587\u5B57\u5217"
1861
+ }
1862
+ },
1863
+ toggle: {
1864
+ \u5FC5\u9808: ["defaultValue"],
1865
+ \u6B04: {
1866
+ defaultValue: "\u771F\u507D",
1867
+ label: "\u6587\u5B57\u5217"
1868
+ }
1869
+ },
1870
+ xypad: {
1871
+ \u5FC5\u9808: ["xMin", "xMax", "yMin", "yMax", "defaultX", "defaultY"],
1872
+ \u6B04: {
1873
+ xMin: "\u6570",
1874
+ xMax: "\u6570",
1875
+ yMin: "\u6570",
1876
+ yMax: "\u6570",
1877
+ defaultX: "\u6570",
1878
+ defaultY: "\u6570",
1879
+ label: "\u6587\u5B57\u5217"
1880
+ }
1881
+ }
1882
+ };
1883
+
1755
1884
  // src/v05/parser.ts
1756
1885
  var EDGE_SIDE_VALUES = ["top", "right", "bottom", "left"];
1757
1886
  var TOP_LEVEL_KEYS = [
@@ -1770,7 +1899,15 @@ var TOP_LEVEL_KEYS = [
1770
1899
  // 2 軸で仕分ける図の軸の名前 (#1251)
1771
1900
  "axes",
1772
1901
  // 値を見せる部品 (#1374)
1773
- "readouts"
1902
+ "readouts",
1903
+ // 読む人が動かすつまみ (#1389)
1904
+ "inputs",
1905
+ // つまみの値から決まる値 (#1391)
1906
+ "formulas",
1907
+ // 押下などの出来事で動く仕掛け (#1393)
1908
+ "events",
1909
+ // 巻き上げに応じて進む値 (#1393)
1910
+ "scrolls"
1774
1911
  ];
1775
1912
  var LANE_ID_ENTRY = /^([\p{L}\p{N}_-]+)\s*:\s*\{([^}]*)\}\s*$/u;
1776
1913
  function \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(\u884C) {
@@ -1808,6 +1945,39 @@ function \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(\u884C) {
1808
1945
  }
1809
1946
  return void 0;
1810
1947
  }
1948
+ function \u672B\u5C3E\u306E\u4E2D\u62EC\u5F27\u3092\u5207\u308A\u51FA\u3059(rest) {
1949
+ const t = rest.trimEnd();
1950
+ if (!t.endsWith("}")) return void 0;
1951
+ let \u6DF1\u3055 = 0;
1952
+ let \u5F15\u7528 = null;
1953
+ let \u76F4\u524D = null;
1954
+ let \u59CB = -1;
1955
+ for (let i = 0; i < t.length; i += 1) {
1956
+ const c = t[i];
1957
+ if (\u5F15\u7528 !== null) {
1958
+ if (\u5F15\u7528 === '"' && c === "\\" && i + 1 < t.length) {
1959
+ i += 1;
1960
+ continue;
1961
+ }
1962
+ if (c === \u5F15\u7528) \u5F15\u7528 = null;
1963
+ continue;
1964
+ }
1965
+ if ((c === '"' || c === "'") && (\u76F4\u524D === null || ":,{[".includes(\u76F4\u524D))) {
1966
+ \u5F15\u7528 = c;
1967
+ \u76F4\u524D = c;
1968
+ continue;
1969
+ }
1970
+ if (c === "{") {
1971
+ if (\u6DF1\u3055 === 0) \u59CB = i;
1972
+ \u6DF1\u3055 += 1;
1973
+ } else if (c === "}") {
1974
+ \u6DF1\u3055 -= 1;
1975
+ if (\u6DF1\u3055 === 0 && i === t.length - 1) return { \u524D: t.slice(0, \u59CB), \u4E2D\u8EAB: t.slice(\u59CB + 1, i) };
1976
+ }
1977
+ if (!/\s/u.test(c)) \u76F4\u524D = c;
1978
+ }
1979
+ return void 0;
1980
+ }
1811
1981
  function isTopLevelKey(key) {
1812
1982
  return TOP_LEVEL_KEYS.includes(key);
1813
1983
  }
@@ -1901,6 +2071,11 @@ function parseTextDslV05(src) {
1901
2071
  let viewport = void 0;
1902
2072
  let lanesMap = void 0;
1903
2073
  let readoutsList = void 0;
2074
+ let inputsList = void 0;
2075
+ let formulasList = void 0;
2076
+ let eventsList = void 0;
2077
+ let scrollsList = void 0;
2078
+ let scrollLines = /* @__PURE__ */ new Map();
1904
2079
  let groupsMap = void 0;
1905
2080
  let i = 0;
1906
2081
  while (i < lines.length) {
@@ -2160,6 +2335,112 @@ function parseTextDslV05(src) {
2160
2335
  i = next;
2161
2336
  continue;
2162
2337
  }
2338
+ if (head.key === "inputs") {
2339
+ if (head.value !== null && head.value.trim() !== "") {
2340
+ errors.push({
2341
+ line: line.no,
2342
+ message: "inputs \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2343
+ 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"
2344
+ });
2345
+ i += 1;
2346
+ continue;
2347
+ }
2348
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2349
+ inputsList = [];
2350
+ for (const it of items) {
2351
+ const m = \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(it.trimmed);
2352
+ if (m) {
2353
+ const \u8AAD\u3081\u305F = \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(m[0], m[1], it.no, errors);
2354
+ if (\u8AAD\u3081\u305F) inputsList.push(\u8AAD\u3081\u305F);
2355
+ } else {
2356
+ errors.push({
2357
+ line: it.no,
2358
+ message: `invalid input entry: "${it.trimmed}"`,
2359
+ hint: "use `id: { kind: slider, min: 0, max: 100, defaultValue: 50 }`"
2360
+ });
2361
+ }
2362
+ }
2363
+ i = next;
2364
+ continue;
2365
+ }
2366
+ if (head.key === "formulas") {
2367
+ if (head.value !== null && head.value.trim() !== "") {
2368
+ errors.push({
2369
+ line: line.no,
2370
+ message: "formulas \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2371
+ 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'
2372
+ });
2373
+ i += 1;
2374
+ continue;
2375
+ }
2376
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2377
+ formulasList = [];
2378
+ for (const it of items) {
2379
+ const f = \u5F0F\u3068\u3057\u3066\u8AAD\u3080(it.trimmed.replace(/^-\s*/, ""), it.no, errors);
2380
+ if (f) formulasList.push(f);
2381
+ }
2382
+ i = next;
2383
+ continue;
2384
+ }
2385
+ if (head.key === "events") {
2386
+ if (head.value !== null && head.value.trim() !== "") {
2387
+ errors.push({
2388
+ line: line.no,
2389
+ message: "events \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2390
+ hint: "\u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `- { on: click, box: Button, handler: toggle }` \u306E\u5F62\u3067\u4E26\u3079\u308B"
2391
+ });
2392
+ i += 1;
2393
+ continue;
2394
+ }
2395
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2396
+ eventsList = [];
2397
+ for (const it of items) {
2398
+ const e = \u51FA\u6765\u4E8B\u3068\u3057\u3066\u8AAD\u3080(it.trimmed.replace(/^-\s*/, ""), it.no, errors);
2399
+ if (e) eventsList.push(e);
2400
+ }
2401
+ i = next;
2402
+ continue;
2403
+ }
2404
+ if (head.key === "scrolls") {
2405
+ if (head.value !== null && head.value.trim() !== "") {
2406
+ errors.push({
2407
+ line: line.no,
2408
+ message: "scrolls \u306F 1 \u884C\u306B\u307E\u3068\u3081\u3066\u66F8\u3051\u306A\u3044",
2409
+ hint: "\u6B21\u306E\u884C\u304B\u3089\u5B57\u4E0B\u3052\u3057\u3066 `intro: { start: 0.9, end: 0.1 }` \u306E\u5F62\u3067\u4E26\u3079\u308B"
2410
+ });
2411
+ i += 1;
2412
+ continue;
2413
+ }
2414
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2415
+ scrollsList = [];
2416
+ scrollLines = /* @__PURE__ */ new Map();
2417
+ for (const it of items) {
2418
+ const m = \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(it.trimmed);
2419
+ if (m) {
2420
+ const \u8AAD\u3081\u305F = \u5DFB\u304D\u4E0A\u3052\u3068\u3057\u3066\u8AAD\u3080(m[0], m[1], it.no, errors);
2421
+ if (\u8AAD\u3081\u305F) {
2422
+ if (scrollLines.has(\u8AAD\u3081\u305F.id)) {
2423
+ errors.push({
2424
+ line: it.no,
2425
+ message: `\u5DFB\u304D\u4E0A\u3052\u306E\u540D\u524D "${\u8AAD\u3081\u305F.id}" \u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059`,
2426
+ hint: "scrolls \u306E\u540D\u524D\u306F 1 \u5EA6\u3060\u3051\u66F8\u304F"
2427
+ });
2428
+ } else {
2429
+ scrollsList.push(\u8AAD\u3081\u305F);
2430
+ scrollLines.set(\u8AAD\u3081\u305F.id, it.no);
2431
+ }
2432
+ }
2433
+ } else {
2434
+ errors.push({
2435
+ line: it.no,
2436
+ message: `invalid scroll entry: "${it.trimmed}"`,
2437
+ hint: "use `id: { start: 0.9, end: 0.1, scrub: 1 }`"
2438
+ });
2439
+ }
2440
+ }
2441
+ i = next;
2442
+ continue;
2443
+ }
2163
2444
  if (head.key === "groups") {
2164
2445
  const { items, next } = collectIndentedList(lines, i + 1, line.indent);
2165
2446
  groupsMap = {};
@@ -2196,6 +2477,18 @@ function parseTextDslV05(src) {
2196
2477
  message: "type is required",
2197
2478
  hint: "add `type: sequence|flow|swimlane|er|state|topology|solidity|gantt|class|pie|c4|mind`"
2198
2479
  });
2480
+ const \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D = /* @__PURE__ */ new Set([
2481
+ ...(inputsList ?? []).map((input) => input.id),
2482
+ ...(formulasList ?? []).map((formula) => formula.id)
2483
+ ]);
2484
+ for (const scroll of scrollsList ?? []) {
2485
+ if (!\u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.has(scroll.id)) continue;
2486
+ errors.push({
2487
+ line: scrollLines.get(scroll.id) ?? 1,
2488
+ message: `\u5DFB\u304D\u4E0A\u3052\u306E\u540D\u524D "${scroll.id}" \u304C inputs \u307E\u305F\u306F formulas \u3068\u91CD\u306A\u3063\u3066\u3044\u307E\u3059`,
2489
+ hint: "inputs / formulas / scrolls \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
2490
+ });
2491
+ }
2199
2492
  if (errors.length > 0) return { ok: false, errors };
2200
2493
  return {
2201
2494
  ok: true,
@@ -2211,6 +2504,10 @@ function parseTextDslV05(src) {
2211
2504
  viewport,
2212
2505
  lanes: lanesMap,
2213
2506
  readouts: readoutsList,
2507
+ inputs: inputsList,
2508
+ formulas: formulasList,
2509
+ events: eventsList,
2510
+ scrolls: scrollsList,
2214
2511
  groups: groupsMap,
2215
2512
  pos: { line: 1 }
2216
2513
  }
@@ -2563,6 +2860,18 @@ function \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, \u63A5\u
2563
2860
  out[\u6B04] = n !== void 0 ? n : \u5024;
2564
2861
  } else if (\u5F62 === "\u6587\u5B57\u5217\u306E\u4E26\u3073") {
2565
2862
  out[\u6B04] = \u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2863
+ } else if (\u5F62 === "\u6570\u306E\u4E26\u3073") {
2864
+ const \u751F = \u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2865
+ const \u6570 = \u751F.map((x) => numberOrUndef(x));
2866
+ if (\u6570.some((n) => n === void 0)) {
2867
+ errors.push({
2868
+ line,
2869
+ message: `${\u63A5\u982D}${\u6B04} \u306B\u6570\u3067\u306A\u3044\u5024\u304C\u3042\u308A\u307E\u3059: "${\u5024}"`,
2870
+ hint: "`[0.5, 1, 2, 4]` \u306E\u5F62\u3067\u6570\u3060\u3051\u3092\u4E26\u3079\u308B"
2871
+ });
2872
+ } else {
2873
+ out[\u6B04] = \u6570;
2874
+ }
2566
2875
  } else if (\u5F62 === "\u7D44\u306E\u4E26\u3073") {
2567
2876
  const \u7D44 = \u7D44\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
2568
2877
  if (\u7D44 !== void 0) out[\u6B04] = \u7D44;
@@ -2619,11 +2928,49 @@ function \u51FA\u3059\u6761\u4EF6\u3068\u3057\u3066\u8AAD\u3080(raw, line, error
2619
2928
  }
2620
2929
  return \u5024;
2621
2930
  }
2931
+ function \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(raw, \u63A5\u982D, line, errors) {
2932
+ if (raw === void 0) return void 0;
2933
+ const \u5024 = raw.trim();
2934
+ if (\u5024 === "") {
2935
+ errors.push({
2936
+ line,
2937
+ message: `${\u63A5\u982D}\u304C\u7A7A\u3067\u3059`,
2938
+ hint: '`{\u72B6\u614B\u306E\u540D\u524D}` \u304B\u6570\u3092\u66F8\u304F (\u4F8B `opacity: "{fade}"` / `opacity: 0.5`)'
2939
+ });
2940
+ return void 0;
2941
+ }
2942
+ const n = numberOrUndef(\u5024);
2943
+ return n !== void 0 ? n : \u5024;
2944
+ }
2945
+ function \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(raw, \u63A5\u982D, line, errors) {
2946
+ if (raw === void 0) return void 0;
2947
+ const \u5024 = raw.trim();
2948
+ if (\u5024 === "") {
2949
+ errors.push({
2950
+ line,
2951
+ message: `${\u63A5\u982D}\u304C\u7A7A\u3067\u3059`,
2952
+ hint: '`{\u72B6\u614B\u306E\u540D\u524D}` \u3092\u66F8\u304F (\u4F8B `wBind: "{barW}"`)'
2953
+ });
2954
+ return void 0;
2955
+ }
2956
+ return \u5024;
2957
+ }
2958
+ var \u5024\u306B\u8FFD\u968F\u3059\u308B\u7BB1\u306E\u6B04 = [
2959
+ "wBind",
2960
+ "hBind",
2961
+ "opacity",
2962
+ "renderOffsetX",
2963
+ "renderOffsetY"
2964
+ ];
2965
+ var \u7A7A\u3092\u77E5\u3089\u305B\u308B\u7BB1\u306E\u6B04 = new Set(\u5024\u306B\u8FFD\u968F\u3059\u308B\u7BB1\u306E\u6B04);
2966
+ function \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u8868, kind) {
2967
+ return Object.hasOwn(\u8868, kind) ? \u8868[kind] : void 0;
2968
+ }
2622
2969
  function \u56F3\u5F62\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
2623
2970
  const \u4E2D\u8EAB = raw.trim().replace(/^\{|\}$/g, "");
2624
2971
  const opts = parseInlineMapping(\u4E2D\u8EAB);
2625
2972
  const kind = (opts.kind ?? "").toLowerCase();
2626
- const \u5B9A\u7FA9 = \u56F3\u5F62\u306E\u8868[kind];
2973
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u56F3\u5F62\u306E\u8868, kind);
2627
2974
  if (\u5B9A\u7FA9 === void 0) {
2628
2975
  errors.push({
2629
2976
  line,
@@ -2639,7 +2986,7 @@ function \u56F3\u5F62\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
2639
2986
  function \u90E8\u54C1\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
2640
2987
  const opts = parseInlineMapping(raw);
2641
2988
  const kind = (opts.kind ?? "").toLowerCase();
2642
- const \u5B9A\u7FA9 = \u90E8\u54C1\u306E\u8868[kind];
2989
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u90E8\u54C1\u306E\u8868, kind);
2643
2990
  if (\u5B9A\u7FA9 === void 0) {
2644
2991
  errors.push({
2645
2992
  line,
@@ -2653,6 +3000,194 @@ function \u90E8\u54C1\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
2653
3000
  for (const \u6B04 of \u5B9A\u7FA9.\u5FC5\u9808) if (\u8AAD\u3081\u305F[\u6B04] === void 0) return void 0;
2654
3001
  return { id, kind, ...\u8AAD\u3081\u305F };
2655
3002
  }
3003
+ var EVENT_KINDS = [
3004
+ "click",
3005
+ "hover",
3006
+ "double-click",
3007
+ "long-press",
3008
+ "drag",
3009
+ "drop",
3010
+ "keydown",
3011
+ "focus",
3012
+ "blur"
3013
+ ];
3014
+ var EVENT_TARGET_KEYS = ["box", "lane", "arrow", "diagram"];
3015
+ function \u51FA\u6765\u4E8B\u3068\u3057\u3066\u8AAD\u3080(raw, line, errors) {
3016
+ const t = raw.trim();
3017
+ if (!t.startsWith("{") || !t.endsWith("}")) {
3018
+ errors.push({
3019
+ line,
3020
+ message: `\u51FA\u6765\u4E8B\u306E\u884C\u304C\u8AAD\u3081\u307E\u305B\u3093: "${t}"`,
3021
+ hint: "`- { on: click, box: Button, handler: toggle }` \u306E\u5F62\u3067\u66F8\u304F"
3022
+ });
3023
+ return void 0;
3024
+ }
3025
+ const opts = parseInlineMapping(t.slice(1, -1));
3026
+ for (const k of Object.keys(opts)) {
3027
+ if (k === "on" || k === "handler" || EVENT_TARGET_KEYS.includes(k))
3028
+ continue;
3029
+ errors.push({
3030
+ line,
3031
+ message: `\u51FA\u6765\u4E8B\u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${k}"`,
3032
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = on, handler, ${EVENT_TARGET_KEYS.join(", ")}`
3033
+ });
3034
+ return void 0;
3035
+ }
3036
+ const on = opts.on ?? "";
3037
+ if (!EVENT_KINDS.includes(on)) {
3038
+ errors.push({
3039
+ line,
3040
+ message: `\u51FA\u6765\u4E8B\u306E\u7A2E\u985E\u304C\u8AAD\u3081\u307E\u305B\u3093: "${on}"`,
3041
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${EVENT_KINDS.join(", ")}`
3042
+ });
3043
+ return void 0;
3044
+ }
3045
+ const handlerId = (opts.handler ?? "").trim();
3046
+ if (handlerId === "") {
3047
+ errors.push({
3048
+ line,
3049
+ message: "\u51FA\u6765\u4E8B\u306E handler \u304C\u7A7A\u3067\u3059",
3050
+ hint: "`handler: toggle-active` \u306E\u3088\u3046\u306B\u3001\u547C\u3073\u51FA\u3059\u4ED5\u639B\u3051\u306E\u540D\u524D\u3092\u66F8\u304F"
3051
+ });
3052
+ return void 0;
3053
+ }
3054
+ const \u66F8\u3044\u305F\u76F8\u624B = EVENT_TARGET_KEYS.filter((k) => opts[k] !== void 0);
3055
+ if (\u66F8\u3044\u305F\u76F8\u624B.length !== 1) {
3056
+ errors.push({
3057
+ line,
3058
+ 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(", ")}`,
3059
+ hint: `${EVENT_TARGET_KEYS.join(" / ")} \u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u3092\u66F8\u304F`
3060
+ });
3061
+ return void 0;
3062
+ }
3063
+ const \u9375 = \u66F8\u3044\u305F\u76F8\u624B[0];
3064
+ const \u5024 = (opts[\u9375] ?? "").trim();
3065
+ let target;
3066
+ if (\u9375 === "diagram") {
3067
+ if (\u5024 !== "true") {
3068
+ errors.push({
3069
+ line,
3070
+ message: `\u51FA\u6765\u4E8B\u306E diagram \u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u5024}"`,
3071
+ hint: "\u56F3\u5168\u4F53\u3092\u6307\u3059\u6642\u306F `diagram: true` \u3068\u66F8\u304F"
3072
+ });
3073
+ return void 0;
3074
+ }
3075
+ target = { kind: "diagram" };
3076
+ } else if (\u9375 === "arrow") {
3077
+ const m = \u5024.split("->");
3078
+ if (m.length !== 2 || m[0].trim() === "" || m[1].trim() === "") {
3079
+ errors.push({
3080
+ line,
3081
+ message: `\u51FA\u6765\u4E8B\u306E\u77E2\u5370\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u5024}"`,
3082
+ hint: "`arrow: A -> B` \u306E\u5F62\u3067\u3001\u77E2\u5370\u306E\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
3083
+ });
3084
+ return void 0;
3085
+ }
3086
+ target = { kind: "edge", from: stripQuotes(m[0].trim()), to: stripQuotes(m[1].trim()) };
3087
+ } else {
3088
+ if (\u5024 === "") {
3089
+ errors.push({
3090
+ line,
3091
+ message: `\u51FA\u6765\u4E8B\u306E ${\u9375} \u304C\u7A7A\u3067\u3059`,
3092
+ hint: "\u6307\u3059\u76F8\u624B\u306E\u540D\u524D\u3092\u66F8\u304F"
3093
+ });
3094
+ return void 0;
3095
+ }
3096
+ target = { kind: \u9375 === "box" ? "node" : "lane", name: stripQuotes(\u5024) };
3097
+ }
3098
+ return { event: on, target, handlerId, pos: { line } };
3099
+ }
3100
+ var SCROLL_VALUE_KINDS = {
3101
+ start: "\u6570",
3102
+ end: "\u6570",
3103
+ scrub: "\u6570"
3104
+ };
3105
+ function \u5DFB\u304D\u4E0A\u3052\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
3106
+ if (!isValueName(id)) {
3107
+ errors.push({ line, ...valueNameIssue(id) });
3108
+ return void 0;
3109
+ }
3110
+ const opts = parseInlineMapping(raw);
3111
+ const \u4F7F\u3048\u308B = [...Object.keys(SCROLL_VALUE_KINDS), "label"];
3112
+ for (const k of Object.keys(opts)) {
3113
+ if (\u4F7F\u3048\u308B.includes(k)) continue;
3114
+ errors.push({
3115
+ line,
3116
+ message: `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${k}"`,
3117
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")}`
3118
+ });
3119
+ return void 0;
3120
+ }
3121
+ const \u6570 = \u8868\u3067\u8AAD\u3080(SCROLL_VALUE_KINDS, opts, `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E `, line, errors);
3122
+ for (const \u6B04 of ["start", "end", "scrub"]) {
3123
+ const \u5024 = \u6570[\u6B04];
3124
+ if (\u5024 === void 0 || \u5024 >= 0 && \u5024 <= 1) continue;
3125
+ errors.push({
3126
+ line,
3127
+ message: `\u5DFB\u304D\u4E0A\u3052 ${id} \u306E ${\u6B04} \u306F 0 \u304B\u3089 1 \u306E\u9593\u3067\u66F8\u304D\u307E\u3059: "${\u5024}"`,
3128
+ 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"
3129
+ });
3130
+ }
3131
+ return {
3132
+ id,
3133
+ ...\u6570.start !== void 0 ? { start: \u6570.start } : {},
3134
+ ...\u6570.end !== void 0 ? { end: \u6570.end } : {},
3135
+ ...\u6570.scrub !== void 0 ? { scrub: \u6570.scrub } : {},
3136
+ ...opts.label !== void 0 ? { label: opts.label } : {}
3137
+ };
3138
+ }
3139
+ function \u5F0F\u3068\u3057\u3066\u8AAD\u3080(\u884C, line, errors) {
3140
+ const c = \u884C.indexOf(":");
3141
+ if (c < 0) {
3142
+ errors.push({
3143
+ line,
3144
+ message: `\u5F0F\u306E\u884C\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u884C}"`,
3145
+ hint: '`\u540D\u524D: "\u5F0F"` \u306E\u5F62\u3067\u66F8\u304F (\u4F8B `doubled: "input * 2"`)'
3146
+ });
3147
+ return void 0;
3148
+ }
3149
+ const \u540D\u524D = \u884C.slice(0, c).trim();
3150
+ const \u5F0F = stripQuotes(\u884C.slice(c + 1).trim());
3151
+ if (!isValueName(\u540D\u524D)) {
3152
+ errors.push({ line, ...valueNameIssue(\u540D\u524D) });
3153
+ return void 0;
3154
+ }
3155
+ if (\u5F0F === "") {
3156
+ errors.push({
3157
+ line,
3158
+ message: `\u5F0F "${\u540D\u524D}" \u304C\u7A7A\u3067\u3059`,
3159
+ hint: '`doubled: "input * 2"` \u306E\u3088\u3046\u306B\u5F0F\u3092\u66F8\u304F'
3160
+ });
3161
+ return void 0;
3162
+ }
3163
+ try {
3164
+ parseFormula(\u5F0F);
3165
+ } catch (e) {
3166
+ errors.push({
3167
+ line,
3168
+ message: `\u5F0F "${\u540D\u524D}" \u3092\u8AAD\u3081\u307E\u305B\u3093: ${e.message}`,
3169
+ 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"
3170
+ });
3171
+ return void 0;
3172
+ }
3173
+ return { id: \u540D\u524D, expression: \u5F0F, pos: { line } };
3174
+ }
3175
+ function \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
3176
+ const opts = parseInlineMapping(raw);
3177
+ const kind = (opts.kind ?? "").toLowerCase();
3178
+ const \u5B9A\u7FA9 = \u8868\u304B\u3089\u5B9A\u7FA9\u3092\u5F15\u304F(\u3064\u307E\u307F\u306E\u8868, kind);
3179
+ if (\u5B9A\u7FA9 === void 0) {
3180
+ errors.push({
3181
+ line,
3182
+ message: `\u3064\u307E\u307F\u306E\u7A2E\u985E\u304C\u8AAD\u3081\u307E\u305B\u3093: "${opts.kind ?? ""}"`,
3183
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${Object.keys(\u3064\u307E\u307F\u306E\u8868).join(", ")}`
3184
+ });
3185
+ return void 0;
3186
+ }
3187
+ const \u8AAD\u3081\u305F = \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, `\u3064\u307E\u307F ${id} \u306E `, line, errors);
3188
+ for (const \u6B04 of \u5B9A\u7FA9.\u5FC5\u9808) if (\u8AAD\u3081\u305F[\u6B04] === void 0) return void 0;
3189
+ return { id, kind, ...\u8AAD\u3081\u305F };
3190
+ }
2656
3191
  var ACTOR_NODE_VALUE_KINDS = {
2657
3192
  posX: "\u6570",
2658
3193
  posY: "\u6570",
@@ -2852,6 +3387,7 @@ function applyContinuationLines(actor, rest, errors) {
2852
3387
  const scaleLines = /* @__PURE__ */ new Map();
2853
3388
  const \u56F3\u7A2E\u3054\u3068\u306E\u6B04 = /* @__PURE__ */ new Map();
2854
3389
  const unknownKeys = [];
3390
+ const \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024 = /* @__PURE__ */ new Map();
2855
3391
  for (const ln of rest) {
2856
3392
  const idx = ln.trimmed.indexOf(":");
2857
3393
  if (idx < 0) continue;
@@ -2864,7 +3400,7 @@ function applyContinuationLines(actor, rest, errors) {
2864
3400
  unknownKeys.push({ key, line: ln.no });
2865
3401
  continue;
2866
3402
  }
2867
- if (!raw) continue;
3403
+ if (!raw && !\u7A7A\u3092\u77E5\u3089\u305B\u308B\u7BB1\u306E\u6B04.has(key)) continue;
2868
3404
  if (COLOR_KEYS.has(key)) {
2869
3405
  const { tone, hex } = splitColorValue(raw);
2870
3406
  if (tone) out.tone = tone;
@@ -2903,6 +3439,23 @@ function applyContinuationLines(actor, rest, errors) {
2903
3439
  case "\u984C":
2904
3440
  out.title = stripQuotes(raw);
2905
3441
  break;
3442
+ /*
3443
+ * 値に追随する 5 欄 (#1392)。 日本語の別名は置かない = 描画側の欄名がそのまま
3444
+ * 状態の名前と並ぶ場所なので、英字 1 種に絞って書き方の揺れを作らない。
3445
+ *
3446
+ * **ここでは読まずに書かれた字だけを控える**。 見本 (parts) では同じ名前が状態の
3447
+ * 上書きになり、中括弧の形は生の字を `coerceStateValue` に通す。 ここで先に読むと
3448
+ * `wBind: 120` が中括弧では数、縦に並べると文字列になって書き方で割れる。
3449
+ * 見本かどうかは `kind` で決まり、それが後ろの行に書かれることがあるため、
3450
+ * 全行を読み終えてから振り分ける。
3451
+ */
3452
+ case "wBind":
3453
+ case "hBind":
3454
+ case "opacity":
3455
+ case "renderOffsetX":
3456
+ case "renderOffsetY":
3457
+ \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024.set(key, { \u5024: stripQuotes(raw), line: ln.no });
3458
+ break;
2906
3459
  case "rows":
2907
3460
  case "\u884C":
2908
3461
  out.rows = raw.replace(/^\[|\]$/g, "").split(/,(?![^[]*\])/).map((x) => stripQuotes(x.trim())).filter(Boolean);
@@ -2990,9 +3543,20 @@ function applyContinuationLines(actor, rest, errors) {
2990
3543
  else out.end = v;
2991
3544
  }
2992
3545
  if (out.partId !== void 0) {
3546
+ for (const [\u6B04, { \u5024 }] of \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024) {
3547
+ state[\u6B04] = coerceStateValue(\u5024);
3548
+ touchedState = true;
3549
+ }
2993
3550
  if (touchedState) out.stateOverride = state;
2994
3551
  return out;
2995
3552
  }
3553
+ for (const [\u6B04, { \u5024, line }] of \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024) {
3554
+ if (\u6B04 === "wBind" || \u6B04 === "hBind") {
3555
+ out[\u6B04] = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(\u5024, `\u7BB1\u306E ${\u6B04} `, line, errors);
3556
+ } else if (\u6B04 === "opacity" || \u6B04 === "renderOffsetX" || \u6B04 === "renderOffsetY") {
3557
+ out[\u6B04] = \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(\u5024, `\u7BB1\u306E ${\u6B04} `, line, errors);
3558
+ }
3559
+ }
2996
3560
  for (const u of unknownKeys) {
2997
3561
  errors.push({
2998
3562
  line: u.line,
@@ -3021,6 +3585,12 @@ var ACTOR_ITEM_KEYS = /* @__PURE__ */ new Set([
3021
3585
  // 箱に出す題 (#1381)
3022
3586
  "title",
3023
3587
  "\u984C",
3588
+ // 値に追随する 5 欄 (#1392)
3589
+ "wBind",
3590
+ "hBind",
3591
+ "opacity",
3592
+ "renderOffsetX",
3593
+ "renderOffsetY",
3024
3594
  "\u4F4D\u7F6E",
3025
3595
  "pos",
3026
3596
  "posX",
@@ -3272,6 +3842,12 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
3272
3842
  "visibleIf",
3273
3843
  // 箱に出す題 (#1381)。 名前と切り離して書ける
3274
3844
  "title",
3845
+ // 値に追随する 5 欄 (#1392)
3846
+ "wBind",
3847
+ "hBind",
3848
+ "opacity",
3849
+ "renderOffsetX",
3850
+ "renderOffsetY",
3275
3851
  // 倍率は別経路 (`reportScaleOnNonPart`) が知らせる。 ここでも読める扱いにしないと
3276
3852
  // 同じ名前で 2 度知らせることになる
3277
3853
  "scale",
@@ -3279,12 +3855,24 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
3279
3855
  // 英語が読める欄の日本語別名 (#1301)。 一覧は `INLINE_ACTOR_ALIASES` が持つ
3280
3856
  ...Object.keys(INLINE_ACTOR_ALIASES)
3281
3857
  ]);
3858
+ var EDGE_BIND_INLINE_READERS = {
3859
+ widthBind: (v) => v,
3860
+ strokeBind: (v) => v,
3861
+ dashOffsetBind: (v) => v
3862
+ };
3282
3863
  var FLOW_INLINE_READERS = {
3283
3864
  sub: (v) => v,
3284
3865
  guard: (v) => v,
3285
3866
  cardinality: (v) => v,
3286
3867
  // 矢印がどの辺から出るか (#1385)。 描画側は 4 方向を取り、書かなければ自動で選ぶ
3287
3868
  side: (v) => v !== void 0 && EDGE_SIDE_VALUES.includes(v) ? v : void 0,
3869
+ /*
3870
+ * 矢印を値に追随させる 3 欄 (#1396)。 箱の `wBind` (#1392) と同じく文字列だけを取る。
3871
+ *
3872
+ * ここでは字をそのまま通し、空かどうかは呼出側が知らせる (表の読み手は行番号を
3873
+ * 持たないため、知らせを出せる場所で見る)。
3874
+ */
3875
+ ...EDGE_BIND_INLINE_READERS,
3288
3876
  // 数と真偽の欄は `FLOW_INLINE_VALUE_KINDS` の表が読む (#1306)。 ここでは名前だけを持つ =
3289
3877
  // 読める欄の一覧 (`FLOW_INLINE_KEYS`) は本表から導くため、載せないと欄ごと消える
3290
3878
  labelOffsetX: null,
@@ -3350,6 +3938,13 @@ function parseActor2(line, errors) {
3350
3938
  visibleIf: isPart ? void 0 : \u51FA\u3059\u6761\u4EF6\u3068\u3057\u3066\u8AAD\u3080(opts.visibleIf, line.no, errors),
3351
3939
  // 箱に出す題 (#1381)。 空文字も意味を持つ (題を出さない箱) ため undefined と分ける
3352
3940
  title: isPart ? void 0 : opts.title,
3941
+ // 値に追随する 5 欄 (#1392)。 図形や出す条件と同じく、パーツでは状態の上書きとして
3942
+ // 意味を持つため横取りしない
3943
+ wBind: isPart ? void 0 : \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(opts.wBind, "\u7BB1\u306E wBind ", line.no, errors),
3944
+ hBind: isPart ? void 0 : \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(opts.hBind, "\u7BB1\u306E hBind ", line.no, errors),
3945
+ opacity: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.opacity, "\u7BB1\u306E opacity ", line.no, errors),
3946
+ renderOffsetX: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.renderOffsetX, "\u7BB1\u306E renderOffsetX ", line.no, errors),
3947
+ renderOffsetY: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.renderOffsetY, "\u7BB1\u306E renderOffsetY ", line.no, errors),
3353
3948
  ...\u8868\u3067\u8AAD\u3080(ACTOR_INLINE_VALUE_KINDS, opts, "\u7BB1\u306E ", line.no, errors),
3354
3949
  // parts では `tone` を状態の上書きとして従来から使えるため、 色として横取りしない
3355
3950
  tone: isPart ? void 0 : resolveTone(opts.tone),
@@ -3408,10 +4003,17 @@ function parseFlowStep(line, no, errors) {
3408
4003
  let tone;
3409
4004
  let style;
3410
4005
  const \u4E2D\u62EC\u5F27 = {};
3411
- const mapMatch = rest.match(/\s*\{([^}]*)\}\s*$/);
4006
+ const \u584A = \u672B\u5C3E\u306E\u4E2D\u62EC\u5F27\u3092\u5207\u308A\u51FA\u3059(rest);
3412
4007
  let \u6570\u3068\u771F\u507D;
3413
- if (mapMatch) {
3414
- const opts = parseInlineMapping(mapMatch[1]);
4008
+ if (\u584A) {
4009
+ const opts = parseInlineMapping(\u584A.\u4E2D\u8EAB);
4010
+ for (const field of splitInlineFields(\u584A.\u4E2D\u8EAB)) {
4011
+ const idx = field.indexOf(":");
4012
+ if (idx < 0) continue;
4013
+ const key = field.slice(0, idx).trim();
4014
+ if (!Object.hasOwn(EDGE_BIND_INLINE_READERS, key)) continue;
4015
+ opts[key] = stripQuotes(field.slice(idx + 1).trim());
4016
+ }
3415
4017
  for (const k of FLOW_INLINE_KEYS) {
3416
4018
  const \u8AAD\u307F\u624B = FLOW_INLINE_READERS[k];
3417
4019
  if (\u8AAD\u307F\u624B === null) continue;
@@ -3425,12 +4027,30 @@ function parseFlowStep(line, no, errors) {
3425
4027
  });
3426
4028
  }
3427
4029
  \u6570\u3068\u771F\u507D = \u8868\u3067\u8AAD\u3080(FLOW_INLINE_VALUE_KINDS, opts, "\u77E2\u5370\u306E ", line.no, errors);
3428
- rest = rest.slice(0, mapMatch.index ?? 0).trim();
4030
+ rest = \u584A.\u524D.trim();
3429
4031
  }
3430
4032
  const sub = \u4E2D\u62EC\u5F27.sub;
3431
4033
  const guard = \u4E2D\u62EC\u5F27.guard;
3432
4034
  const cardinality = \u4E2D\u62EC\u5F27.cardinality;
3433
4035
  const side = \u4E2D\u62EC\u5F27.side;
4036
+ const widthBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4037
+ \u4E2D\u62EC\u5F27.widthBind,
4038
+ "\u77E2\u5370\u306E widthBind ",
4039
+ line.no,
4040
+ errors
4041
+ );
4042
+ const strokeBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4043
+ \u4E2D\u62EC\u5F27.strokeBind,
4044
+ "\u77E2\u5370\u306E strokeBind ",
4045
+ line.no,
4046
+ errors
4047
+ );
4048
+ const dashOffsetBind = \u8FFD\u968F\u3059\u308B\u5927\u304D\u3055\u3068\u3057\u3066\u8AAD\u3080(
4049
+ \u4E2D\u62EC\u5F27.dashOffsetBind,
4050
+ "\u77E2\u5370\u306E dashOffsetBind ",
4051
+ line.no,
4052
+ errors
4053
+ );
3434
4054
  const labelOffsetX = \u6570\u3068\u771F\u507D?.labelOffsetX;
3435
4055
  const labelOffsetY = \u6570\u3068\u771F\u507D?.labelOffsetY;
3436
4056
  const overlay = \u6570\u3068\u771F\u507D?.overlay;
@@ -3482,6 +4102,9 @@ function parseFlowStep(line, no, errors) {
3482
4102
  guard,
3483
4103
  cardinality,
3484
4104
  side,
4105
+ widthBind,
4106
+ strokeBind,
4107
+ dashOffsetBind,
3485
4108
  labelOffsetX,
3486
4109
  labelOffsetY,
3487
4110
  overlay,
@@ -4039,14 +4662,22 @@ var PAINT_KEYS = /* @__PURE__ */ new Set([
4039
4662
  var SAFE_PAINT = "none";
4040
4663
  function stripExternalPaint(diagram2) {
4041
4664
  const stripped = [];
4042
- walk(diagram2, "", false, stripped);
4665
+ walk(diagram2, "", false, stripped, false);
4043
4666
  return stripped;
4044
4667
  }
4045
- function walk(node, path, inStateValue, out) {
4668
+ var INPUT_VALUE_KEYS = /* @__PURE__ */ new Set(["defaultvalue", "defaultvalues", "options"]);
4669
+ function walk(node, path, inStateValue, out, inInputs) {
4046
4670
  if (node === null || typeof node !== "object") return;
4047
4671
  if (Array.isArray(node)) {
4048
4672
  for (let i = 0; i < node.length; i++) {
4049
- walk(node[i], `${path}[${i}]`, inStateValue, out);
4673
+ const here = `${path}[${i}]`;
4674
+ const value = node[i];
4675
+ if (inStateValue && typeof value === "string" && pointsOutside(value)) {
4676
+ node[i] = SAFE_PAINT;
4677
+ out.push({ path: here, value });
4678
+ } else {
4679
+ walk(value, here, inStateValue, out, inInputs);
4680
+ }
4050
4681
  }
4051
4682
  return;
4052
4683
  }
@@ -4054,7 +4685,8 @@ function walk(node, path, inStateValue, out) {
4054
4685
  for (const [key, value] of Object.entries(obj)) {
4055
4686
  const here = path ? `${path}.${key}` : key;
4056
4687
  const lower = key.toLowerCase();
4057
- const nextInState = inStateValue || lower === "states" || lower === "sets" || lower === "tweens";
4688
+ const nextInState = inStateValue || lower === "states" || lower === "sets" || lower === "tweens" || inInputs && INPUT_VALUE_KEYS.has(lower);
4689
+ const nextInInputs = inInputs || lower === "inputs";
4058
4690
  if (typeof value === "string") {
4059
4691
  const isPaint = PAINT_KEYS.has(lower) || nextInState && (lower === "initial" || lower === "to" || lower === "from" || !isReservedStateKey(lower));
4060
4692
  if (isPaint && pointsOutside(value)) {
@@ -4063,7 +4695,7 @@ function walk(node, path, inStateValue, out) {
4063
4695
  }
4064
4696
  continue;
4065
4697
  }
4066
- walk(value, here, nextInState, out);
4698
+ walk(value, here, nextInState, out, nextInInputs);
4067
4699
  }
4068
4700
  }
4069
4701
  function isReservedStateKey(lowerKey) {
@@ -4081,7 +4713,15 @@ function countDocElements(doc) {
4081
4713
  );
4082
4714
  return doc.actors.length + doc.flow.length + phases.length + phaseChildren + (doc.animate?.states.length ?? 0) + (doc.values?.length ?? 0) + // 値を見せる部品も描画時に 1 widget ずつ展開される (#1374)。 数えないと、 actors が
4083
4715
  // 少ないまま readouts だけを大量に並べた入力が組み立て前の上限をすり抜ける。
4084
- (doc.readouts?.length ?? 0) + (doc.groups ? Object.keys(doc.groups).length : 0) + (doc.lanes ? Object.keys(doc.lanes).length : 0);
4716
+ (doc.readouts?.length ?? 0) + // 読む人が動かすつまみも 1 widget ずつ展開される (#1389) readouts と同じ上限で守る。
4717
+ (doc.inputs?.length ?? 0) + /*
4718
+ * 式 (#1391) と、押下 / 巻き上げ (#1393) も数える。
4719
+ *
4720
+ * **図の側 (`countDiagramElements`) は既に数えている**。 記法側だけ数えないと、
4721
+ * 箱が少ないままこれらを大量に並べた入力が組み立て前の上限をすり抜け、
4722
+ * 組み立て終わってから (= 時間をかけてから) 図の側で弾かれる。
4723
+ */
4724
+ (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);
4085
4725
  }
4086
4726
  function countDiagramElements(diagram2) {
4087
4727
  const phases = Array.isArray(diagram2.phases) ? diagram2.phases : [];
@@ -4227,6 +4867,100 @@ function compileToCdl(doc, opts) {
4227
4867
  );
4228
4868
  merged.readouts = [...merged.readouts ?? [], ...ownReadouts];
4229
4869
  }
4870
+ if (doc.inputs && doc.inputs.length > 0) {
4871
+ const ownInputs = doc.inputs.map(
4872
+ (input) => deepRewriteStrings(input, (value) => value)
4873
+ );
4874
+ merged.inputs = [...merged.inputs ?? [], ...ownInputs];
4875
+ }
4876
+ if (doc.formulas && doc.formulas.length > 0) {
4877
+ const ownFormulas = doc.formulas.map((formula) => ({
4878
+ id: formula.id,
4879
+ expression: formula.expression,
4880
+ line: formula.pos?.line ?? 0
4881
+ }));
4882
+ const \u3064\u307E\u307F = new Map((merged.inputs ?? []).map((input) => [input.id, input]));
4883
+ const \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F = new Set((merged.formulas ?? []).map((formula) => formula.id));
4884
+ const \u8F09\u305B\u308B\u5F0F = [...merged.formulas ?? []];
4885
+ for (const formula of ownFormulas) {
4886
+ if (\u3064\u307E\u307F.has(formula.id) || \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(formula.id)) {
4887
+ opts?.onNotice?.({
4888
+ kind: "formula-unresolved",
4889
+ actor: formula.id,
4890
+ line: formula.line,
4891
+ 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`,
4892
+ hint: "`inputs:` \u3068 `formulas:` \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
4893
+ });
4894
+ continue;
4895
+ }
4896
+ let \u540D\u524D\u305F\u3061;
4897
+ try {
4898
+ \u540D\u524D\u305F\u3061 = extractIdentifiers(parseFormula(formula.expression));
4899
+ } catch {
4900
+ continue;
4901
+ }
4902
+ let \u89E3\u3051\u306A\u3044 = false;
4903
+ for (const \u540D of \u540D\u524D\u305F\u3061) {
4904
+ if (\u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(\u540D)) continue;
4905
+ const input = \u3064\u307E\u307F.get(\u540D);
4906
+ if (input) {
4907
+ const \u521D\u671F\u5024 = inputDefaultValue(input);
4908
+ if (typeof \u521D\u671F\u5024 === "number" || typeof \u521D\u671F\u5024 === "boolean") continue;
4909
+ \u89E3\u3051\u306A\u3044 = true;
4910
+ opts?.onNotice?.({
4911
+ kind: "formula-unresolved",
4912
+ actor: formula.id,
4913
+ line: formula.line,
4914
+ 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`,
4915
+ hint: "\u5F0F\u304C\u8AAD\u3081\u308B\u3064\u307E\u307F\u306F slider / number / stepper / timeline / toggle"
4916
+ });
4917
+ continue;
4918
+ }
4919
+ \u89E3\u3051\u306A\u3044 = true;
4920
+ opts?.onNotice?.({
4921
+ kind: "formula-unresolved",
4922
+ actor: formula.id,
4923
+ line: formula.line,
4924
+ 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`,
4925
+ hint: "`inputs:` \u306B\u66F8\u304F\u304B\u3001\u53C2\u7167\u3055\u308C\u308B\u5F0F\u3092\u3053\u306E\u5F0F\u3088\u308A\u524D\u306B\u66F8\u304F"
4926
+ });
4927
+ }
4928
+ if (\u89E3\u3051\u306A\u3044) continue;
4929
+ \u8F09\u305B\u308B\u5F0F.push({ id: formula.id, expression: formula.expression });
4930
+ \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.add(formula.id);
4931
+ }
4932
+ if (\u8F09\u305B\u308B\u5F0F.length > 0) merged.formulas = \u8F09\u305B\u308B\u5F0F;
4933
+ else delete merged.formulas;
4934
+ }
4935
+ if (doc.events && doc.events.length > 0) {
4936
+ const \u8F09\u305B\u308B = [...merged.eventBindings ?? []];
4937
+ for (const e of doc.events) {
4938
+ const \u76F8\u624B = \u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092\u89E3\u304F(merged, doc, e);
4939
+ if (\u76F8\u624B === void 0) {
4940
+ opts?.onNotice?.({
4941
+ kind: "event-target-missing",
4942
+ actor: e.handlerId,
4943
+ line: e.pos.line,
4944
+ message: `\u51FA\u6765\u4E8B "${e.handlerId}" \u304C\u6307\u3059\u76F8\u624B\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093`,
4945
+ hint: "box \u306F\u7BB1\u306E\u540D\u524D\u3001 lane \u306F\u7E26\u5217\u306E\u540D\u524D\u3001 arrow \u306F `A -> B` \u3067\u66F8\u304F"
4946
+ });
4947
+ continue;
4948
+ }
4949
+ \u8F09\u305B\u308B.push({
4950
+ id: `evt-${\u8F09\u305B\u308B.length + 1}`,
4951
+ event: e.event,
4952
+ target: \u76F8\u624B,
4953
+ handlerId: e.handlerId
4954
+ });
4955
+ }
4956
+ if (\u8F09\u305B\u308B.length > 0) merged.eventBindings = \u8F09\u305B\u308B;
4957
+ }
4958
+ if (doc.scrolls && doc.scrolls.length > 0) {
4959
+ merged.scrollTriggers = [
4960
+ ...merged.scrollTriggers ?? [],
4961
+ ...doc.scrolls.map((x) => ({ ...x }))
4962
+ ];
4963
+ }
4230
4964
  const \u5916\u3057\u305F\u90E8\u54C1\u306E\u914D\u8272 = stripExternalReadoutPalettes(merged);
4231
4965
  for (const dropped of [...stripExternalPaint(merged), ...\u5916\u3057\u305F\u90E8\u54C1\u306E\u914D\u8272]) {
4232
4966
  opts?.onNotice?.({
@@ -4561,6 +5295,23 @@ function disambiguateActorIds(doc, onNotice) {
4561
5295
  const from = \u76F4\u3059(s.from);
4562
5296
  const to = \u76F4\u3059(s.to);
4563
5297
  return from === s.from && to === s.to ? s : { ...s, from, to };
5298
+ }),
5299
+ events: doc.events?.map((event) => {
5300
+ const target = event.target;
5301
+ if (target.kind === "node") {
5302
+ const name = \u76F4\u3059(target.name);
5303
+ return name === target.name ? event : { ...event, target: { ...target, name } };
5304
+ }
5305
+ if (target.kind === "edge") {
5306
+ const from = \u76F4\u3059(target.from);
5307
+ const to = \u76F4\u3059(target.to);
5308
+ return from === target.from && to === target.to ? event : { ...event, target: { ...target, from, to } };
5309
+ }
5310
+ if (target.kind === "lane" && (doc.type === "sequence" || doc.type === "solidity")) {
5311
+ const name = \u76F4\u3059(target.name);
5312
+ return name === target.name ? event : { ...event, target: { ...target, name } };
5313
+ }
5314
+ return event;
4564
5315
  })
4565
5316
  };
4566
5317
  if (\u6B21.animate) {
@@ -5602,6 +6353,35 @@ function applyEdgeInlineOptions(diagram2, doc, sourceLines) {
5602
6353
  \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc);
5603
6354
  });
5604
6355
  }
6356
+ function \u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092\u89E3\u304F(diagram2, doc, e) {
6357
+ if (e.target.kind === "diagram") return { kind: "diagram" };
6358
+ if (e.target.kind === "edge") {
6359
+ const from = slugify(e.target.from);
6360
+ const to = slugify(e.target.to);
6361
+ let \u77E2\u5370;
6362
+ if (doc.type === "sequence" || doc.type === "solidity") {
6363
+ const stepIdx = doc.flow.findIndex(
6364
+ (step) => slugify(step.from) === from && slugify(step.to) === to
6365
+ );
6366
+ if (stepIdx >= 0) {
6367
+ \u77E2\u5370 = diagram2.edges.find(
6368
+ (x) => (x.from === `s${stepIdx}-${from}` || x.from === from) && (x.to === `s${stepIdx}-${to}` || x.from === x.to)
6369
+ );
6370
+ }
6371
+ } else {
6372
+ \u77E2\u5370 = diagram2.edges.find((x) => x.from === from && x.to === to);
6373
+ }
6374
+ return \u77E2\u5370 ? { kind: "edge", id: \u77E2\u5370.id } : void 0;
6375
+ }
6376
+ const \u540D = e.target.name;
6377
+ const slug = slugify(\u540D);
6378
+ if (e.target.kind === "node") {
6379
+ const \u7BB1 = diagram2.nodes.find((n) => n.id === slug || n.id === \u540D || n.title === \u540D);
6380
+ return \u7BB1 ? { kind: "node", id: \u7BB1.id } : void 0;
6381
+ }
6382
+ const \u5217 = (diagram2.lanes ?? []).find((l) => l.id === slug || l.id === \u540D || l.label === \u540D);
6383
+ return \u5217 ? { kind: "lane", id: \u5217.id } : void 0;
6384
+ }
5605
6385
  function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
5606
6386
  if (s.sub !== void 0) target.sub = s.sub;
5607
6387
  if (s.guard !== void 0) {
@@ -5618,6 +6398,9 @@ function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
5618
6398
  if (s.labelOffsetX !== void 0) target.labelOffsetX = s.labelOffsetX;
5619
6399
  if (s.labelOffsetY !== void 0) target.labelOffsetY = s.labelOffsetY;
5620
6400
  if (s.overlay !== void 0) target.overlay = s.overlay;
6401
+ if (s.widthBind !== void 0) target.widthBind = s.widthBind;
6402
+ if (s.strokeBind !== void 0) target.strokeBind = s.strokeBind;
6403
+ if (s.dashOffsetBind !== void 0) target.dashOffsetBind = s.dashOffsetBind;
5621
6404
  }
5622
6405
  function \u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc) {
5623
6406
  if (doc.type !== "flow") return false;
@@ -6832,7 +7615,12 @@ var \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u306E\u540D\u524D = {
6832
7615
  nodes: "\u4E2D\u306E\u7BB1\u3054\u3068\u306E\u6307\u5B9A",
6833
7616
  layoutPos: "\u914D\u7F6E\u306E\u305A\u3089\u3057",
6834
7617
  shape: "\u7BB1\u306E\u4E2D\u306E\u56F3\u5F62",
6835
- visibleIf: "\u51FA\u3059\u6761\u4EF6"
7618
+ visibleIf: "\u51FA\u3059\u6761\u4EF6",
7619
+ wBind: "\u5024\u306B\u8FFD\u968F\u3059\u308B\u5927\u304D\u3055",
7620
+ hBind: "\u5024\u306B\u8FFD\u968F\u3059\u308B\u5927\u304D\u3055",
7621
+ opacity: "\u6FC3\u3055",
7622
+ renderOffsetX: "\u63CF\u304F\u6642\u306E\u305A\u3089\u3057",
7623
+ renderOffsetY: "\u63CF\u304F\u6642\u306E\u305A\u3089\u3057"
6836
7624
  };
6837
7625
  function \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u3092\u66F8\u3044\u305F\u304B(a, \u6B04) {
6838
7626
  if (\u6B04 === "kind") return a.kindWritten === true;
@@ -7077,6 +7865,11 @@ function applyV05Extensions(diagram2, doc, \u8FFD\u52A0\u3057\u305F\u7E26\u5217o
7077
7865
  if (footer) footer.visibleIf = a.visibleIf;
7078
7866
  }
7079
7867
  }
7868
+ if (a.wBind !== void 0) node.wBind = a.wBind;
7869
+ if (a.hBind !== void 0) node.hBind = a.hBind;
7870
+ if (a.opacity !== void 0) node.opacity = a.opacity;
7871
+ if (a.renderOffsetX !== void 0) node.renderOffsetX = a.renderOffsetX;
7872
+ if (a.renderOffsetY !== void 0) node.renderOffsetY = a.renderOffsetY;
7080
7873
  }
7081
7874
  }
7082
7875
  alignSeqHeaderHeights(diagram2, doc);
@@ -7535,21 +8328,39 @@ function compileGenericWithAnimate(doc, opts) {
7535
8328
  const { kind, laneWidth } = opts;
7536
8329
  const actorToNodeId = /* @__PURE__ */ new Map();
7537
8330
  if (\u66F8\u3044\u305F\u7E26\u5217\u306B\u7F6E\u304F(kind, doc)) {
7538
- const \u4E26\u3073 = [];
8331
+ const \u4F7F\u3063\u305F = [];
7539
8332
  for (const a of doc.actors) {
7540
8333
  const lid = a.lane;
7541
- if (lid !== void 0 && !\u4E26\u3073.includes(lid)) \u4E26\u3073.push(lid);
8334
+ if (lid !== void 0 && !\u4F7F\u3063\u305F.includes(lid)) \u4F7F\u3063\u305F.push(lid);
7542
8335
  }
8336
+ const \u66F8\u3044\u305F\u9806 = doc.lanes ? Object.keys(doc.lanes) : [];
8337
+ const \u4E26\u3073 = [
8338
+ ...\u66F8\u3044\u305F\u9806.filter((lid) => \u4F7F\u3063\u305F.includes(lid)),
8339
+ ...\u4F7F\u3063\u305F.filter((lid) => !\u66F8\u3044\u305F\u9806.includes(lid))
8340
+ ];
7543
8341
  for (const lid of \u4E26\u3073) {
7544
8342
  b.lane(lid, { width: laneWidth, ...kind === "topology" ? { contain: true } : {} });
7545
8343
  }
7546
- const \u7A4D\u3093\u3060\u6570 = /* @__PURE__ */ new Map();
8344
+ const \u57CB\u307E\u3063\u305F\u6BB5 = /* @__PURE__ */ new Map();
8345
+ const \u57CB\u3081\u308B = (lid, stack) => {
8346
+ const \u96C6\u5408 = \u57CB\u307E\u3063\u305F\u6BB5.get(lid) ?? /* @__PURE__ */ new Set();
8347
+ \u96C6\u5408.add(stack);
8348
+ \u57CB\u307E\u3063\u305F\u6BB5.set(lid, \u96C6\u5408);
8349
+ };
8350
+ for (const a of doc.actors) {
8351
+ if (a.lane !== void 0 && a.stack !== void 0) \u57CB\u3081\u308B(a.lane, a.stack);
8352
+ }
7547
8353
  doc.actors.forEach((a, idx) => {
7548
8354
  const id = slugify(a.name);
7549
8355
  actorToNodeId.set(a.name, id);
7550
8356
  const lid = a.lane;
7551
- const stack = \u7A4D\u3093\u3060\u6570.get(lid) ?? 0;
7552
- \u7A4D\u3093\u3060\u6570.set(lid, stack + 1);
8357
+ let stack = a.stack;
8358
+ if (stack === void 0) {
8359
+ stack = 0;
8360
+ const \u96C6\u5408 = \u57CB\u307E\u3063\u305F\u6BB5.get(lid);
8361
+ while (\u96C6\u5408?.has(stack)) stack += 1;
8362
+ \u57CB\u3081\u308B(lid, stack);
8363
+ }
7553
8364
  b.node(id, { lane: lid, stack, kind: a.kind, title: \u7BB1\u306E\u984C(a) });
7554
8365
  });
7555
8366
  } else if (kind === "flow" || kind === "topology") {
@@ -8267,8 +9078,6 @@ function \u533A\u9593\u306B\u5E83\u3052\u308B(src, tokens) {
8267
9078
  if (\u4F4D\u7F6E < src.length) out.push({ \u6587\u5B57: src.slice(\u4F4D\u7F6E) });
8268
9079
  return out;
8269
9080
  }
8270
-
8271
- // src/json-parser.ts
8272
9081
  var VALID_KIND_SET = NODE_KIND_VALID;
8273
9082
  var VALID_PRESETS = [...PRESET_TYPES];
8274
9083
  var ACCEPTED_KEYS = {
@@ -8286,7 +9095,14 @@ var ACCEPTED_KEYS = {
8286
9095
  "lanes",
8287
9096
  "groups",
8288
9097
  // 値を見せる部品 (#1374)
8289
- "readouts"
9098
+ "readouts",
9099
+ // 読む人が動かすつまみ (#1389)
9100
+ "inputs",
9101
+ // つまみの値から決まる値 (#1391)
9102
+ "formulas",
9103
+ // 押下などの出来事で動く仕掛けと、巻き上げに応じて進む値 (#1393)
9104
+ "events",
9105
+ "scrolls"
8290
9106
  ],
8291
9107
  actor: [
8292
9108
  "name",
@@ -8318,7 +9134,13 @@ var ACCEPTED_KEYS = {
8318
9134
  // その箱を出すかどうかの条件 (#1381)
8319
9135
  "visibleIf",
8320
9136
  // 箱に出す題 (#1381)
8321
- "title"
9137
+ "title",
9138
+ // 値に追随する 5 欄 (#1392)
9139
+ "wBind",
9140
+ "hBind",
9141
+ "opacity",
9142
+ "renderOffsetX",
9143
+ "renderOffsetY"
8322
9144
  ],
8323
9145
  step: [
8324
9146
  "from",
@@ -8331,6 +9153,10 @@ var ACCEPTED_KEYS = {
8331
9153
  "style",
8332
9154
  "guard",
8333
9155
  "cardinality",
9156
+ // 値に追随する 3 欄 (#1396)
9157
+ "widthBind",
9158
+ "strokeBind",
9159
+ "dashOffsetBind",
8334
9160
  "labelOffsetX",
8335
9161
  "labelOffsetY",
8336
9162
  "overlay",
@@ -8361,7 +9187,14 @@ var \u6B04\u306E\u578B\u8868 = {
8361
9187
  lanes: "object",
8362
9188
  groups: "object",
8363
9189
  // 値を見せる部品 (#1374)。 中身は下の検査が種類ごとに見る
8364
- readouts: "\u4E26\u3073"
9190
+ readouts: "\u4E26\u3073",
9191
+ // 読む人が動かすつまみ (#1389)。 部品と同じく中身は下の検査が種類ごとに見る
9192
+ inputs: "\u4E26\u3073",
9193
+ // つまみの値から決まる値 (#1391)。 中身は下の検査が式ごとに見る
9194
+ formulas: "object",
9195
+ // 押下と巻き上げ (#1393)。 中身は下の検査が 1 件ずつ見る
9196
+ events: "\u4E26\u3073",
9197
+ scrolls: "object"
8365
9198
  },
8366
9199
  actor: {
8367
9200
  name: "\u5FC5\u9808\u306E\u975E\u7A7A\u6587\u5B57\u5217",
@@ -8393,7 +9226,13 @@ var \u6B04\u306E\u578B\u8868 = {
8393
9226
  // その箱を出すかどうかの条件 (#1381)
8394
9227
  visibleIf: "\u6587\u5B57\u5217",
8395
9228
  // 箱に出す題 (#1381)
8396
- title: "\u6587\u5B57\u5217"
9229
+ title: "\u6587\u5B57\u5217",
9230
+ // 値に追随する 5 欄 (#1392)。 大きさは文字列だけ、濃さとずらしは数も受ける
9231
+ wBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9232
+ hBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9233
+ opacity: "\u6570\u304B\u6587\u5B57\u5217",
9234
+ renderOffsetX: "\u6570\u304B\u6587\u5B57\u5217",
9235
+ renderOffsetY: "\u6570\u304B\u6587\u5B57\u5217"
8397
9236
  },
8398
9237
  step: {
8399
9238
  from: "\u5FC5\u9808\u306E\u6587\u5B57\u5217",
@@ -8406,6 +9245,10 @@ var \u6B04\u306E\u578B\u8868 = {
8406
9245
  style: "\u7DDA\u7A2E",
8407
9246
  guard: "\u6587\u5B57\u5217",
8408
9247
  cardinality: "\u6587\u5B57\u5217",
9248
+ // 値に追随する 3 欄 (#1396)。 描画側は文字列だけを取る
9249
+ widthBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9250
+ strokeBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9251
+ dashOffsetBind: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
8409
9252
  labelOffsetX: "\u6570",
8410
9253
  labelOffsetY: "\u6570",
8411
9254
  overlay: "\u771F\u507D",
@@ -8466,7 +9309,13 @@ var \u898B\u672C\u306B\u52B9\u304B\u306A\u3044\u6B04 = [
8466
9309
  // その箱を出すかどうかの条件 (#1381)。 見本は自分の出方を持つ
8467
9310
  "visibleIf",
8468
9311
  // 箱に出す題 (#1381)。 見本は自分の題を持つ
8469
- "title"
9312
+ "title",
9313
+ // 値に追随する 5 欄 (#1392)。 見本は自分の大きさと出方を持つ
9314
+ "wBind",
9315
+ "hBind",
9316
+ "opacity",
9317
+ "renderOffsetX",
9318
+ "renderOffsetY"
8470
9319
  ];
8471
9320
  function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8472
9321
  const \u578B\u9055\u3044 = (\u671F\u5F85, \u88DC\u8DB3) => {
@@ -8485,7 +9334,7 @@ function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8485
9334
  return;
8486
9335
  case "\u975E\u7A7A\u306E\u6587\u5B57\u5217":
8487
9336
  if (v === void 0) return;
8488
- if (typeof v !== "string" || v.length === 0) \u578B\u9055\u3044("a non-empty string if present");
9337
+ if (typeof v !== "string" || v.trim().length === 0) \u578B\u9055\u3044("a non-empty string if present");
8489
9338
  return;
8490
9339
  case "\u6587\u5B57\u5217":
8491
9340
  if (v === void 0) return;
@@ -8521,6 +9370,19 @@ function \u5024\u3092\u691C\u67FB(v, \u578B, path, \u540D\u524D, errors) {
8521
9370
  \u578B\u9055\u3044("a finite number", typeof v === "number" ? `got ${String(v)}` : void 0);
8522
9371
  }
8523
9372
  return;
9373
+ case "\u6570\u304B\u6587\u5B57\u5217":
9374
+ if (v === void 0) return;
9375
+ if (typeof v === "string") {
9376
+ if (v.trim().length === 0) \u578B\u9055\u3044("a non-empty string if present");
9377
+ return;
9378
+ }
9379
+ if (typeof v !== "number" || !Number.isFinite(v)) {
9380
+ \u578B\u9055\u3044(
9381
+ "a finite number or a non-empty string if present",
9382
+ typeof v === "number" ? `got ${String(v)}` : void 0
9383
+ );
9384
+ }
9385
+ return;
8524
9386
  case "\u771F\u507D":
8525
9387
  if (v === void 0) return;
8526
9388
  if (typeof v !== "boolean") \u578B\u9055\u3044("true or false if present");
@@ -8698,7 +9560,7 @@ function validateViewport(v, errors) {
8698
9560
  }
8699
9561
  function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path, \u4F55, errors) {
8700
9562
  const kind = typeof o.kind === "string" ? o.kind : "";
8701
- const \u5B9A\u7FA9 = \u8868[kind];
9563
+ const \u5B9A\u7FA9 = Object.hasOwn(\u8868, kind) ? \u8868[kind] : void 0;
8702
9564
  if (\u5B9A\u7FA9 === void 0) {
8703
9565
  errors.push({
8704
9566
  path: `${path}.kind`,
@@ -8720,7 +9582,7 @@ function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path,
8720
9582
  });
8721
9583
  continue;
8722
9584
  }
8723
- 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(
9585
+ 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(
8724
9586
  (x) => typeof x === "object" && x !== null && !Array.isArray(x) && Object.keys(x).length > 0 && Object.values(x).every(
8725
9587
  (y) => typeof y === "string" || typeof y === "number" && Number.isFinite(y)
8726
9588
  )
@@ -8801,6 +9663,238 @@ function validateReadouts(v, errors) {
8801
9663
  }
8802
9664
  });
8803
9665
  }
9666
+ function validateInputs(v, errors) {
9667
+ if (v === void 0) return;
9668
+ if (!Array.isArray(v)) {
9669
+ errors.push({
9670
+ path: "$.inputs",
9671
+ message: "inputs must be an array of input objects",
9672
+ hint: `got ${v === null ? "null" : typeof v}`
9673
+ });
9674
+ return;
9675
+ }
9676
+ v.forEach((r, i) => {
9677
+ const path = `$.inputs[${i}]`;
9678
+ if (!r || typeof r !== "object" || Array.isArray(r)) {
9679
+ errors.push({ path, message: "input must be a plain object", hint: `got ${typeof r}` });
9680
+ return;
9681
+ }
9682
+ const o = r;
9683
+ if (typeof o.id !== "string" || o.id === "") {
9684
+ errors.push({ path: `${path}.id`, message: "id is required", hint: "\u7A7A\u3067\u306A\u3044\u6587\u5B57\u5217\u3067\u66F8\u304F" });
9685
+ }
9686
+ \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u3064\u307E\u307F\u306E\u8868, path, "input", errors);
9687
+ });
9688
+ }
9689
+ function validateFormulas(v, inputs, errors) {
9690
+ if (v === void 0) return;
9691
+ if (!v || typeof v !== "object" || Array.isArray(v)) {
9692
+ errors.push({
9693
+ path: "$.formulas",
9694
+ message: "formulas must be an object of name to expression",
9695
+ hint: `got ${v === null ? "null" : Array.isArray(v) ? "array" : typeof v}`
9696
+ });
9697
+ return;
9698
+ }
9699
+ const \u3064\u307E\u307F = /* @__PURE__ */ new Map();
9700
+ if (Array.isArray(inputs)) {
9701
+ for (const input of inputs) {
9702
+ if (input && typeof input === "object" && !Array.isArray(input)) {
9703
+ const candidate = input;
9704
+ if (typeof candidate.id === "string" && typeof candidate.kind === "string") {
9705
+ \u3064\u307E\u307F.set(candidate.id, candidate.kind);
9706
+ }
9707
+ }
9708
+ }
9709
+ }
9710
+ const \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F = /* @__PURE__ */ new Set();
9711
+ for (const [\u540D\u524D, \u5F0F] of Object.entries(v)) {
9712
+ const path = `$.formulas.${\u540D\u524D}`;
9713
+ if (!isValueName(\u540D\u524D)) {
9714
+ errors.push({ path, ...valueNameIssue(\u540D\u524D) });
9715
+ continue;
9716
+ }
9717
+ if (typeof \u5F0F !== "string" || \u5F0F.trim() === "") {
9718
+ errors.push({
9719
+ path,
9720
+ message: `${\u540D\u524D} must be a non-empty expression string`,
9721
+ hint: `got ${Array.isArray(\u5F0F) ? "array" : \u5F0F === null ? "null" : typeof \u5F0F}`
9722
+ });
9723
+ continue;
9724
+ }
9725
+ try {
9726
+ const names = extractIdentifiers(parseFormula(\u5F0F));
9727
+ if (\u3064\u307E\u307F.has(\u540D\u524D) || \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(\u540D\u524D)) {
9728
+ errors.push({
9729
+ path,
9730
+ message: `${\u540D\u524D} collides with an input or an earlier formula`,
9731
+ hint: "inputs \u3068 formulas \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
9732
+ });
9733
+ continue;
9734
+ }
9735
+ let valid = true;
9736
+ for (const name of names) {
9737
+ if (\u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.has(name)) continue;
9738
+ const kind = \u3064\u307E\u307F.get(name);
9739
+ if (["slider", "number", "stepper", "timeline", "toggle"].includes(kind ?? "")) continue;
9740
+ valid = false;
9741
+ errors.push({
9742
+ path,
9743
+ message: `${\u540D\u524D} references an unavailable formula identifier`,
9744
+ 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`
9745
+ });
9746
+ }
9747
+ if (valid) \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.add(\u540D\u524D);
9748
+ } catch (e) {
9749
+ errors.push({
9750
+ path,
9751
+ message: `${\u540D\u524D} is not a readable expression`,
9752
+ hint: e.message
9753
+ });
9754
+ }
9755
+ }
9756
+ }
9757
+ function validateEvents(v, errors) {
9758
+ if (v === void 0) return;
9759
+ if (!Array.isArray(v)) {
9760
+ errors.push({
9761
+ path: "$.events",
9762
+ message: "events must be an array of event objects",
9763
+ hint: `got ${v === null ? "null" : typeof v}`
9764
+ });
9765
+ return;
9766
+ }
9767
+ const \u76F8\u624B\u306E\u9375 = ["box", "lane", "arrow", "diagram"];
9768
+ v.forEach((e, i) => {
9769
+ const path = `$.events[${i}]`;
9770
+ if (!e || typeof e !== "object" || Array.isArray(e)) {
9771
+ errors.push({ path, message: "event must be a plain object", hint: `got ${typeof e}` });
9772
+ return;
9773
+ }
9774
+ const o = e;
9775
+ for (const k of Object.keys(o)) {
9776
+ if (k === "on" || k === "handler" || \u76F8\u624B\u306E\u9375.includes(k)) continue;
9777
+ errors.push({
9778
+ path: `${path}.${k}`,
9779
+ message: `unknown key "${k}"`,
9780
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = on, handler, ${\u76F8\u624B\u306E\u9375.join(", ")}`
9781
+ });
9782
+ }
9783
+ if (typeof o.on !== "string" || !EVENT_KINDS.includes(o.on)) {
9784
+ errors.push({
9785
+ path: `${path}.on`,
9786
+ message: "on must be a known event kind",
9787
+ hint: `\u4F7F\u3048\u308B\u7A2E\u985E = ${EVENT_KINDS.join(", ")}`
9788
+ });
9789
+ }
9790
+ if (typeof o.handler !== "string" || o.handler.trim() === "") {
9791
+ errors.push({
9792
+ path: `${path}.handler`,
9793
+ message: "handler is required",
9794
+ hint: "\u7A7A\u3067\u306A\u3044\u6587\u5B57\u5217\u3067\u66F8\u304F"
9795
+ });
9796
+ }
9797
+ const \u66F8\u3044\u305F = \u76F8\u624B\u306E\u9375.filter((k) => o[k] !== void 0);
9798
+ if (\u66F8\u3044\u305F.length !== 1) {
9799
+ errors.push({
9800
+ path,
9801
+ message: \u66F8\u3044\u305F.length === 0 ? "event target is required" : "event target must be written once",
9802
+ hint: `${\u76F8\u624B\u306E\u9375.join(" / ")} \u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u3092\u66F8\u304F`
9803
+ });
9804
+ return;
9805
+ }
9806
+ const \u9375 = \u66F8\u3044\u305F[0];
9807
+ if (\u9375 === "diagram") {
9808
+ if (o.diagram !== true) {
9809
+ errors.push({
9810
+ path: `${path}.diagram`,
9811
+ message: "diagram must be true",
9812
+ hint: "\u56F3\u5168\u4F53\u3092\u6307\u3059\u6642\u3060\u3051\u66F8\u304F"
9813
+ });
9814
+ }
9815
+ return;
9816
+ }
9817
+ if (typeof o[\u9375] !== "string" || o[\u9375].trim() === "") {
9818
+ errors.push({ path: `${path}.${\u9375}`, message: `${\u9375} must be a non-empty string` });
9819
+ return;
9820
+ }
9821
+ if (\u9375 === "arrow") {
9822
+ const \u4E21\u7AEF = o.arrow.split("->");
9823
+ if (\u4E21\u7AEF.length !== 2 || \u4E21\u7AEF.some((x) => x.trim() === "")) {
9824
+ errors.push({
9825
+ path: `${path}.arrow`,
9826
+ message: "arrow must be `A -> B`",
9827
+ hint: "\u77E2\u5370\u306E\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
9828
+ });
9829
+ }
9830
+ }
9831
+ });
9832
+ }
9833
+ function validateScrolls(v, inputs, formulas, errors) {
9834
+ if (v === void 0) return;
9835
+ if (!v || typeof v !== "object" || Array.isArray(v)) {
9836
+ errors.push({
9837
+ path: "$.scrolls",
9838
+ message: "scrolls must be an object of name to spec",
9839
+ hint: `got ${v === null ? "null" : Array.isArray(v) ? "array" : typeof v}`
9840
+ });
9841
+ return;
9842
+ }
9843
+ const \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D = /* @__PURE__ */ new Set();
9844
+ if (Array.isArray(inputs)) {
9845
+ for (const input of inputs) {
9846
+ if (!input || typeof input !== "object" || Array.isArray(input)) continue;
9847
+ const id = input.id;
9848
+ if (typeof id === "string") \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.add(id);
9849
+ }
9850
+ }
9851
+ if (formulas && typeof formulas === "object" && !Array.isArray(formulas)) {
9852
+ for (const id of Object.keys(formulas)) \u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.add(id);
9853
+ }
9854
+ for (const [\u540D\u524D, spec] of Object.entries(v)) {
9855
+ const path = `$.scrolls.${\u540D\u524D}`;
9856
+ if (!isValueName(\u540D\u524D)) {
9857
+ errors.push({ path, ...valueNameIssue(\u540D\u524D) });
9858
+ continue;
9859
+ }
9860
+ if (\u65E2\u306B\u5024\u3092\u4F5C\u308B\u540D\u524D.has(\u540D\u524D)) {
9861
+ errors.push({
9862
+ path,
9863
+ message: `${\u540D\u524D} collides with an input or formula`,
9864
+ hint: "inputs / formulas / scrolls \u3067\u306F\u91CD\u306A\u3089\u306A\u3044\u540D\u524D\u3092\u4F7F\u3046"
9865
+ });
9866
+ }
9867
+ if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
9868
+ errors.push({ path, message: `${\u540D\u524D} must be a plain object`, hint: `got ${typeof spec}` });
9869
+ continue;
9870
+ }
9871
+ for (const [k, x] of Object.entries(spec)) {
9872
+ if (k === "label") {
9873
+ if (typeof x !== "string") {
9874
+ errors.push({ path: `${path}.label`, message: "label must be a string" });
9875
+ }
9876
+ continue;
9877
+ }
9878
+ if (k !== "start" && k !== "end" && k !== "scrub") {
9879
+ errors.push({
9880
+ path: `${path}.${k}`,
9881
+ message: `unknown key "${k}"`,
9882
+ hint: "\u4F7F\u3048\u308B\u9805\u76EE = start, end, scrub, label"
9883
+ });
9884
+ continue;
9885
+ }
9886
+ if (typeof x !== "number" || !Number.isFinite(x)) {
9887
+ errors.push({ path: `${path}.${k}`, message: `${k} must be a finite number` });
9888
+ } else if (x < 0 || x > 1) {
9889
+ errors.push({
9890
+ path: `${path}.${k}`,
9891
+ message: `${k} must be between 0 and 1`,
9892
+ hint: "0 \u3068 1 \u3092\u542B\u3080\u7BC4\u56F2\u3067\u66F8\u304F"
9893
+ });
9894
+ }
9895
+ }
9896
+ }
9897
+ }
8804
9898
  function validateActorShape(v, path, errors) {
8805
9899
  if (v === void 0) return;
8806
9900
  if (!v || typeof v !== "object" || Array.isArray(v)) {
@@ -8975,6 +10069,10 @@ function validateJson(json) {
8975
10069
  const j = \u5199\u3057.value;
8976
10070
  checkUnknownKeys(j, "root", "$", errors);
8977
10071
  validateReadouts(j.readouts, errors);
10072
+ validateInputs(j.inputs, errors);
10073
+ validateFormulas(j.formulas, j.inputs, errors);
10074
+ validateEvents(j.events, errors);
10075
+ validateScrolls(j.scrolls, j.inputs, j.formulas, errors);
8978
10076
  \u8868\u3067\u691C\u67FB(j, "root", "$", "", errors);
8979
10077
  if (!Array.isArray(j.actors) || j.actors.length === 0) {
8980
10078
  errors.push({ path: "$.actors", message: "actors must be a non-empty array" });
@@ -9211,6 +10309,12 @@ function jsonToDoc(json) {
9211
10309
  shape: isPart ? void 0 : a.shape,
9212
10310
  visibleIf: isPart ? void 0 : a.visibleIf,
9213
10311
  title: isPart ? void 0 : a.title,
10312
+ // 値に追随する 5 欄 (#1392)。 記法と同じく見本には渡さない
10313
+ wBind: isPart ? void 0 : a.wBind,
10314
+ hBind: isPart ? void 0 : a.hBind,
10315
+ opacity: isPart ? void 0 : a.opacity,
10316
+ renderOffsetX: isPart ? void 0 : a.renderOffsetX,
10317
+ renderOffsetY: isPart ? void 0 : a.renderOffsetY,
9214
10318
  // 普通の箱にしか効かない欄は見本では落とす。 落とす欄の一覧は `見本に効かない欄` が
9215
10319
  // 唯一の出どころで、検査 (#1308) も同じ表を見る = 「検査は通すが組み立てが捨てる」
9216
10320
  // 状態が作れない
@@ -9258,6 +10362,10 @@ function jsonToDoc(json) {
9258
10362
  style: s.style,
9259
10363
  guard: s.guard,
9260
10364
  cardinality: s.cardinality,
10365
+ // 値に追随する 3 欄 (#1396)
10366
+ widthBind: s.widthBind,
10367
+ strokeBind: s.strokeBind,
10368
+ dashOffsetBind: s.dashOffsetBind,
9261
10369
  labelOffsetX: s.labelOffsetX,
9262
10370
  labelOffsetY: s.labelOffsetY,
9263
10371
  overlay: s.overlay,
@@ -9266,6 +10374,19 @@ function jsonToDoc(json) {
9266
10374
  pos: p0
9267
10375
  }));
9268
10376
  const readouts = json.readouts ? [...json.readouts] : void 0;
10377
+ const inputs = json.inputs ? [...json.inputs] : void 0;
10378
+ const events = json.events?.map((e) => ({
10379
+ event: e.on,
10380
+ target: e.diagram === true ? { kind: "diagram" } : e.arrow !== void 0 ? {
10381
+ kind: "edge",
10382
+ from: e.arrow.split("->")[0]?.trim() ?? "",
10383
+ to: e.arrow.split("->")[1]?.trim() ?? ""
10384
+ } : e.lane !== void 0 ? { kind: "lane", name: e.lane } : { kind: "node", name: e.box ?? "" },
10385
+ handlerId: e.handler.trim(),
10386
+ pos: p0
10387
+ }));
10388
+ const scrolls = json.scrolls ? Object.entries(json.scrolls).map(([id, spec]) => ({ id, ...spec })) : void 0;
10389
+ const formulas = json.formulas ? Object.entries(json.formulas).map(([id, expression]) => ({ id, expression, pos: p0 })) : void 0;
9269
10390
  const states = Object.entries(json.states ?? {}).map(([name, initial]) => ({
9270
10391
  name,
9271
10392
  initial,
@@ -9323,6 +10444,10 @@ function jsonToDoc(json) {
9323
10444
  ])
9324
10445
  ) : void 0,
9325
10446
  readouts,
10447
+ inputs,
10448
+ formulas,
10449
+ events,
10450
+ scrolls,
9326
10451
  pos: p0
9327
10452
  };
9328
10453
  }
@@ -9711,6 +10836,36 @@ var diagram_default = {
9711
10836
  required: ["sides"]
9712
10837
  }
9713
10838
  ]
10839
+ },
10840
+ wBind: {
10841
+ type: "string",
10842
+ minLength: 1,
10843
+ pattern: "\\S",
10844
+ 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"
10845
+ },
10846
+ hBind: {
10847
+ type: "string",
10848
+ minLength: 1,
10849
+ pattern: "\\S",
10850
+ description: "\u7BB1\u306E\u9AD8\u3055\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 wBind \u3068\u540C\u3058\u8AAD\u307F\u65B9"
10851
+ },
10852
+ opacity: {
10853
+ type: ["number", "string"],
10854
+ minLength: 1,
10855
+ pattern: "\\S",
10856
+ 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"
10857
+ },
10858
+ renderOffsetX: {
10859
+ type: ["number", "string"],
10860
+ minLength: 1,
10861
+ pattern: "\\S",
10862
+ 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"
10863
+ },
10864
+ renderOffsetY: {
10865
+ type: ["number", "string"],
10866
+ minLength: 1,
10867
+ pattern: "\\S",
10868
+ description: "\u63CF\u304F\u6642\u3060\u3051\u7BB1\u3092\u7E26\u3078\u305A\u3089\u3059\u91CF\u3002 renderOffsetX \u3068\u540C\u3058\u8AAD\u307F\u65B9"
9714
10869
  }
9715
10870
  }
9716
10871
  }
@@ -9802,6 +10957,24 @@ var diagram_default = {
9802
10957
  type: "number"
9803
10958
  }
9804
10959
  }
10960
+ },
10961
+ widthBind: {
10962
+ type: "string",
10963
+ minLength: 1,
10964
+ pattern: "\\S",
10965
+ 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"
10966
+ },
10967
+ strokeBind: {
10968
+ type: "string",
10969
+ minLength: 1,
10970
+ pattern: "\\S",
10971
+ description: "\u7DDA\u306E\u8272\u3092\u5024\u306B\u8FFD\u968F\u3055\u305B\u308B\u3002 widthBind \u3068\u540C\u3058\u8AAD\u307F\u65B9"
10972
+ },
10973
+ dashOffsetBind: {
10974
+ type: "string",
10975
+ minLength: 1,
10976
+ pattern: "\\S",
10977
+ 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"
9805
10978
  }
9806
10979
  }
9807
10980
  }
@@ -10828,6 +12001,314 @@ var diagram_default = {
10828
12001
  }
10829
12002
  ]
10830
12003
  }
12004
+ },
12005
+ inputs: {
12006
+ type: "array",
12007
+ 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",
12008
+ items: {
12009
+ type: "object",
12010
+ required: ["id", "kind"],
12011
+ additionalProperties: false,
12012
+ properties: {
12013
+ id: {
12014
+ type: "string",
12015
+ minLength: 1
12016
+ },
12017
+ kind: {
12018
+ type: "string",
12019
+ enum: [
12020
+ "color",
12021
+ "datetime",
12022
+ "dropdown",
12023
+ "multi-select",
12024
+ "number",
12025
+ "radio",
12026
+ "range",
12027
+ "slider",
12028
+ "stepper",
12029
+ "tabs",
12030
+ "text",
12031
+ "timeline",
12032
+ "toggle",
12033
+ "xypad"
12034
+ ]
12035
+ },
12036
+ autoplay: {
12037
+ type: "boolean"
12038
+ },
12039
+ defaultHi: {
12040
+ type: "number"
12041
+ },
12042
+ defaultLo: {
12043
+ type: "number"
12044
+ },
12045
+ defaultSpeedIdx: {
12046
+ type: "number"
12047
+ },
12048
+ defaultValue: {
12049
+ type: ["boolean", "number", "string"]
12050
+ },
12051
+ defaultValues: {
12052
+ type: "array",
12053
+ items: {
12054
+ type: "string"
12055
+ }
12056
+ },
12057
+ defaultX: {
12058
+ type: "number"
12059
+ },
12060
+ defaultY: {
12061
+ type: "number"
12062
+ },
12063
+ duration: {
12064
+ type: "number"
12065
+ },
12066
+ label: {
12067
+ type: "string"
12068
+ },
12069
+ loop: {
12070
+ type: "boolean"
12071
+ },
12072
+ max: {
12073
+ type: "number"
12074
+ },
12075
+ maxLength: {
12076
+ type: "number"
12077
+ },
12078
+ min: {
12079
+ type: "number"
12080
+ },
12081
+ options: {
12082
+ type: "array",
12083
+ items: {
12084
+ type: "string"
12085
+ }
12086
+ },
12087
+ placeholder: {
12088
+ type: "string"
12089
+ },
12090
+ speeds: {
12091
+ type: "array",
12092
+ items: {
12093
+ type: "number"
12094
+ }
12095
+ },
12096
+ step: {
12097
+ type: "number"
12098
+ },
12099
+ xMax: {
12100
+ type: "number"
12101
+ },
12102
+ xMin: {
12103
+ type: "number"
12104
+ },
12105
+ yMax: {
12106
+ type: "number"
12107
+ },
12108
+ yMin: {
12109
+ type: "number"
12110
+ }
12111
+ },
12112
+ oneOf: [
12113
+ {
12114
+ properties: {
12115
+ kind: {
12116
+ enum: ["color", "datetime", "text"]
12117
+ },
12118
+ defaultValue: {
12119
+ type: "string"
12120
+ }
12121
+ },
12122
+ required: ["defaultValue"]
12123
+ },
12124
+ {
12125
+ properties: {
12126
+ kind: {
12127
+ enum: ["dropdown", "radio", "tabs"]
12128
+ },
12129
+ defaultValue: {
12130
+ type: "string"
12131
+ }
12132
+ },
12133
+ required: ["options", "defaultValue"]
12134
+ },
12135
+ {
12136
+ properties: {
12137
+ kind: {
12138
+ enum: ["multi-select"]
12139
+ }
12140
+ },
12141
+ required: ["options", "defaultValues"]
12142
+ },
12143
+ {
12144
+ properties: {
12145
+ kind: {
12146
+ enum: ["number", "stepper"]
12147
+ },
12148
+ defaultValue: {
12149
+ type: "number"
12150
+ }
12151
+ },
12152
+ required: ["defaultValue"]
12153
+ },
12154
+ {
12155
+ properties: {
12156
+ kind: {
12157
+ enum: ["range"]
12158
+ }
12159
+ },
12160
+ required: ["min", "max", "defaultLo", "defaultHi"]
12161
+ },
12162
+ {
12163
+ properties: {
12164
+ kind: {
12165
+ enum: ["slider"]
12166
+ },
12167
+ defaultValue: {
12168
+ type: "number"
12169
+ }
12170
+ },
12171
+ required: ["min", "max", "defaultValue"]
12172
+ },
12173
+ {
12174
+ properties: {
12175
+ kind: {
12176
+ enum: ["timeline"]
12177
+ }
12178
+ },
12179
+ required: ["duration"]
12180
+ },
12181
+ {
12182
+ properties: {
12183
+ kind: {
12184
+ enum: ["toggle"]
12185
+ },
12186
+ defaultValue: {
12187
+ type: "boolean"
12188
+ }
12189
+ },
12190
+ required: ["defaultValue"]
12191
+ },
12192
+ {
12193
+ properties: {
12194
+ kind: {
12195
+ enum: ["xypad"]
12196
+ }
12197
+ },
12198
+ required: ["xMin", "xMax", "yMin", "yMax", "defaultX", "defaultY"]
12199
+ }
12200
+ ]
12201
+ }
12202
+ },
12203
+ formulas: {
12204
+ type: "object",
12205
+ 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',
12206
+ additionalProperties: {
12207
+ type: "string",
12208
+ minLength: 1,
12209
+ pattern: "\\S"
12210
+ },
12211
+ propertyNames: {
12212
+ pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
12213
+ }
12214
+ },
12215
+ events: {
12216
+ type: "array",
12217
+ 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",
12218
+ items: {
12219
+ type: "object",
12220
+ required: ["on", "handler"],
12221
+ additionalProperties: false,
12222
+ properties: {
12223
+ on: {
12224
+ type: "string",
12225
+ enum: [
12226
+ "click",
12227
+ "hover",
12228
+ "double-click",
12229
+ "long-press",
12230
+ "drag",
12231
+ "drop",
12232
+ "keydown",
12233
+ "focus",
12234
+ "blur"
12235
+ ]
12236
+ },
12237
+ handler: {
12238
+ type: "string",
12239
+ minLength: 1,
12240
+ pattern: "\\S"
12241
+ },
12242
+ box: {
12243
+ type: "string",
12244
+ minLength: 1,
12245
+ description: "\u7BB1\u306E\u540D\u524D"
12246
+ },
12247
+ lane: {
12248
+ type: "string",
12249
+ minLength: 1,
12250
+ description: "\u7E26\u5217\u306E\u540D\u524D"
12251
+ },
12252
+ arrow: {
12253
+ type: "string",
12254
+ minLength: 1,
12255
+ pattern: "^(?!.*->.*->)\\s*\\S(?:.*\\S)?\\s*->\\s*\\S(?:.*\\S)?\\s*$",
12256
+ description: "\u77E2\u5370\u3002 `A -> B` \u306E\u5F62\u3067\u4E21\u7AEF\u306E\u540D\u524D\u3092\u66F8\u304F"
12257
+ },
12258
+ diagram: {
12259
+ const: true,
12260
+ description: "\u56F3\u5168\u4F53\u3092\u6307\u3059"
12261
+ }
12262
+ },
12263
+ oneOf: [
12264
+ {
12265
+ required: ["box"]
12266
+ },
12267
+ {
12268
+ required: ["lane"]
12269
+ },
12270
+ {
12271
+ required: ["arrow"]
12272
+ },
12273
+ {
12274
+ required: ["diagram"]
12275
+ }
12276
+ ]
12277
+ }
12278
+ },
12279
+ scrolls: {
12280
+ type: "object",
12281
+ 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",
12282
+ propertyNames: {
12283
+ pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
12284
+ },
12285
+ additionalProperties: {
12286
+ type: "object",
12287
+ additionalProperties: false,
12288
+ properties: {
12289
+ start: {
12290
+ type: "number",
12291
+ minimum: 0,
12292
+ maximum: 1,
12293
+ description: "\u9032\u307F\u5177\u5408\u304C 0 \u306B\u306A\u308B\u753B\u9762\u4E0A\u306E\u4F4D\u7F6E (0 \u304C\u4E0A\u7AEF\u30011 \u304C\u4E0B\u7AEF)"
12294
+ },
12295
+ end: {
12296
+ type: "number",
12297
+ minimum: 0,
12298
+ maximum: 1,
12299
+ description: "\u9032\u307F\u5177\u5408\u304C 1 \u306B\u306A\u308B\u753B\u9762\u4E0A\u306E\u4F4D\u7F6E"
12300
+ },
12301
+ scrub: {
12302
+ type: "number",
12303
+ minimum: 0,
12304
+ maximum: 1,
12305
+ description: "\u5DFB\u304D\u4E0A\u3052\u3078\u306E\u8FFD\u968F\u5EA6\u5408\u3044 (0 \u304C\u6BB5\u968E\u7684\u30011 \u304C\u9023\u7D9A)"
12306
+ },
12307
+ label: {
12308
+ type: "string"
12309
+ }
12310
+ }
12311
+ }
10831
12312
  }
10832
12313
  }
10833
12314
  };