@cardenelabs/cdl 0.57.0 → 0.58.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/CHANGELOG.md +38 -1
- package/dist/index.cjs +247 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +247 -92
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +225 -72
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +225 -72
- package/dist/react.js.map +1 -1
- package/dist/{render-Cp41meYv.d.cts → render-DpwY2hzM.d.cts} +39 -1
- package/dist/{render-Cp41meYv.d.ts → render-DpwY2hzM.d.ts} +39 -1
- package/package.json +9 -12
- package/src/builder.ts +7 -0
- package/src/index.ts +6 -0
- package/src/kinds/shape-blockchain.tsx +40 -22
- package/src/kinds/shape-commerce.tsx +24 -12
- package/src/kinds/shape-finance.tsx +25 -17
- package/src/kinds/shape-software.tsx +30 -11
- package/src/lang.ts +168 -0
- package/src/layout.ts +4 -0
- package/src/render/interactive-panel.tsx +18 -1
- package/src/render/nodes.tsx +18 -14
- package/src/render/stage.tsx +2 -0
- package/src/types.ts +15 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
2
|
import type { LaidNode } from "../types";
|
|
3
|
+
import { 字引きを作る, type CdlLang } from "../lang";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Shape-driven software 6 kinds (CAR-1111 Phase 2-B)。
|
|
@@ -38,6 +39,8 @@ import type { LaidNode } from "../types";
|
|
|
38
39
|
type ShapeProps = {
|
|
39
40
|
node: LaidNode;
|
|
40
41
|
active: boolean;
|
|
42
|
+
/** 描画側の固定の字の言語 (#847)。 渡さない呼び方は英語で描く */
|
|
43
|
+
lang?: CdlLang;
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
const commonFrame = (active: boolean) => ({
|
|
@@ -53,6 +56,19 @@ const DESCENT = 0.25;
|
|
|
53
56
|
// SVG の字幅は描く前に測れず、 getBBox も描いた後にしか使えないため送り幅で見積もる。
|
|
54
57
|
// 手元の等幅書体は 0.55-0.61 なので、 0.62 なら実寸を下回らず収めた行が実際にはみ出さない。
|
|
55
58
|
const MONO_ADVANCE = 0.62;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 等幅の書体で描く字の桁数。 和文 (U+2E80 以降) は 2 桁、それ以外は 1 桁で数える (#847)。
|
|
62
|
+
*
|
|
63
|
+
* 字数 (`length`) で数えると、日本語の辞書で描く字 (`進行中` / `→ 12 個を 1.8 秒で出力`) を
|
|
64
|
+
* 半分の幅に見積もり、縮める倍率が効かずに箱からはみ出す。 英語の辞書の字はすべて U+2E80 より
|
|
65
|
+
* 前にあり (`→` も含む)、字数と同じ値になるので、英語の図の見え方は変わらない。
|
|
66
|
+
*/
|
|
67
|
+
function 等幅の桁(s: string): number {
|
|
68
|
+
let 桁 = 0;
|
|
69
|
+
for (const c of s) 桁 += (c.codePointAt(0) ?? 0) >= 0x2e80 ? 2 : 1;
|
|
70
|
+
return 桁;
|
|
71
|
+
}
|
|
56
72
|
// 説明は名前が 16 の時に従来の 11 となり、 名前を縮めた時も同じ比で追随する。
|
|
57
73
|
const LABEL_SUB_RATIO = 11 / 16;
|
|
58
74
|
// 肩書は名前が 16 の時に従来の 12 となり、 名前を縮めた時も同じ比で追随する。
|
|
@@ -187,7 +203,8 @@ export function ShapeWindowNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
187
203
|
}
|
|
188
204
|
|
|
189
205
|
/** shape-terminal = 端末 (黒地 + macOS 風 top bar + prompt 3 行 + typing cursor) */
|
|
190
|
-
export function ShapeTerminalNode({ node, active }: ShapeProps): JSX.Element {
|
|
206
|
+
export function ShapeTerminalNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
207
|
+
const 字引 = 字引きを作る(lang);
|
|
191
208
|
const frame = commonFrame(active);
|
|
192
209
|
const 線 = frame.strokeWidth / 2;
|
|
193
210
|
const x = node.cx - node.w / 2 + 線;
|
|
@@ -209,11 +226,11 @@ export function ShapeTerminalNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
209
226
|
{ 左: 16, 字: 12.5, 色: "#7cd88f", 文: "$" },
|
|
210
227
|
{ 左: 30, 字: 12.5, 色: "#e6edf3", 文: "pnpm build" },
|
|
211
228
|
],
|
|
212
|
-
[{ 左: 16, 字: 12, 色: "#8b95a5", 文: "
|
|
229
|
+
[{ 左: 16, 字: 12, 色: "#8b95a5", 文: 字引("terminal.output") }],
|
|
213
230
|
[{ 左: 16, 字: 12.5, 色: "#7cd88f", 文: "$" }],
|
|
214
231
|
];
|
|
215
232
|
// 中身は自分の座標で描くため、 本体に入る倍率を出せるよう最長行から自然幅を求める。
|
|
216
|
-
const 自然幅 = Math.max(...行.flat().map((
|
|
233
|
+
const 自然幅 = Math.max(...行.flat().map((c) => c.左 + 等幅の桁(c.文) * MONO_ADVANCE * c.字)) + 余白;
|
|
217
234
|
// 最終行とカーソルまで入る自然高を使い、 縦にも同じ倍率を適用できるようにする。
|
|
218
235
|
const 自然高 = 帯 + 先頭 + 行間 * (行.length - 1) + Math.max(カーソル.下, 12.5 * DESCENT);
|
|
219
236
|
// 縦横を同じ倍率で縮めて比を保ち、 幅 300・高さ 200 では 1 のまま従来値を保つ。
|
|
@@ -317,7 +334,8 @@ export function ShapeTerminalNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
317
334
|
}
|
|
318
335
|
|
|
319
336
|
/** shape-code-block = code editor (tab + gutter + 4 syntax-colored stub lines) */
|
|
320
|
-
export function ShapeCodeBlockNode({ node, active }: ShapeProps): JSX.Element {
|
|
337
|
+
export function ShapeCodeBlockNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
338
|
+
const 字引 = 字引きを作る(lang);
|
|
321
339
|
const frame = commonFrame(active);
|
|
322
340
|
const 線 = frame.strokeWidth / 2;
|
|
323
341
|
const x = node.cx - node.w / 2 + 線;
|
|
@@ -410,7 +428,7 @@ export function ShapeCodeBlockNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
410
428
|
textAnchor="middle"
|
|
411
429
|
fill="#e6edf3"
|
|
412
430
|
>
|
|
413
|
-
|
|
431
|
+
{字引("codeBlock.fileName")}
|
|
414
432
|
</text>
|
|
415
433
|
<circle cx={x + tabW - 丸} cy={y + tabH / 2} r={3 * 倍} fill="#7cd88f" stroke="none" />
|
|
416
434
|
<path
|
|
@@ -483,7 +501,8 @@ export function ShapeCodeBlockNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
483
501
|
}
|
|
484
502
|
|
|
485
503
|
/** shape-kanban-card = kanban ticket (top color bar + 3 stub line) */
|
|
486
|
-
export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
504
|
+
export function ShapeKanbanCardNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
505
|
+
const 字引 = 字引きを作る(lang);
|
|
487
506
|
const frame = commonFrame(active);
|
|
488
507
|
const 線 = frame.strokeWidth / 2;
|
|
489
508
|
// 影は札を右下へずらして重ねるため、 ずらす分と枠線を札の寸法から先に引く。
|
|
@@ -496,7 +515,7 @@ export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
496
515
|
const 左右余白 = 14;
|
|
497
516
|
const 上段隙間 = 8;
|
|
498
517
|
const 優先帯高 = 10;
|
|
499
|
-
const ID文 = "
|
|
518
|
+
const ID文 = 字引("kanbanCard.id");
|
|
500
519
|
const ID基準 = 30;
|
|
501
520
|
const ID字 = 11;
|
|
502
521
|
const ID字間 = 1;
|
|
@@ -516,7 +535,7 @@ export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
516
535
|
const 下帯 = FOOTER下 - AVATAR中心Y + AVATAR半径 + AVATAR枠 / 2 + 帯間余白;
|
|
517
536
|
const 中帯 = 名前字 * ASCENT + 名前字 * 説明基準比 + 名前字 * 説明字比 * DESCENT;
|
|
518
537
|
const 自然高 = 上帯 + 中帯 + 下帯;
|
|
519
|
-
const ID幅 = ID
|
|
538
|
+
const ID幅 = 等幅の桁(ID文) * MONO_ADVANCE * ID字 + ID字間 * [...ID文].length;
|
|
520
539
|
const 自然幅 = 左右余白 + ID幅 + 上段隙間 + PILL幅 + 左右余白;
|
|
521
540
|
// 札の中身だけを縦横同率で縮め、 入る札では 1 のまま従来の大きさを保つ。
|
|
522
541
|
const 倍 = Math.min(1, w / 自然幅, h / 自然高);
|
|
@@ -594,7 +613,7 @@ export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
594
613
|
fill="#5a4a1a"
|
|
595
614
|
fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace"
|
|
596
615
|
>
|
|
597
|
-
|
|
616
|
+
{字引("kanbanCard.status")}
|
|
598
617
|
</text>
|
|
599
618
|
{/* タスク名 = title (中央上、 大きく太字) */}
|
|
600
619
|
<text
|
|
@@ -616,7 +635,7 @@ export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
616
635
|
textAnchor="middle"
|
|
617
636
|
fill="var(--cdl-text-dim, #5a6270)"
|
|
618
637
|
>
|
|
619
|
-
|
|
638
|
+
{字引("kanbanCard.task")}
|
|
620
639
|
</text>
|
|
621
640
|
{/* footer = 2 avatars 左 + due date 右 */}
|
|
622
641
|
<g transform={`translate(${x + 左右余白 * 倍}, ${footY})`}>
|
|
@@ -668,7 +687,7 @@ export function ShapeKanbanCardNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
668
687
|
textAnchor="end"
|
|
669
688
|
fill="var(--cdl-text-dim, #5a6270)"
|
|
670
689
|
>
|
|
671
|
-
|
|
690
|
+
{字引("kanbanCard.due")}
|
|
672
691
|
</text>
|
|
673
692
|
</>
|
|
674
693
|
)}
|
package/src/lang.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 描画側が書く固定の字の言語 (#847)。
|
|
3
|
+
*
|
|
4
|
+
* 書き手が何を渡しても描かれる字 (形の看板 / 絵の中の見本の値 / 行の名前) を 1 つの辞書に集め、
|
|
5
|
+
* 図の `lang` で引き替える。 書き手の字 (`title` / `subtitle` / 行 / 札) はこの辞書を通らない。
|
|
6
|
+
*
|
|
7
|
+
* **既定は英語**。 字を直接日本語へ書き換えると、英語で使う人の図まで変わり、戻す口も無い。
|
|
8
|
+
* 指定の無い図は変更前と同じ字で描く。
|
|
9
|
+
*
|
|
10
|
+
* **JSX を持たない module に置く**。 型の定義 (`types.ts`) と配置 (`layout.ts`) からも読むため、
|
|
11
|
+
* ここから React を引き込むと字の幅を測る検査の読込みが重くなる (`kinds/text-width.ts` の注記と同じ)。
|
|
12
|
+
*
|
|
13
|
+
* 言語は `CdlStage` → `CdlNodeView` → 形の部品へ引数 (`lang`) で届く。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** 図の言語。 書かない図は `"en"` で描く */
|
|
17
|
+
export type CdlLang = "en" | "ja";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 記法から届いた値を言語に直す。 型の外の値 (記法の文字列の書き損じ等) は既定の `"en"` に落とす。
|
|
21
|
+
*
|
|
22
|
+
* 落とす先を英語にするのは、指定の無い図と同じ見え方になるため。 書き損じで一部の字だけ
|
|
23
|
+
* 日本語になる形は作らない。
|
|
24
|
+
*/
|
|
25
|
+
export function resolveLang(value: unknown): CdlLang {
|
|
26
|
+
return value === "ja" ? "ja" : "en";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 英語の辞書。 鍵の一覧の出どころで、値は変更前に描いていた字そのもの。
|
|
31
|
+
*
|
|
32
|
+
* 鍵は `形.役割` の形にする。 同じ字でも役割が違えば別の鍵にする (訳が分かれうるため)。
|
|
33
|
+
*/
|
|
34
|
+
const en = {
|
|
35
|
+
/** `shape-terminal` の 2 行目 (命令の出力) */
|
|
36
|
+
"terminal.output": "→ 12 chunks in 1.8s",
|
|
37
|
+
/** `shape-code-block` の札の file 名 */
|
|
38
|
+
"codeBlock.fileName": "utils.ts",
|
|
39
|
+
/** `shape-kanban-card` の課題の番号 */
|
|
40
|
+
"kanbanCard.id": "CAR-1111",
|
|
41
|
+
/** `shape-kanban-card` の状態の札 */
|
|
42
|
+
"kanbanCard.status": "IN PROG",
|
|
43
|
+
/** `shape-kanban-card` の題の下の説明 */
|
|
44
|
+
"kanbanCard.task": "shape-driven kind 実装",
|
|
45
|
+
/** `shape-kanban-card` の期日 */
|
|
46
|
+
"kanbanCard.due": "Jul 10",
|
|
47
|
+
/** `shape-smart-contract` の契約の本文の 1 行 */
|
|
48
|
+
"smartContract.call": "function execute()",
|
|
49
|
+
/** `shape-blockchain-block` の題を渡さない時の見出し */
|
|
50
|
+
"blockchainBlock.title": "Block #421,873",
|
|
51
|
+
/** `shape-blockchain-block` の 1 行目の名前 (塊を識別する値) */
|
|
52
|
+
"blockchainBlock.hash": "hash",
|
|
53
|
+
/** `shape-blockchain-block` の 2 行目の名前 (1 つ前の塊の識別値) */
|
|
54
|
+
"blockchainBlock.prev": "prev",
|
|
55
|
+
/** `shape-blockchain-block` の 3 行目の名前 (取引をまとめた木の根) */
|
|
56
|
+
"blockchainBlock.merkle": "merkle",
|
|
57
|
+
/** `shape-blockchain-block` の 4 行目の名前 (採掘で試した値) */
|
|
58
|
+
"blockchainBlock.nonce": "nonce",
|
|
59
|
+
/** `shape-blockchain-block` の 5 行目の名前 (取引の件数) */
|
|
60
|
+
"blockchainBlock.tx": "tx",
|
|
61
|
+
/** `shape-blockchain-block` の 5 行目の値 */
|
|
62
|
+
"blockchainBlock.txCount": "142 tx",
|
|
63
|
+
/** `shape-rpc-node` の稼働の札 */
|
|
64
|
+
"rpcNode.status": "RPC ONLINE",
|
|
65
|
+
/** `shape-trust-bank` の看板 */
|
|
66
|
+
"trustBank.sign": "TRUST",
|
|
67
|
+
/** `shape-payment-provider` の看板 */
|
|
68
|
+
"paymentProvider.sign": "PAY",
|
|
69
|
+
/** `shape-payment-provider` の状態の札 */
|
|
70
|
+
"paymentProvider.status": "PROCESSING",
|
|
71
|
+
/** `shape-brokerage` の株価の帯 */
|
|
72
|
+
"brokerage.ticker": "▲NKY 38,240 ▲AAPL 194",
|
|
73
|
+
/** `shape-brokerage` の看板 */
|
|
74
|
+
"brokerage.sign": "$ SECURITIES",
|
|
75
|
+
/** `shape-exchange` の看板 */
|
|
76
|
+
"exchange.sign": "EXCHANGE",
|
|
77
|
+
/** `shape-exchange` の看板の下の札 */
|
|
78
|
+
"exchange.sub": "clearing",
|
|
79
|
+
/** `shape-atm` の天井の看板 */
|
|
80
|
+
"atm.sign": "ATM CORNER",
|
|
81
|
+
/** `shape-atm` の画面の案内 */
|
|
82
|
+
"atm.screen": "SELECT AMOUNT",
|
|
83
|
+
/** `shape-atm` の決める鍵 */
|
|
84
|
+
"atm.ok": "OK",
|
|
85
|
+
/** `shape-atm` のカードを入れる口の札 */
|
|
86
|
+
"atm.cardSlot": "CARD SLOT",
|
|
87
|
+
/** `shape-storefront` の看板 */
|
|
88
|
+
"storefront.sign": "SHOP",
|
|
89
|
+
/** `shape-storefront` の扉の札 */
|
|
90
|
+
"storefront.open": "OPEN",
|
|
91
|
+
/** `shape-warehouse` の看板 */
|
|
92
|
+
"warehouse.sign": "WAREHOUSE",
|
|
93
|
+
/** `shape-api-gateway` の看板 */
|
|
94
|
+
"apiGateway.sign": "API GATEWAY",
|
|
95
|
+
/** `shape-api-gateway` の 3 行目の要求の種類 */
|
|
96
|
+
"apiGateway.delete": "DEL",
|
|
97
|
+
/** `shape-api-gateway` の 1 行目の宛先 */
|
|
98
|
+
"apiGateway.users": "/users",
|
|
99
|
+
/** `shape-api-gateway` の 2 行目の宛先 */
|
|
100
|
+
"apiGateway.orders": "/orders",
|
|
101
|
+
/** `shape-api-gateway` の 3 行目の宛先 */
|
|
102
|
+
"apiGateway.session": "/session",
|
|
103
|
+
} as const;
|
|
104
|
+
|
|
105
|
+
/** 辞書の鍵 */
|
|
106
|
+
export type CdlTextKey = keyof typeof en;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 日本語の辞書。 型を `en` の鍵と同じにし、訳の抜けと余分な鍵を型で落とす。
|
|
110
|
+
*
|
|
111
|
+
* 製品名と定着した略語 (`API` / `ATM` / `RPC`) と、要求の種類の綴り (`DELETE`) は英字のまま残す。
|
|
112
|
+
* 日本語の文でもこの綴りで書くため。
|
|
113
|
+
*/
|
|
114
|
+
const ja: Record<CdlTextKey, string> = {
|
|
115
|
+
"terminal.output": "→ 1.8 秒で完了",
|
|
116
|
+
"codeBlock.fileName": "共通.ts",
|
|
117
|
+
"kanbanCard.id": "#1111",
|
|
118
|
+
"kanbanCard.status": "進行中",
|
|
119
|
+
"kanbanCard.task": "形を実装",
|
|
120
|
+
"kanbanCard.due": "7/10",
|
|
121
|
+
"smartContract.call": "自動で実行する",
|
|
122
|
+
"blockchainBlock.title": "ブロック #421,873",
|
|
123
|
+
"blockchainBlock.hash": "ハッシュ",
|
|
124
|
+
"blockchainBlock.prev": "直前",
|
|
125
|
+
"blockchainBlock.merkle": "木の根",
|
|
126
|
+
"blockchainBlock.nonce": "ノンス",
|
|
127
|
+
"blockchainBlock.tx": "取引",
|
|
128
|
+
"blockchainBlock.txCount": "142 件",
|
|
129
|
+
"rpcNode.status": "RPC 稼働中",
|
|
130
|
+
"trustBank.sign": "信託",
|
|
131
|
+
"paymentProvider.sign": "決済",
|
|
132
|
+
"paymentProvider.status": "処理中",
|
|
133
|
+
"brokerage.ticker": "▲日経 38,240 ▲東証 2,710",
|
|
134
|
+
"brokerage.sign": "¥ 証券",
|
|
135
|
+
"exchange.sign": "取引所",
|
|
136
|
+
"exchange.sub": "清算",
|
|
137
|
+
"atm.sign": "ATM コーナー",
|
|
138
|
+
"atm.screen": "金額を選択",
|
|
139
|
+
"atm.ok": "確定",
|
|
140
|
+
"atm.cardSlot": "カード挿入口",
|
|
141
|
+
"storefront.sign": "商店",
|
|
142
|
+
"storefront.open": "営業",
|
|
143
|
+
"warehouse.sign": "倉庫",
|
|
144
|
+
"apiGateway.sign": "API 入口",
|
|
145
|
+
"apiGateway.delete": "DELETE",
|
|
146
|
+
"apiGateway.users": "/利用者",
|
|
147
|
+
"apiGateway.orders": "/注文",
|
|
148
|
+
"apiGateway.session": "/接続",
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/** 言語ごとの辞書。 検査が鍵の一致を実行時にも確かめるため公開する */
|
|
152
|
+
export const CDL_TEXT: Readonly<Record<CdlLang, Readonly<Record<CdlTextKey, string>>>> = { en, ja };
|
|
153
|
+
|
|
154
|
+
/** 言語と鍵から描く字を引く */
|
|
155
|
+
export function cdlText(lang: CdlLang, key: CdlTextKey): string {
|
|
156
|
+
return CDL_TEXT[lang][key];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 部品が受け取った言語で辞書を引く関数を返す。 言語を渡さない呼び方は英語で引く。
|
|
161
|
+
*
|
|
162
|
+
* **部品へは引数で渡す** (React の文脈で届けない)。 形の部品は検査から関数として直接呼ばれており
|
|
163
|
+
* (`描く({ node, active })`)、文脈を読む hook はその呼び方で使えない。
|
|
164
|
+
*/
|
|
165
|
+
export function 字引きを作る(lang: CdlLang | undefined): (key: CdlTextKey) => string {
|
|
166
|
+
const 言語 = lang ?? "en";
|
|
167
|
+
return (key) => CDL_TEXT[言語][key];
|
|
168
|
+
}
|
package/src/layout.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CdlDiagram, LaidDiagram } from "./types";
|
|
2
|
+
import { resolveLang } from "./lang";
|
|
2
3
|
import {
|
|
3
4
|
CLEARANCE_LABEL_LABEL,
|
|
4
5
|
CLEARANCE_NODE_LABEL,
|
|
@@ -422,6 +423,9 @@ export function layout(diag: CdlDiagram): LaidDiagram {
|
|
|
422
423
|
// **遮断はここだけに置く**。 描画は必ず組み立てを通り、組み立て API も `er` も
|
|
423
424
|
// 素通しにしてある。 上流にも置くと、どの入力でも通らない分岐が残る
|
|
424
425
|
...(diag.palette ? { palette: diag.palette } : {}),
|
|
426
|
+
// 描画側の固定の字の言語 (#847)。 既定 (`en`) と型の外の値は持たせない = 配置の結果の形を
|
|
427
|
+
// 変更前と揃え、記法の書き損じで一部の字だけ日本語になる形を作らない
|
|
428
|
+
...(resolveLang(diag.lang) === "ja" ? { lang: "ja" as const } : {}),
|
|
425
429
|
// 種類も配色と同じく空の目印を出さない。 遮断をここに揃えると手書きの図にも効く
|
|
426
430
|
...(diag.type ? { type: diag.type } : {}),
|
|
427
431
|
bboxes,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "../event-handler";
|
|
15
15
|
import type { Signal, Computed } from "../reactive";
|
|
16
16
|
import { effect } from "../reactive";
|
|
17
|
+
import { textWidth } from "../kinds/text-width";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* interactive primitive (input widget / formula / scroll trigger / event handler) を SVG diagram に
|
|
@@ -3473,6 +3474,22 @@ function ProgressGroupReadout({
|
|
|
3473
3474
|
);
|
|
3474
3475
|
}
|
|
3475
3476
|
|
|
3477
|
+
/**
|
|
3478
|
+
* 点の真上に置く札の揃え方。
|
|
3479
|
+
*
|
|
3480
|
+
* 中央揃えのままだと、範囲の端の点 (x = 余白 8) では札の幅の半分が図の外へ出て切れる
|
|
3481
|
+
* (実測 = 時刻 0 の `認可要求` が `可要求` に見えた、 #845)。 はみ出す側だけ揃え位置で押し戻す。
|
|
3482
|
+
*
|
|
3483
|
+
* 札の幅は描く前に分からないので `textWidth` で見積もる。 見積りは実物以上に倒してあるため、
|
|
3484
|
+
* 収まる札を端に寄せることはあっても、はみ出す札を中央に残すことは無い。
|
|
3485
|
+
*/
|
|
3486
|
+
function sequenceLabelAnchor(x: number, name: string, fontSize: number, viewW: number): "start" | "middle" | "end" {
|
|
3487
|
+
const half = textWidth(name, fontSize) / 2;
|
|
3488
|
+
if (x - half < 0) return "start";
|
|
3489
|
+
if (x + half > viewW) return "end";
|
|
3490
|
+
return "middle";
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3476
3493
|
function SequenceTimelineReadout({
|
|
3477
3494
|
id,
|
|
3478
3495
|
label,
|
|
@@ -3543,7 +3560,7 @@ function SequenceTimelineReadout({
|
|
|
3543
3560
|
<circle cx={x} cy={trackY} r={5} fill={color} stroke="#fff" strokeWidth={1.5}>
|
|
3544
3561
|
<title>{`${e.name}: t=${e.t}`}</title>
|
|
3545
3562
|
</circle>
|
|
3546
|
-
<text x={x} y={trackY - 12} textAnchor=
|
|
3563
|
+
<text x={x} y={trackY - 12} textAnchor={sequenceLabelAnchor(x, e.name, 10, viewW)} fontSize={10} fill="var(--v4-ink, #1a1f2a)">
|
|
3547
3564
|
{e.name}
|
|
3548
3565
|
</text>
|
|
3549
3566
|
<text x={x} y={trackY + 18} textAnchor="middle" fontSize={9} fill="var(--v4-mute, #64748b)">
|
package/src/render/nodes.tsx
CHANGED
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
ShapeCustomerServiceNode,
|
|
88
88
|
} from "../kinds/shape-people";
|
|
89
89
|
import type { LaidNode } from "../types";
|
|
90
|
+
import type { CdlLang } from "../lang";
|
|
90
91
|
import { hasUnresolvedRef, interpolate, resolveNumericAttr } from "./utils";
|
|
91
92
|
|
|
92
93
|
/**
|
|
@@ -115,9 +116,12 @@ export function CdlNodeView({
|
|
|
115
116
|
currentPhaseId,
|
|
116
117
|
chartLineScale,
|
|
117
118
|
関係の受け口,
|
|
119
|
+
lang,
|
|
118
120
|
}: {
|
|
119
121
|
node: LaidNode;
|
|
120
122
|
active: boolean;
|
|
123
|
+
/** 描画側の固定の字の言語 (#847)。 字を持つ形の部品へ渡す。 渡さない呼び方は英語で描く */
|
|
124
|
+
lang?: CdlLang;
|
|
121
125
|
/**
|
|
122
126
|
* この phase の `draw` に載っているか (cdl#512)。 true の間だけ、 対象の種別が
|
|
123
127
|
* phase の進み (`progress`) に合わせて左の起点から描かれる。
|
|
@@ -353,11 +357,11 @@ export function CdlNodeView({
|
|
|
353
357
|
case "shape-window":
|
|
354
358
|
return <ShapeWindowNode node={resolvedNode} active={active} />;
|
|
355
359
|
case "shape-terminal":
|
|
356
|
-
return <ShapeTerminalNode node={resolvedNode} active={active} />;
|
|
360
|
+
return <ShapeTerminalNode node={resolvedNode} active={active} lang={lang} />;
|
|
357
361
|
case "shape-code-block":
|
|
358
|
-
return <ShapeCodeBlockNode node={resolvedNode} active={active} />;
|
|
362
|
+
return <ShapeCodeBlockNode node={resolvedNode} active={active} lang={lang} />;
|
|
359
363
|
case "shape-kanban-card":
|
|
360
|
-
return <ShapeKanbanCardNode node={resolvedNode} active={active} />;
|
|
364
|
+
return <ShapeKanbanCardNode node={resolvedNode} active={active} lang={lang} />;
|
|
361
365
|
case "shape-message-bubble":
|
|
362
366
|
return <ShapeMessageBubbleNode node={resolvedNode} active={active} />;
|
|
363
367
|
case "shape-gear":
|
|
@@ -375,11 +379,11 @@ export function CdlNodeView({
|
|
|
375
379
|
case "shape-satellite":
|
|
376
380
|
return <ShapeSatelliteNode node={resolvedNode} active={active} />;
|
|
377
381
|
case "shape-smart-contract":
|
|
378
|
-
return <ShapeSmartContractNode node={resolvedNode} active={active} />;
|
|
382
|
+
return <ShapeSmartContractNode node={resolvedNode} active={active} lang={lang} />;
|
|
379
383
|
case "shape-blockchain-block":
|
|
380
|
-
return <ShapeBlockchainBlockNode node={resolvedNode} active={active} />;
|
|
384
|
+
return <ShapeBlockchainBlockNode node={resolvedNode} active={active} lang={lang} />;
|
|
381
385
|
case "shape-rpc-node":
|
|
382
|
-
return <ShapeRpcNodeNode node={resolvedNode} active={active} />;
|
|
386
|
+
return <ShapeRpcNodeNode node={resolvedNode} active={active} lang={lang} />;
|
|
383
387
|
case "shape-wallet":
|
|
384
388
|
return <ShapeWalletNode node={resolvedNode} active={active} />;
|
|
385
389
|
case "shape-nft":
|
|
@@ -397,29 +401,29 @@ export function CdlNodeView({
|
|
|
397
401
|
case "shape-bank":
|
|
398
402
|
return <ShapeBankNode node={resolvedNode} active={active} />;
|
|
399
403
|
case "shape-trust-bank":
|
|
400
|
-
return <ShapeTrustBankNode node={resolvedNode} active={active} />;
|
|
404
|
+
return <ShapeTrustBankNode node={resolvedNode} active={active} lang={lang} />;
|
|
401
405
|
case "shape-payment-provider":
|
|
402
|
-
return <ShapePaymentProviderNode node={resolvedNode} active={active} />;
|
|
406
|
+
return <ShapePaymentProviderNode node={resolvedNode} active={active} lang={lang} />;
|
|
403
407
|
case "shape-credit-card":
|
|
404
408
|
return <ShapeCreditCardNode node={resolvedNode} active={active} />;
|
|
405
409
|
case "shape-brokerage":
|
|
406
|
-
return <ShapeBrokerageNode node={resolvedNode} active={active} />;
|
|
410
|
+
return <ShapeBrokerageNode node={resolvedNode} active={active} lang={lang} />;
|
|
407
411
|
case "shape-exchange":
|
|
408
|
-
return <ShapeExchangeNode node={resolvedNode} active={active} />;
|
|
412
|
+
return <ShapeExchangeNode node={resolvedNode} active={active} lang={lang} />;
|
|
409
413
|
case "shape-atm":
|
|
410
|
-
return <ShapeAtmNode node={resolvedNode} active={active} />;
|
|
414
|
+
return <ShapeAtmNode node={resolvedNode} active={active} lang={lang} />;
|
|
411
415
|
case "shape-website":
|
|
412
416
|
return <ShapeWebsiteNode node={resolvedNode} active={active} />;
|
|
413
417
|
case "shape-storefront":
|
|
414
|
-
return <ShapeStorefrontNode node={resolvedNode} active={active} />;
|
|
418
|
+
return <ShapeStorefrontNode node={resolvedNode} active={active} lang={lang} />;
|
|
415
419
|
case "shape-warehouse":
|
|
416
|
-
return <ShapeWarehouseNode node={resolvedNode} active={active} />;
|
|
420
|
+
return <ShapeWarehouseNode node={resolvedNode} active={active} lang={lang} />;
|
|
417
421
|
case "shape-online-shop":
|
|
418
422
|
return <ShapeOnlineShopNode node={resolvedNode} active={active} />;
|
|
419
423
|
case "shape-cdn-edge":
|
|
420
424
|
return <ShapeCdnEdgeNode node={resolvedNode} active={active} />;
|
|
421
425
|
case "shape-api-gateway":
|
|
422
|
-
return <ShapeApiGatewayNode node={resolvedNode} active={active} />;
|
|
426
|
+
return <ShapeApiGatewayNode node={resolvedNode} active={active} lang={lang} />;
|
|
423
427
|
case "shape-auditor":
|
|
424
428
|
return <ShapeAuditorNode node={resolvedNode} active={active} />;
|
|
425
429
|
case "shape-regulator":
|
package/src/render/stage.tsx
CHANGED
package/src/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
SequenceBoardMessage,
|
|
6
6
|
SequenceBoardMessageKind,
|
|
7
7
|
} from "./kinds/sequence-board-metrics";
|
|
8
|
+
import type { CdlLang } from "./lang";
|
|
8
9
|
|
|
9
10
|
export type {
|
|
10
11
|
SequenceBoardActor,
|
|
@@ -2613,6 +2614,15 @@ export type CdlDiagram = {
|
|
|
2613
2614
|
* 既定の図にも当たる。
|
|
2614
2615
|
*/
|
|
2615
2616
|
palette?: string;
|
|
2617
|
+
/**
|
|
2618
|
+
* 描画側が書く固定の字を、どの言語で描くか (#847)。 書かない図は `"en"` で描く。
|
|
2619
|
+
*
|
|
2620
|
+
* 引き替わるのは描画側が持つ字 (形の看板 / 絵の中の見本の値 / 行の名前) だけで、書き手の字
|
|
2621
|
+
* (`title` / `subtitle` / 札) は変わらない。 字の一覧は `src/lang.ts` が持つ。
|
|
2622
|
+
*
|
|
2623
|
+
* 型の外の値は `layout` が既定に落とす (記法から文字列で届く場合の書き損じ)。
|
|
2624
|
+
*/
|
|
2625
|
+
lang?: CdlLang;
|
|
2616
2626
|
/**
|
|
2617
2627
|
* この図がどの種類か (#645)。 書かない図は種類を持たない。
|
|
2618
2628
|
*
|
|
@@ -2840,6 +2850,11 @@ export type LaidDiagram = {
|
|
|
2840
2850
|
topic: string;
|
|
2841
2851
|
/** どの配色で描くか (#1553)。 `CdlDiagram.palette` をそのまま持ち越す */
|
|
2842
2852
|
palette?: string;
|
|
2853
|
+
/**
|
|
2854
|
+
* 描画側の固定の字の言語 (#847)。 `CdlDiagram.lang` を既定以外の時だけ持ち越す。
|
|
2855
|
+
* 無い時は `"en"` で描く。
|
|
2856
|
+
*/
|
|
2857
|
+
lang?: CdlLang;
|
|
2843
2858
|
/** どの種類の図か (#645)。 `CdlDiagram.type` をそのまま持ち越す */
|
|
2844
2859
|
type?: string;
|
|
2845
2860
|
viewBox: { x: number; y: number; w: number; h: number };
|