@cardenelabs/cdl 0.5.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/LICENSE +21 -0
- package/README.md +343 -0
- package/SPEC.md +374 -0
- package/dist/index.cjs +28085 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3415 -0
- package/dist/index.d.ts +3415 -0
- package/dist/index.js +27962 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +23043 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +2 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +23041 -0
- package/dist/react.js.map +1 -0
- package/dist/render-C78lIXeC.d.cts +2449 -0
- package/dist/render-C78lIXeC.d.ts +2449 -0
- package/examples/quick-start.md +88 -0
- package/package.json +79 -0
- package/src/anim/core/easing.ts +77 -0
- package/src/anim/core/timeline.ts +335 -0
- package/src/anim/core/types.ts +42 -0
- package/src/anim/index.ts +20 -0
- package/src/anim/react/index.ts +3 -0
- package/src/anim/react/useReducedMotion.ts +27 -0
- package/src/anim/react/useTimeline.ts +48 -0
- package/src/assert-never.ts +16 -0
- package/src/author-intent-verify.ts +587 -0
- package/src/builder.ts +3740 -0
- package/src/compile.ts +12 -0
- package/src/dom-verify-core.ts +121 -0
- package/src/dom-verify-types.ts +21 -0
- package/src/dom-verify.ts +948 -0
- package/src/event-handler/index.ts +184 -0
- package/src/formula/ast.ts +46 -0
- package/src/formula/evaluator.ts +163 -0
- package/src/formula/formula-computeds.ts +83 -0
- package/src/formula/index.ts +5 -0
- package/src/formula/parser.ts +399 -0
- package/src/index.ts +284 -0
- package/src/input-signals.ts +74 -0
- package/src/kinds/actor.tsx +79 -0
- package/src/kinds/card.tsx +61 -0
- package/src/kinds/chart-bar.tsx +121 -0
- package/src/kinds/chart-line.tsx +163 -0
- package/src/kinds/chart-pie.tsx +107 -0
- package/src/kinds/compact-title.ts +164 -0
- package/src/kinds/dyn-shape.tsx +394 -0
- package/src/kinds/event.tsx +70 -0
- package/src/kinds/function.tsx +53 -0
- package/src/kinds/funnel.tsx +122 -0
- package/src/kinds/gantt.tsx +193 -0
- package/src/kinds/generic.tsx +368 -0
- package/src/kinds/mind-map.tsx +367 -0
- package/src/kinds/mind-radial.tsx +209 -0
- package/src/kinds/node-tone.ts +18 -0
- package/src/kinds/quadrant.tsx +164 -0
- package/src/kinds/row-align.ts +179 -0
- package/src/kinds/shape-basement.tsx +683 -0
- package/src/kinds/shape-blockchain.tsx +750 -0
- package/src/kinds/shape-commerce.tsx +553 -0
- package/src/kinds/shape-finance.tsx +706 -0
- package/src/kinds/shape-hardware.tsx +862 -0
- package/src/kinds/shape-people.tsx +439 -0
- package/src/kinds/shape-region.tsx +383 -0
- package/src/kinds/shape-software.tsx +859 -0
- package/src/kinds/storage.tsx +180 -0
- package/src/kinds/text-width.ts +73 -0
- package/src/kinds/tree.tsx +275 -0
- package/src/kinds/user-journey.tsx +240 -0
- package/src/label-text.ts +71 -0
- package/src/layout/clearance-constants.ts +47 -0
- package/src/layout/collisions.ts +2078 -0
- package/src/layout/edges.ts +2498 -0
- package/src/layout/footer-shape.ts +97 -0
- package/src/layout/geometry.ts +135 -0
- package/src/layout/label-shift.ts +28 -0
- package/src/layout/lanes.ts +328 -0
- package/src/layout/nodes.ts +190 -0
- package/src/layout/predict-bbox.ts +76 -0
- package/src/layout/px-projection.ts +176 -0
- package/src/layout/spec.ts +872 -0
- package/src/layout/text-width.ts +133 -0
- package/src/layout/tokens.ts +181 -0
- package/src/layout/viewbox.ts +47 -0
- package/src/layout-with-validation.ts +175 -0
- package/src/layout.ts +381 -0
- package/src/presets.ts +2108 -0
- package/src/reactive/batch.ts +48 -0
- package/src/reactive/computed.ts +85 -0
- package/src/reactive/effect.ts +145 -0
- package/src/reactive/index.ts +6 -0
- package/src/reactive/internal.ts +109 -0
- package/src/reactive/signal.ts +113 -0
- package/src/render/edges.tsx +318 -0
- package/src/render/header.tsx +146 -0
- package/src/render/interactive-panel.tsx +9620 -0
- package/src/render/nodes.tsx +319 -0
- package/src/render/stage.tsx +377 -0
- package/src/render/tone.ts +64 -0
- package/src/render/utils.ts +238 -0
- package/src/render.tsx +221 -0
- package/src/scroll-trigger/index.ts +109 -0
- package/src/scroll-trigger/progress.ts +49 -0
- package/src/thumbnail.tsx +114 -0
- package/src/types.ts +2371 -0
- package/src/validate.ts +268 -0
- package/src/visual-validate.ts +4381 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { JSX } from "react";
|
|
2
|
+
import type { LaidNode, JourneyStepPayload } from "../types";
|
|
3
|
+
import { TONE } from "../render/tone";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* journey-map kind ... 1 node に step 配列 (journeyData) を保持し、 UX journey map を SVG 描画する。
|
|
7
|
+
*
|
|
8
|
+
* デザイン方針 (batch3):
|
|
9
|
+
* - 感情 5 段階の水平 band 背景色 (delighted 緑 → angry 赤 の gradient)
|
|
10
|
+
* - 各 step 区切りに縦線 + step index
|
|
11
|
+
* - 感情曲線を bezier smooth curve + tone accent
|
|
12
|
+
* - touchpoint は icon pill + step label 下に配置
|
|
13
|
+
* - opportunity は 電球 + 吹き出し風 rounded rect
|
|
14
|
+
* - 「ただの折れ線グラフ」 との差別化 = 5 emotion band + touchpoint 装飾 + opportunity call-out
|
|
15
|
+
*/
|
|
16
|
+
export function UserJourneyNode({ node, active }: { node: LaidNode; active: boolean }): JSX.Element {
|
|
17
|
+
const x0 = node.cx - node.w / 2;
|
|
18
|
+
const y0 = node.cy - node.h / 2;
|
|
19
|
+
const steps = node.journeyData ?? [];
|
|
20
|
+
|
|
21
|
+
const PAD_TOP = 20;
|
|
22
|
+
const PAD_RIGHT = 32;
|
|
23
|
+
const PAD_BOTTOM = 108;
|
|
24
|
+
const PAD_LEFT = 108;
|
|
25
|
+
const canvasW = node.w - PAD_LEFT - PAD_RIGHT;
|
|
26
|
+
const canvasH = node.h - PAD_TOP - PAD_BOTTOM;
|
|
27
|
+
|
|
28
|
+
const emotionRows: JourneyStepPayload["emotion"][] = ["delighted", "happy", "neutral", "frustrated", "angry"];
|
|
29
|
+
const emotionScore: Record<JourneyStepPayload["emotion"], number> = {
|
|
30
|
+
delighted: 4,
|
|
31
|
+
happy: 3,
|
|
32
|
+
neutral: 2,
|
|
33
|
+
frustrated: 1,
|
|
34
|
+
angry: 0,
|
|
35
|
+
};
|
|
36
|
+
// 感情ごとの色。 共有の表から引く (直書きすると表を直した時に取り残される)。
|
|
37
|
+
const emotionColor: Record<JourneyStepPayload["emotion"], string> = {
|
|
38
|
+
delighted: TONE.success,
|
|
39
|
+
happy: TONE.teal,
|
|
40
|
+
neutral: TONE.info,
|
|
41
|
+
frustrated: TONE.warning,
|
|
42
|
+
angry: TONE.error,
|
|
43
|
+
};
|
|
44
|
+
const emotionEmoji: Record<JourneyStepPayload["emotion"], string> = {
|
|
45
|
+
delighted: "😄",
|
|
46
|
+
happy: "🙂",
|
|
47
|
+
neutral: "😐",
|
|
48
|
+
frustrated: "😕",
|
|
49
|
+
angry: "😠",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const rowH = canvasH / 5;
|
|
53
|
+
// step を列の中央に置く。 端に寄せると、 step の下に置く touchpoint chip が枠からはみ出す。
|
|
54
|
+
const colW = canvasW / Math.max(steps.length, 1);
|
|
55
|
+
const xAt = (idx: number) =>
|
|
56
|
+
PAD_LEFT + (steps.length <= 1 ? canvasW / 2 : colW / 2 + colW * idx);
|
|
57
|
+
const yAt = (emotion: JourneyStepPayload["emotion"]) =>
|
|
58
|
+
PAD_TOP + rowH / 2 + (4 - emotionScore[emotion]) * rowH;
|
|
59
|
+
|
|
60
|
+
// smooth curve for emotion path
|
|
61
|
+
const pts = steps.map((s, i) => ({ x: xAt(i), y: yAt(s.emotion) }));
|
|
62
|
+
const smoothPath = pts.length > 1
|
|
63
|
+
? pts.reduce((acc, p, i) => {
|
|
64
|
+
if (i === 0) return `M ${p.x} ${p.y}`;
|
|
65
|
+
const prev = pts[i - 1]!;
|
|
66
|
+
const midX = (prev.x + p.x) / 2;
|
|
67
|
+
return `${acc} C ${midX} ${prev.y}, ${midX} ${p.y}, ${p.x} ${p.y}`;
|
|
68
|
+
}, "")
|
|
69
|
+
: "";
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<g transform={`translate(${x0} ${y0})`}>
|
|
73
|
+
<rect
|
|
74
|
+
data-cdl-role="node-body"
|
|
75
|
+
x={0}
|
|
76
|
+
y={0}
|
|
77
|
+
width={node.w}
|
|
78
|
+
height={node.h}
|
|
79
|
+
rx={16}
|
|
80
|
+
fill="var(--cdl-node-fill, #ffffff)"
|
|
81
|
+
stroke={active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)"}
|
|
82
|
+
strokeWidth={active ? 3 : 1.25}
|
|
83
|
+
/>
|
|
84
|
+
|
|
85
|
+
{emotionRows.map((e, i) => (
|
|
86
|
+
<g key={`band-${e}`}>
|
|
87
|
+
<rect
|
|
88
|
+
data-cdl-role="journey-band"
|
|
89
|
+
x={PAD_LEFT}
|
|
90
|
+
y={PAD_TOP + i * rowH}
|
|
91
|
+
width={canvasW}
|
|
92
|
+
height={rowH}
|
|
93
|
+
fill={emotionColor[e]}
|
|
94
|
+
fillOpacity={0.09}
|
|
95
|
+
/>
|
|
96
|
+
<text
|
|
97
|
+
x={PAD_LEFT - 84}
|
|
98
|
+
y={PAD_TOP + i * rowH + rowH / 2 + 5}
|
|
99
|
+
fontSize={18}
|
|
100
|
+
textAnchor="middle"
|
|
101
|
+
>
|
|
102
|
+
{emotionEmoji[e]}
|
|
103
|
+
</text>
|
|
104
|
+
<text
|
|
105
|
+
x={PAD_LEFT - 14}
|
|
106
|
+
y={PAD_TOP + i * rowH + rowH / 2 + 4}
|
|
107
|
+
fontSize={12}
|
|
108
|
+
fontWeight={600}
|
|
109
|
+
textAnchor="end"
|
|
110
|
+
fill={emotionColor[e]}
|
|
111
|
+
>
|
|
112
|
+
{e}
|
|
113
|
+
</text>
|
|
114
|
+
</g>
|
|
115
|
+
))}
|
|
116
|
+
|
|
117
|
+
{/*
|
|
118
|
+
段の区切りの縦線 (#424)。 `actor` と同じ理由で `--cdl-row-divider` に分けた。
|
|
119
|
+
破線は残す = 段の境目は補助線で、 実線にすると折れ線より前に出る。
|
|
120
|
+
*/}
|
|
121
|
+
{steps.map((_, idx) => (
|
|
122
|
+
<line
|
|
123
|
+
key={`div-${idx}`}
|
|
124
|
+
data-cdl-role="node-column-divider"
|
|
125
|
+
x1={xAt(idx)}
|
|
126
|
+
y1={PAD_TOP}
|
|
127
|
+
x2={xAt(idx)}
|
|
128
|
+
y2={PAD_TOP + canvasH}
|
|
129
|
+
stroke="var(--cdl-row-divider, #7e848e)"
|
|
130
|
+
strokeDasharray="4 4"
|
|
131
|
+
/>
|
|
132
|
+
))}
|
|
133
|
+
|
|
134
|
+
{steps.length > 1 && (
|
|
135
|
+
<>
|
|
136
|
+
<path
|
|
137
|
+
data-cdl-role="journey-line-glow"
|
|
138
|
+
d={smoothPath}
|
|
139
|
+
fill="none"
|
|
140
|
+
stroke="var(--cdl-tone-accent, #2d6a8f)"
|
|
141
|
+
strokeOpacity={0.18}
|
|
142
|
+
strokeWidth={10}
|
|
143
|
+
strokeLinecap="round"
|
|
144
|
+
/>
|
|
145
|
+
<path
|
|
146
|
+
data-cdl-role="journey-line"
|
|
147
|
+
d={smoothPath}
|
|
148
|
+
fill="none"
|
|
149
|
+
stroke="var(--cdl-tone-accent, #2d6a8f)"
|
|
150
|
+
strokeWidth={2.75}
|
|
151
|
+
strokeLinejoin="round"
|
|
152
|
+
strokeLinecap="round"
|
|
153
|
+
/>
|
|
154
|
+
</>
|
|
155
|
+
)}
|
|
156
|
+
|
|
157
|
+
{steps.map((s, idx) => (
|
|
158
|
+
<g key={`step-${s.id}`}>
|
|
159
|
+
<circle
|
|
160
|
+
cx={xAt(idx)}
|
|
161
|
+
cy={yAt(s.emotion)}
|
|
162
|
+
r={9}
|
|
163
|
+
fill="var(--cdl-node-fill, #ffffff)"
|
|
164
|
+
stroke={emotionColor[s.emotion]}
|
|
165
|
+
strokeWidth={2.5}
|
|
166
|
+
/>
|
|
167
|
+
<circle
|
|
168
|
+
cx={xAt(idx)}
|
|
169
|
+
cy={yAt(s.emotion)}
|
|
170
|
+
r={4}
|
|
171
|
+
fill={emotionColor[s.emotion]}
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<text
|
|
175
|
+
x={xAt(idx)}
|
|
176
|
+
y={PAD_TOP + canvasH + 24}
|
|
177
|
+
fontSize={12}
|
|
178
|
+
fontWeight={700}
|
|
179
|
+
textAnchor="middle"
|
|
180
|
+
fill="var(--cdl-text, #1a1f2a)"
|
|
181
|
+
>
|
|
182
|
+
{`${idx + 1}. ${s.title}`}
|
|
183
|
+
</text>
|
|
184
|
+
{s.touchpoint && (
|
|
185
|
+
<g>
|
|
186
|
+
{/* 枠の濃さは 0.5 だと背景に埋もれる (実測 = dark 2.86 / 明色 2.13)。 0.6 が
|
|
187
|
+
3.0 を超える最小値 */}
|
|
188
|
+
<rect
|
|
189
|
+
data-cdl-role="journey-chip"
|
|
190
|
+
x={xAt(idx) - 40}
|
|
191
|
+
y={PAD_TOP + canvasH + 34}
|
|
192
|
+
width={80}
|
|
193
|
+
height={20}
|
|
194
|
+
rx={10}
|
|
195
|
+
fill="var(--cdl-tone-accent, #2d6a8f)"
|
|
196
|
+
fillOpacity={0.12}
|
|
197
|
+
stroke="var(--cdl-tone-accent, #2d6a8f)"
|
|
198
|
+
strokeOpacity={0.6}
|
|
199
|
+
strokeWidth={1}
|
|
200
|
+
/>
|
|
201
|
+
<text
|
|
202
|
+
x={xAt(idx)}
|
|
203
|
+
y={PAD_TOP + canvasH + 48}
|
|
204
|
+
fontSize={10}
|
|
205
|
+
fontWeight={600}
|
|
206
|
+
textAnchor="middle"
|
|
207
|
+
fill="var(--cdl-tone-accent, #2d6a8f)"
|
|
208
|
+
>
|
|
209
|
+
{s.touchpoint}
|
|
210
|
+
</text>
|
|
211
|
+
</g>
|
|
212
|
+
)}
|
|
213
|
+
{s.opportunity && (
|
|
214
|
+
<g>
|
|
215
|
+
<rect
|
|
216
|
+
x={xAt(idx) - 55}
|
|
217
|
+
y={PAD_TOP + canvasH + 62}
|
|
218
|
+
width={110}
|
|
219
|
+
height={26}
|
|
220
|
+
rx={13}
|
|
221
|
+
fill="var(--cdl-note-fill, #fef3c7)"
|
|
222
|
+
stroke={TONE.warning}
|
|
223
|
+
strokeWidth={1}
|
|
224
|
+
/>
|
|
225
|
+
<text
|
|
226
|
+
x={xAt(idx)}
|
|
227
|
+
y={PAD_TOP + canvasH + 79}
|
|
228
|
+
fontSize={10}
|
|
229
|
+
textAnchor="middle"
|
|
230
|
+
fill="var(--cdl-note-text, #7a5320)"
|
|
231
|
+
>
|
|
232
|
+
💡 {s.opportunity}
|
|
233
|
+
</text>
|
|
234
|
+
</g>
|
|
235
|
+
)}
|
|
236
|
+
</g>
|
|
237
|
+
))}
|
|
238
|
+
</g>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* edge label の 2 行の文字仕様 SSOT。
|
|
3
|
+
*
|
|
4
|
+
* 描画 (`render/edges.tsx`) と検査 (`visual-validate.ts` の軸 27 `contrast-basics`) が同じ
|
|
5
|
+
* 値を読む。 描画側に literal を残して検査側が「描画はこうなっているはず」 と書き写す形は
|
|
6
|
+
* 使わない。 書き写しは片方だけが変わった時に検知できず、 検査が実在しない描画を測る
|
|
7
|
+
* (軸 27 が sub 行を通常文字として測っていた間、 描画は 19px のままで検査だけが正しかった
|
|
8
|
+
* ように見えていた)。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** edge label の行。 `main` = `label`、 `sub` = `sub`。 */
|
|
12
|
+
export type EdgeLabelLine = "main" | "sub";
|
|
13
|
+
|
|
14
|
+
export interface EdgeLabelTextSpec {
|
|
15
|
+
fontSize: number;
|
|
16
|
+
fontWeight: number;
|
|
17
|
+
/**
|
|
18
|
+
* 文字を背景に重ねる不透明度。 1 = 合成なし。
|
|
19
|
+
*
|
|
20
|
+
* 1 未満だと実際に目に入る色は背景との合成結果になり、 対比が必ず下がる。
|
|
21
|
+
*/
|
|
22
|
+
opacity: number;
|
|
23
|
+
/**
|
|
24
|
+
* 描画で指定する font-family の先頭。 指定せず継承する行は null。
|
|
25
|
+
*
|
|
26
|
+
* 下流が「その太さの face を読み込んでいるか」 を確かめる時、 どの family を見ればよいかが
|
|
27
|
+
* ここで決まる。 主題が family を宣言しない時の落とし先でもある。
|
|
28
|
+
*/
|
|
29
|
+
fontFamily: string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const EDGE_LABEL_TEXT: Record<EdgeLabelLine, EdgeLabelTextSpec> = {
|
|
33
|
+
// main 行は family を指定せず、 host 側の指定を継承する。
|
|
34
|
+
main: { fontSize: 22, fontWeight: 700, opacity: 1, fontFamily: null },
|
|
35
|
+
// sub を太字にすると WCAG の large text に入り、 要求される対比が 4.5:1 から 3:1 に下がる。
|
|
36
|
+
// 幅は変わらない = sub は JetBrains Mono (等幅) で描くため、 advance width が太さに依らない
|
|
37
|
+
// (`layout/text-width.ts` の mono 経路も太さを見ない)。
|
|
38
|
+
sub: { fontSize: 19, fontWeight: 700, opacity: 1, fontFamily: "JetBrains Mono" },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/** `font-family` 属性に書く値。 先頭の family と、 端末に入っている前提の代替を並べる。 */
|
|
42
|
+
export function fontFamilyAttr(line: EdgeLabelLine): string | undefined {
|
|
43
|
+
const family = EDGE_LABEL_TEXT[line].fontFamily;
|
|
44
|
+
return family === null ? undefined : `'${family}', monospace`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** WCAG AA の large text (24px 以上 or 太字 18.66px 以上) の閾値。 */
|
|
48
|
+
export const WCAG_AA_LARGE = 3.0;
|
|
49
|
+
/** WCAG AA の通常文字の閾値。 */
|
|
50
|
+
export const WCAG_AA_NORMAL = 4.5;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* WCAG の large text (14pt 太字 = 18.66px、 または 18pt = 24px) に当たるか。
|
|
54
|
+
*
|
|
55
|
+
* 太字の下限を 700 に取るのは WCAG が「bold」 の具体値を定めておらず、 CSS の `bold` が
|
|
56
|
+
* 700 に対応するため。 600 を太字と見なすと、 実際には満たさない対比を通す。
|
|
57
|
+
*/
|
|
58
|
+
export function isLargeText(spec: EdgeLabelTextSpec): boolean {
|
|
59
|
+
return spec.fontSize >= 24 || (spec.fontWeight >= 700 && spec.fontSize >= 18.66);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 文字仕様から WCAG AA が要求する対比を返す。 */
|
|
63
|
+
export function requiredContrastRatio(spec: EdgeLabelTextSpec): number {
|
|
64
|
+
return isLargeText(spec) ? WCAG_AA_LARGE : WCAG_AA_NORMAL;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 検査の指摘文に出す文字の説明 (例 `19px 太字 = large text`)。 */
|
|
68
|
+
export function describeTextSpec(spec: EdgeLabelTextSpec): string {
|
|
69
|
+
const weight = spec.fontWeight >= 700 ? " 太字" : "";
|
|
70
|
+
return `${spec.fontSize}px${weight} = ${isLargeText(spec) ? "large text" : "通常文字"}`;
|
|
71
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clearance / distance SSOT 定数 (world unit)。
|
|
3
|
+
*
|
|
4
|
+
* label × node / label × label / label × path の clearance と label × path 距離の
|
|
5
|
+
* 目標範囲を engine 内で SSOT 定義。 downstream (edges / collisions / visual-diagnostics / dragon
|
|
6
|
+
* gate) が本 module を import して同一値を使うことで、 threshold の食い違いを防ぐ。
|
|
7
|
+
*
|
|
8
|
+
* world unit = SVG viewBox 内の座標系単位。 実 DOM px は viewBox scale で 縮小 / 拡大される
|
|
9
|
+
* (px-projection 参照)。 gate 判定は px-projection でこれらの world 値を実測 scale に変換して
|
|
10
|
+
* 使う (pixel-perfect assertion)。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** node × edge-label ... 誤読を起こす重大事案、 32 world unit (edges.ts / collisions.ts SSOT) */
|
|
14
|
+
export const CLEARANCE_NODE_LABEL = 32;
|
|
15
|
+
|
|
16
|
+
/** lane-label × edge-label ... lane 見出しと edge label の近接判定、 24 world unit */
|
|
17
|
+
export const CLEARANCE_LANE_LABEL = 24;
|
|
18
|
+
|
|
19
|
+
/** edge-label × edge-label ... 2 label が近接して読みづらい、 36 world unit */
|
|
20
|
+
export const CLEARANCE_LABEL_LABEL = 36;
|
|
21
|
+
|
|
22
|
+
/** edge-path × edge-label ... path 線が label 文字を貫通する誤読、 14 world unit */
|
|
23
|
+
export const CLEARANCE_PATH_LABEL = 14;
|
|
24
|
+
|
|
25
|
+
/** label 箱 → path 最短距離の下限 (label が path に貼り付き) */
|
|
26
|
+
export const DIST_LABEL_PATH_MIN = 14;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* label 箱 → path 最短距離の上限 (label が path から浮遊)。
|
|
30
|
+
*
|
|
31
|
+
* 「見た目の隙間」 の上限で、 軸 7 (`edge-label-proximity`) の warn 閾値がこの値を使う。
|
|
32
|
+
* engine 自身が置く label は 16 world 以内に収まり、 これを超えるのは著者が `labelOffset`
|
|
33
|
+
* で動かした場合に限る。
|
|
34
|
+
*/
|
|
35
|
+
export const DIST_LABEL_PATH_MAX = 80;
|
|
36
|
+
|
|
37
|
+
/** label 位置 score の目標 path 距離 (routing v10 SSOT、 NORMAL 100 world = DOM ~25 px 相当) */
|
|
38
|
+
export const TARGET_LABEL_PATH_DIST = 100;
|
|
39
|
+
|
|
40
|
+
/** arrow tail / head の折れ角許容 (degree) */
|
|
41
|
+
export const ARROW_ANGLE_MAX_DEG = 100;
|
|
42
|
+
|
|
43
|
+
/** Fan-in / fan-out path 分散の slot 幅 (world unit) */
|
|
44
|
+
export const FAN_GAP = 120;
|
|
45
|
+
|
|
46
|
+
/** Detour path の gap = obstacle bottom / top からの余白 (routing v10.1 SSOT、 44 → 94 拡張) */
|
|
47
|
+
export const DETOUR_GAP = 94;
|