@cardenelabs/cdl 0.74.0 → 0.76.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 +85 -1
- package/dist/index.cjs +314 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +314 -223
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +314 -223
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +314 -223
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/kinds/shape-blockchain.tsx +104 -21
- package/src/kinds/shape-commerce.tsx +50 -17
- package/src/kinds/shape-finance.tsx +111 -29
- package/src/kinds/shape-people.tsx +3 -3
- package/src/kinds/shape-software.tsx +3 -2
- package/src/lang.ts +9 -3
- package/src/visual-validate.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
|
@@ -39,7 +39,7 @@ const BLOCK_W = 240;
|
|
|
39
39
|
const BLOCK_H = 220;
|
|
40
40
|
/** `shape-blockchain-block` の字の指定 (#871 で打ち消しの計算に使うため定数へ出した) */
|
|
41
41
|
const 見出しの字 = 13;
|
|
42
|
-
const 名の字 =
|
|
42
|
+
const 名の字 = 11;
|
|
43
43
|
const 値の字 = 11;
|
|
44
44
|
/** 5 行を並べる間隔と、見出しが乗る帯の高さ。 打ち消しの上限をここから出す (#871) */
|
|
45
45
|
const 行の間隔 = 22;
|
|
@@ -56,6 +56,19 @@ const CHAIN_BLOCK_H = 66;
|
|
|
56
56
|
const CHAIN_LINK_W = 12;
|
|
57
57
|
const CHAIN_SHADOW = 3;
|
|
58
58
|
const CHAIN_BLOCK_SW = 2.5;
|
|
59
|
+
/** 連鎖の箱の頭の帯の高さ。 番号がここに乗る (#887 で打ち消しの帯に使うため定数へ出した) */
|
|
60
|
+
const CHAIN_HEAD_H = 16;
|
|
61
|
+
/** 箱の中で字が使える幅。 左右に 4 ずつ余白を置く */
|
|
62
|
+
const CHAIN_TEXT_W = CHAIN_BLOCK_W - 8;
|
|
63
|
+
/** 箱の中の 2 行 (中央の記号と下の字) の baseline の間隔 */
|
|
64
|
+
const CHAIN_ROW_GAP = 14;
|
|
65
|
+
/** 連鎖の箱の中の字の指定 (#887 で打ち消しの計算に使うため定数へ出した) */
|
|
66
|
+
const CHAIN_NO_SIZE = 11;
|
|
67
|
+
const CONTRACT_CALL_SIZE = 11;
|
|
68
|
+
const NFT_ID_SIZE = 15;
|
|
69
|
+
const CHAIN_HASH_SIZE = 11;
|
|
70
|
+
const BTC_NO_SIZE = 11;
|
|
71
|
+
const ETH_NO_SIZE = 11;
|
|
59
72
|
|
|
60
73
|
const NODE_HEX_R = 44;
|
|
61
74
|
const NODE_PEER_R = 12;
|
|
@@ -223,7 +236,23 @@ export function ShapeSmartContractNode({ node, active, lang }: ShapeProps): JSX.
|
|
|
223
236
|
gearPts.push(`${gearCx + Math.cos(a3) * gearTipR},${gearCy + Math.sin(a3) * gearTipR}`);
|
|
224
237
|
gearPts.push(`${gearCx + Math.cos(a4) * gearBodyR},${gearCy + Math.sin(a4) * gearBodyR}`);
|
|
225
238
|
}
|
|
226
|
-
|
|
239
|
+
/*
|
|
240
|
+
* 打ち消しの上限を出す帯 (#887)。 呼び出し行は書類の下寄りに 1 行だけ置くので、
|
|
241
|
+
* 幅は書類の内側 (左右 16 ずつ)、高さは行を並べる間隔 18 を使う。
|
|
242
|
+
*
|
|
243
|
+
* 字引きで日英が切り替わる (`function execute()` 18 字 と 自動で実行する 7 字) ため、
|
|
244
|
+
* 描く字そのものを渡して幅を数える。
|
|
245
|
+
*/
|
|
246
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
247
|
+
{
|
|
248
|
+
text: 字引("smartContract.call"),
|
|
249
|
+
size: CONTRACT_CALL_SIZE,
|
|
250
|
+
帯: { 幅: docW - 32, 高さ: 18 },
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
const art = (倍率: number): JSX.Element => {
|
|
254
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
255
|
+
return (
|
|
227
256
|
<g>
|
|
228
257
|
<path data-cdl-role="node-body" d={path} {...frame} strokeLinejoin="round" />
|
|
229
258
|
<path d={foldPath} fill="none" stroke={frame.stroke} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
@@ -232,7 +261,7 @@ export function ShapeSmartContractNode({ node, active, lang }: ShapeProps): JSX.
|
|
|
232
261
|
<rect key={i} x={x + 16} y={ly - 3} width={docW - 32 - i * 22} height={5} rx={1} fill="var(--cdl-divider, #d4d4d8)" fillOpacity={0.7} stroke="none" />
|
|
233
262
|
))}
|
|
234
263
|
{/* function signature */}
|
|
235
|
-
<text x={x + 16} y={y + docH - 46} fontSize={
|
|
264
|
+
<text data-cdl-counter-scaled="1" x={x + 16} y={y + docH - 46} fontSize={CONTRACT_CALL_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fill="var(--cdl-tone-accent, #2d6a8f)">
|
|
236
265
|
{字引("smartContract.call")}
|
|
237
266
|
</text>
|
|
238
267
|
{/* gear (auto-execution 記号) */}
|
|
@@ -247,7 +276,8 @@ export function ShapeSmartContractNode({ node, active, lang }: ShapeProps): JSX.
|
|
|
247
276
|
</polygon>
|
|
248
277
|
<circle cx={gearCx} cy={gearCy} r={gearBodyR * 0.4} fill="var(--cdl-node-fill, #ffffff)" stroke="none" />
|
|
249
278
|
</g>
|
|
250
|
-
|
|
279
|
+
);
|
|
280
|
+
};
|
|
251
281
|
return (
|
|
252
282
|
<g>
|
|
253
283
|
{fitArt(r, smartContractExtent(frame.strokeWidth), art)}
|
|
@@ -413,7 +443,19 @@ export function ShapeBlockchainNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
413
443
|
const linkW = CHAIN_LINK_W;
|
|
414
444
|
const totalW = blockCount * blockW + (blockCount - 1) * linkW;
|
|
415
445
|
const startX = cx - totalW / 2;
|
|
416
|
-
|
|
446
|
+
/*
|
|
447
|
+
* 打ち消しの上限を出す帯 (#887)。 番号は頭の帯 (高さ 16) に乗り、下の字は中央の記号との
|
|
448
|
+
* 間隔 14 に収まる。 幅はどちらも箱の内側。
|
|
449
|
+
*
|
|
450
|
+
* **中央の記号 (`#`) は打ち消さない**。 箱の中央に大きく置いた飾りで、戻すと箱から出る。
|
|
451
|
+
*/
|
|
452
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
453
|
+
{ text: "#420", size: CHAIN_NO_SIZE, 帯: { 幅: CHAIN_TEXT_W, 高さ: CHAIN_HEAD_H } },
|
|
454
|
+
{ text: "0x…", size: CHAIN_HASH_SIZE, 帯: { 幅: CHAIN_TEXT_W, 高さ: CHAIN_ROW_GAP } },
|
|
455
|
+
];
|
|
456
|
+
const art = (倍率: number): JSX.Element => {
|
|
457
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
458
|
+
return (
|
|
417
459
|
<g>
|
|
418
460
|
{Array.from({ length: blockCount }, (_, i) => i).map((i) => {
|
|
419
461
|
const bx = startX + i * (blockW + linkW);
|
|
@@ -440,21 +482,22 @@ export function ShapeBlockchainNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
440
482
|
stroke={frame.stroke}
|
|
441
483
|
strokeWidth={isCurrent ? 2.5 : 1.5}
|
|
442
484
|
/>
|
|
443
|
-
<rect x={bx} y={cy - blockH / 2} width={blockW} height={
|
|
444
|
-
<text x={bx + blockW / 2} y={cy - blockH / 2 + 12} fontSize={
|
|
485
|
+
<rect x={bx} y={cy - blockH / 2} width={blockW} height={CHAIN_HEAD_H} rx={4} fill={isCurrent ? "#1a4a68" : "var(--cdl-divider, #d4d4d8)"} fillOpacity={isCurrent ? 1 : 0.4} stroke="none" />
|
|
486
|
+
<text data-cdl-counter-scaled="1" x={bx + blockW / 2} y={cy - blockH / 2 + 12} fontSize={CHAIN_NO_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)"}>
|
|
445
487
|
#{420 + i}
|
|
446
488
|
</text>
|
|
447
|
-
<text x={bx + blockW / 2} y={cy + 8} fontSize={14} fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-tone-accent, #2d6a8f)"} fontFamily="Georgia, serif">
|
|
489
|
+
<text data-cdl-counter-scaled="0" x={bx + blockW / 2} y={cy + 8} fontSize={14} fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-tone-accent, #2d6a8f)"} fontFamily="Georgia, serif">
|
|
448
490
|
#
|
|
449
491
|
</text>
|
|
450
|
-
<text x={bx + blockW / 2} y={cy + 22} fontSize={
|
|
492
|
+
<text data-cdl-counter-scaled="1" x={bx + blockW / 2} y={cy + 22} fontSize={CHAIN_HASH_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)"} opacity={0.9}>
|
|
451
493
|
0x…
|
|
452
494
|
</text>
|
|
453
495
|
</g>
|
|
454
496
|
);
|
|
455
497
|
})}
|
|
456
498
|
</g>
|
|
457
|
-
|
|
499
|
+
);
|
|
500
|
+
};
|
|
458
501
|
return (
|
|
459
502
|
<g>
|
|
460
503
|
{fitArt(r, chainExtent(), art)}
|
|
@@ -476,7 +519,17 @@ export function ShapeBitcoinChainNode({ node, active }: ShapeProps): JSX.Element
|
|
|
476
519
|
const linkW = CHAIN_LINK_W;
|
|
477
520
|
const totalW = blockCount * blockW + (blockCount - 1) * linkW;
|
|
478
521
|
const startX = cx - totalW / 2;
|
|
479
|
-
|
|
522
|
+
/*
|
|
523
|
+
* 打ち消しの上限を出す帯 (#887)。 番号は箱の下半分に置き、中央の `₿` との間隔 20 に収まる。
|
|
524
|
+
*
|
|
525
|
+
* **`₿` は打ち消さない** (指定 30 の飾りで、箱の高さ 66 に対して既に大きい)。
|
|
526
|
+
*/
|
|
527
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
528
|
+
{ text: "#820", size: BTC_NO_SIZE, 帯: { 幅: CHAIN_TEXT_W, 高さ: 20 } },
|
|
529
|
+
];
|
|
530
|
+
const art = (倍率: number): JSX.Element => {
|
|
531
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
532
|
+
return (
|
|
480
533
|
<g>
|
|
481
534
|
{Array.from({ length: blockCount }, (_, i) => i).map((i) => {
|
|
482
535
|
const bx = startX + i * (blockW + linkW);
|
|
@@ -496,17 +549,18 @@ export function ShapeBitcoinChainNode({ node, active }: ShapeProps): JSX.Element
|
|
|
496
549
|
stroke={btcOrange}
|
|
497
550
|
strokeWidth={isCurrent ? 2.5 : 1.5}
|
|
498
551
|
/>
|
|
499
|
-
<text x={bx + blockW / 2} y={cy - 4} fontSize={30} fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : btcOrange} fontFamily="Georgia, serif">
|
|
552
|
+
<text data-cdl-counter-scaled="0" x={bx + blockW / 2} y={cy - 4} fontSize={30} fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : btcOrange} fontFamily="Georgia, serif">
|
|
500
553
|
₿
|
|
501
554
|
</text>
|
|
502
|
-
<text x={bx + blockW / 2} y={cy + 16} fontSize={
|
|
555
|
+
<text data-cdl-counter-scaled="1" x={bx + blockW / 2} y={cy + 16} fontSize={BTC_NO_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)"}>
|
|
503
556
|
#{820 + i}
|
|
504
557
|
</text>
|
|
505
558
|
</g>
|
|
506
559
|
);
|
|
507
560
|
})}
|
|
508
561
|
</g>
|
|
509
|
-
|
|
562
|
+
);
|
|
563
|
+
};
|
|
510
564
|
return (
|
|
511
565
|
<g>
|
|
512
566
|
{fitArt(r, chainExtent(), art)}
|
|
@@ -528,7 +582,21 @@ export function ShapeEthereumChainNode({ node, active }: ShapeProps): JSX.Elemen
|
|
|
528
582
|
const linkW = CHAIN_LINK_W;
|
|
529
583
|
const totalW = blockCount * blockW + (blockCount - 1) * linkW;
|
|
530
584
|
const startX = cx - totalW / 2;
|
|
531
|
-
|
|
585
|
+
/*
|
|
586
|
+
* 打ち消しの上限を出す帯 (#888)。 番号は箱の下半分に置き、ロゴとの間隔 20 に収まる。
|
|
587
|
+
*
|
|
588
|
+
* **ロゴは打ち消さない** (絵で、字ではない)。
|
|
589
|
+
*
|
|
590
|
+
* #887 では 6 桁 (`#21400`) の幅 56.8 が帯 42 を縮む前から超えていたため打ち消しに
|
|
591
|
+
* 乗せられなかった。 番号を 3 桁に揃えて 37.8 に収めたので、他の 2 つの連鎖と同じ
|
|
592
|
+
* 扱いに戻した。
|
|
593
|
+
*/
|
|
594
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
595
|
+
{ text: "#214", size: ETH_NO_SIZE, 帯: { 幅: CHAIN_TEXT_W, 高さ: 20 } },
|
|
596
|
+
];
|
|
597
|
+
const art = (倍率: number): JSX.Element => {
|
|
598
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
599
|
+
return (
|
|
532
600
|
<g>
|
|
533
601
|
{Array.from({ length: blockCount }, (_, i) => i).map((i) => {
|
|
534
602
|
const bx = startX + i * (blockW + linkW);
|
|
@@ -553,14 +621,15 @@ export function ShapeEthereumChainNode({ node, active }: ShapeProps): JSX.Elemen
|
|
|
553
621
|
/>
|
|
554
622
|
{/* Ethereum Diamond ロゴ */}
|
|
555
623
|
<EthereumDiamond cx={bx + blockW / 2} cy={cy - 6} h={16} colors={iconColors} />
|
|
556
|
-
<text x={bx + blockW / 2} y={cy + 22} fontSize={
|
|
557
|
-
#{
|
|
624
|
+
<text data-cdl-counter-scaled="1" x={bx + blockW / 2} y={cy + 22} fontSize={ETH_NO_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fontWeight={700} textAnchor="middle" fill={isCurrent ? "#ffffff" : "var(--cdl-text-dim, #5a6270)"}>
|
|
625
|
+
#{214 + i}
|
|
558
626
|
</text>
|
|
559
627
|
</g>
|
|
560
628
|
);
|
|
561
629
|
})}
|
|
562
630
|
</g>
|
|
563
|
-
|
|
631
|
+
);
|
|
632
|
+
};
|
|
564
633
|
return (
|
|
565
634
|
<g>
|
|
566
635
|
{fitArt(r, chainExtent(), art)}
|
|
@@ -776,7 +845,19 @@ export function ShapeNftNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
776
845
|
const artH = cardH * 0.72;
|
|
777
846
|
const artCx = x + cardW / 2;
|
|
778
847
|
const artCy = y + artH / 2;
|
|
779
|
-
|
|
848
|
+
/*
|
|
849
|
+
* 打ち消しの上限を出す帯 (#887)。 番号は下の帯に置く。 高さは帯 (cardH - artH = 67)、
|
|
850
|
+
* 幅は左の余白 16 と右の丸 (半径 10、中心が cardW - 20) を避けた分。
|
|
851
|
+
*
|
|
852
|
+
* **絵の中央の `NFT` (指定 68) は打ち消さない**。 上の帯いっぱいに置いた飾りで、
|
|
853
|
+
* 戻すと帯から出る (実測 = 余り 0.92 で既に使い切っている)。
|
|
854
|
+
*/
|
|
855
|
+
const 打ち消す字ら: 打ち消す字[] = [
|
|
856
|
+
{ text: "#1024", size: NFT_ID_SIZE, 帯: { 幅: cardW - 16 - 34, 高さ: cardH - artH } },
|
|
857
|
+
];
|
|
858
|
+
const art = (倍率: number): JSX.Element => {
|
|
859
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
860
|
+
return (
|
|
780
861
|
<g>
|
|
781
862
|
{/* shadow */}
|
|
782
863
|
<rect x={x + 4} y={y + 4} width={cardW} height={cardH} rx={14} fill={frame.stroke} opacity={0.2} stroke="none" />
|
|
@@ -791,6 +872,7 @@ export function ShapeNftNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
791
872
|
/>
|
|
792
873
|
{/* 巨大 NFT 文字 (art 中央、 accent 色) */}
|
|
793
874
|
<text
|
|
875
|
+
data-cdl-counter-scaled="0"
|
|
794
876
|
x={artCx}
|
|
795
877
|
y={artCy + 24}
|
|
796
878
|
fontSize={68}
|
|
@@ -805,7 +887,7 @@ export function ShapeNftNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
805
887
|
{/* 下部 info bar */}
|
|
806
888
|
<line x1={x} y1={y + artH} x2={x + cardW} y2={y + artH} stroke={frame.stroke} strokeWidth={1} opacity={0.5} />
|
|
807
889
|
{/* token id (左) */}
|
|
808
|
-
<text x={x + 16} y={y + artH + 30} fontSize={
|
|
890
|
+
<text data-cdl-counter-scaled="1" x={x + 16} y={y + artH + 30} fontSize={NFT_ID_SIZE * 倍} fontWeight={700} fill="var(--cdl-text, #1a1f2a)" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
809
891
|
#1024
|
|
810
892
|
</text>
|
|
811
893
|
{/* verified check (右) */}
|
|
@@ -814,7 +896,8 @@ export function ShapeNftNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
814
896
|
<path d="M -4 0 L -1 3 L 4 -3" fill="none" stroke="#ffffff" strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" />
|
|
815
897
|
</g>
|
|
816
898
|
</g>
|
|
817
|
-
|
|
899
|
+
);
|
|
900
|
+
};
|
|
818
901
|
return (
|
|
819
902
|
<g>
|
|
820
903
|
{fitArt(r, nftExtent(frame.strokeWidth), art)}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
shapeRegion,
|
|
4
|
+
labelPlan,
|
|
5
|
+
fitArt,
|
|
6
|
+
textWidth,
|
|
7
|
+
打ち消しの倍率,
|
|
8
|
+
type 打ち消す字,
|
|
9
|
+
} from "./shape-region";
|
|
3
10
|
import { MONO_ADVANCE_RATIO, displayWidth } from "./row-align";
|
|
4
11
|
import type { LaidNode } from "../types";
|
|
5
12
|
import { 字引きを作る, type CdlLang } from "../lang";
|
|
@@ -208,6 +215,8 @@ export function ShapeStorefrontNode({ node, active, lang }: ShapeProps): JSX.Ele
|
|
|
208
215
|
const doorH = facadeH - 30;
|
|
209
216
|
const doorX = x + bw - doorW - 12;
|
|
210
217
|
const doorY = facadeY + 20;
|
|
218
|
+
// 営業中の札。 扉より広げない = 扉の外へ貼り出すと店の絵が壊れる
|
|
219
|
+
const 札幅 = Math.min(doorW - 6, 50);
|
|
211
220
|
return (
|
|
212
221
|
<g>
|
|
213
222
|
{/* drop shadow */}
|
|
@@ -232,9 +241,9 @@ export function ShapeStorefrontNode({ node, active, lang }: ShapeProps): JSX.Ele
|
|
|
232
241
|
{/* door の水平 line 装飾 */}
|
|
233
242
|
<line x1={doorX + 4} y1={doorY + doorH * 0.38} x2={doorX + doorW - 4} y2={doorY + doorH * 0.38} stroke={accentDarker} strokeWidth={1} />
|
|
234
243
|
<line x1={doorX + 4} y1={doorY + doorH * 0.72} x2={doorX + doorW - 4} y2={doorY + doorH * 0.72} stroke={accentDarker} strokeWidth={1} />
|
|
235
|
-
{/* OPEN sign (door 下部に貼付) */}
|
|
236
|
-
<rect x={doorX + doorW / 2 -
|
|
237
|
-
<text x={doorX + doorW / 2} y={doorY + doorH * 0.85 +
|
|
244
|
+
{/* OPEN sign (door 下部に貼付)。 札は字に合わせる = 指定 11 の `OPEN` は字間 1 で幅 41.8 (#888) */}
|
|
245
|
+
<rect x={doorX + doorW / 2 - 札幅 / 2} y={doorY + doorH * 0.85} width={札幅} height={16} fill="#e5c07b" stroke="#a67c00" strokeWidth={1.5} />
|
|
246
|
+
<text x={doorX + doorW / 2} y={doorY + doorH * 0.85 + 11} fontSize={11} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#5a3a10">{字引("storefront.open")}</text>
|
|
238
247
|
{/* door handle (小さな dot) */}
|
|
239
248
|
<circle cx={doorX + 6} cy={doorY + doorH * 0.55} r={1.5} fill="#c15a4a" />
|
|
240
249
|
{/* base 床 (前 storefront 直下のみ) */}
|
|
@@ -304,7 +313,7 @@ export function ShapeWarehouseNode({ node, active, lang }: ShapeProps): JSX.Elem
|
|
|
304
313
|
<rect data-cdl-role="node-body" x={x} y={y + roofH} width={bw} height={bh - roofH - 12} fill="#a89d8f" stroke="#5a6270" strokeWidth={frame.strokeWidth} />
|
|
305
314
|
{/* WAREHOUSE 看板 (赤帯) */}
|
|
306
315
|
<rect x={x} y={y + roofH} width={bw} height={signH} fill="#c15a4a" stroke="#8b3f2f" strokeWidth={1.5} />
|
|
307
|
-
<text x={cx} y={y + roofH + 17} fontSize={12} fontWeight={900} letterSpacing={6} textAnchor="middle" fill="#ffffff">{字引("warehouse.sign")}</text>
|
|
316
|
+
<text data-cdl-counter-scaled="0" x={cx} y={y + roofH + 17} fontSize={12} fontWeight={900} letterSpacing={6} textAnchor="middle" fill="#ffffff">{字引("warehouse.sign")}</text>
|
|
308
317
|
{/* 中央大 shutter (rib 縞) */}
|
|
309
318
|
<rect x={shutterX} y={shutterY} width={shutterW} height={shutterH} fill="#8b949e" stroke={accentDarker} strokeWidth={2} />
|
|
310
319
|
{/* shutter 上部 shade (立体感) */}
|
|
@@ -501,6 +510,12 @@ const API_ROWS = 3;
|
|
|
501
510
|
/** 板の大きさ。 高さの下限は行が最小の間隔で 3 本入る高さ。 */
|
|
502
511
|
const API_H_MIN =
|
|
503
512
|
API_ROW_TOP + (API_ROWS - 1) * API_ROW_PITCH_MIN + API_ROW_H + API_ROW_BOTTOM_PAD;
|
|
513
|
+
/** 要求の道と天井看板の字の指定 (#887 で打ち消しの計算に使うため定数へ出した) */
|
|
514
|
+
const API_PATH_SIZE = 12;
|
|
515
|
+
const API_SIGN_SIZE = 14;
|
|
516
|
+
/** 種類の箱の幅と、その中で字が使える幅 (左右 3 ずつ空ける) */
|
|
517
|
+
const API_METHOD_BOX_W = 54;
|
|
518
|
+
const API_METHOD_TEXT_W = 48;
|
|
504
519
|
const API_W_MIN = 200;
|
|
505
520
|
const API_W_MAX = 300;
|
|
506
521
|
|
|
@@ -522,31 +537,48 @@ export function ShapeApiGatewayNode({ node, active, lang }: ShapeProps): JSX.Ele
|
|
|
522
537
|
// 11 のまま入り、長い綴り (日本語の辞書の `DELETE`) だけを縮める。 見積りは等幅と比例の大きい方
|
|
523
538
|
// (`shape-blockchain.tsx` の `字の幅` と同じ考え方で、どちらの書体で描かれても箱からはみ出さない)
|
|
524
539
|
const 種類の字 = (s: string): number =>
|
|
525
|
-
Math.min(11, (11 *
|
|
540
|
+
Math.min(11, (11 * API_METHOD_TEXT_W) / Math.max(displayWidth(s) * 11 * MONO_ADVANCE_RATIO, textWidth(s, 11)));
|
|
526
541
|
const rowPitch = Math.max(
|
|
527
542
|
API_ROW_PITCH_MIN,
|
|
528
543
|
(bh - API_ROW_TOP - API_ROW_H - API_ROW_BOTTOM_PAD) / (API_ROWS - 1),
|
|
529
544
|
);
|
|
530
|
-
const
|
|
545
|
+
const 行ら = [
|
|
546
|
+
{ method: "GET", path: 字引("apiGateway.users"), color: "#27c93f" },
|
|
547
|
+
{ method: "POST", path: 字引("apiGateway.orders"), color: "#e5c07b" },
|
|
548
|
+
{ method: 字引("apiGateway.delete"), path: 字引("apiGateway.session"), color: "#c9302c" },
|
|
549
|
+
];
|
|
550
|
+
/*
|
|
551
|
+
* 打ち消しの上限を出す帯 (#887)。 要求の道の字が使える幅は、行の箱 (bw - 32) から
|
|
552
|
+
* 種類の箱までの 64 と、右端で点滅する印の丸の 16 を除いた残り。
|
|
553
|
+
*
|
|
554
|
+
* **種類の字 (`GET` / `POST`) は打ち消さない**。 `種類の字` が箱の幅 48 に合わせて指定を
|
|
555
|
+
* 決めているので余白が 0 で、打ち消す余地が無い (長い綴りでは上限がちょうど 1.0 になる)。
|
|
556
|
+
* 打ち消しは絵ごとに 1 つの倍率で、最も狭い字が全体を縛る = これを入れると要求の道の字も
|
|
557
|
+
* 戻せなくなる。
|
|
558
|
+
*/
|
|
559
|
+
const 打ち消す字ら: 打ち消す字[] = 行ら.map((e) => ({
|
|
560
|
+
text: e.path,
|
|
561
|
+
size: API_PATH_SIZE,
|
|
562
|
+
帯: { 幅: bw - 32 - 64 - 16, 高さ: API_ROW_H },
|
|
563
|
+
}));
|
|
564
|
+
const 絵 = (倍率: number): JSX.Element => {
|
|
565
|
+
const 倍 = 打ち消しの倍率(倍率, 打ち消す字ら);
|
|
566
|
+
return (
|
|
531
567
|
<g>
|
|
532
568
|
<rect x={x + DROP_SHADOW_D} y={y + DROP_SHADOW_D} width={bw} height={bh} rx={10} fill={frame.stroke} opacity={0.2} stroke="none" />
|
|
533
569
|
<rect data-cdl-role="node-body" x={x} y={y} width={bw} height={bh} rx={10} fill="#1a2332" stroke={frame.stroke} strokeWidth={frame.strokeWidth} />
|
|
534
570
|
<rect x={x} y={y} width={bw} height={36} rx={10} fill="var(--cdl-tone-accent, #2d6a8f)" stroke="none" />
|
|
535
|
-
<text x={cx} y={y + 24} fontSize={
|
|
571
|
+
<text data-cdl-counter-scaled="0" x={cx} y={y + 24} fontSize={API_SIGN_SIZE} fontWeight={700} letterSpacing={3} textAnchor="middle" fill="#ffffff" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
536
572
|
{字引("apiGateway.sign")}
|
|
537
573
|
</text>
|
|
538
|
-
{
|
|
539
|
-
{ method: "GET", path: 字引("apiGateway.users"), color: "#27c93f" },
|
|
540
|
-
{ method: "POST", path: 字引("apiGateway.orders"), color: "#e5c07b" },
|
|
541
|
-
{ method: 字引("apiGateway.delete"), path: 字引("apiGateway.session"), color: "#c9302c" },
|
|
542
|
-
].map((e, i) => (
|
|
574
|
+
{行ら.map((e, i) => (
|
|
543
575
|
<g key={i} transform={`translate(${x + 16}, ${y + API_ROW_TOP + i * rowPitch})`}>
|
|
544
576
|
<rect x={0} y={0} width={bw - 32} height={API_ROW_H} rx={4} fill="#0f1419" stroke="none" />
|
|
545
|
-
<rect x={0} y={0} width={
|
|
546
|
-
<text x={27} y={16} fontSize={種類の字(e.method)} fontWeight={700} textAnchor="middle" fill="#ffffff" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
577
|
+
<rect x={0} y={0} width={API_METHOD_BOX_W} height={API_ROW_H} rx={4} fill={e.color} stroke="none" />
|
|
578
|
+
<text data-cdl-counter-scaled="0" x={27} y={16} fontSize={種類の字(e.method)} fontWeight={700} textAnchor="middle" fill="#ffffff" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
547
579
|
{e.method}
|
|
548
580
|
</text>
|
|
549
|
-
<text x={64} y={16} fontSize={
|
|
581
|
+
<text data-cdl-counter-scaled="1" x={64} y={16} fontSize={API_PATH_SIZE * 倍} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fill="#e6edf3">
|
|
550
582
|
{e.path}
|
|
551
583
|
</text>
|
|
552
584
|
<circle cx={bw - 44} cy={12} r={4} fill="#27c93f" stroke="none">
|
|
@@ -555,7 +587,8 @@ export function ShapeApiGatewayNode({ node, active, lang }: ShapeProps): JSX.Ele
|
|
|
555
587
|
</g>
|
|
556
588
|
))}
|
|
557
589
|
</g>
|
|
558
|
-
|
|
590
|
+
);
|
|
591
|
+
};
|
|
559
592
|
return (
|
|
560
593
|
<g>
|
|
561
594
|
{fitArt(r, 広がり, 絵)}
|