@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
|
@@ -90,6 +90,30 @@ type SequenceBoardMetrics = {
|
|
|
90
90
|
*/
|
|
91
91
|
declare function sequenceBoardMetrics(data: SequenceBoardData): SequenceBoardMetrics;
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* 描画側が書く固定の字の言語 (#847)。
|
|
95
|
+
*
|
|
96
|
+
* 書き手が何を渡しても描かれる字 (形の看板 / 絵の中の見本の値 / 行の名前) を 1 つの辞書に集め、
|
|
97
|
+
* 図の `lang` で引き替える。 書き手の字 (`title` / `subtitle` / 行 / 札) はこの辞書を通らない。
|
|
98
|
+
*
|
|
99
|
+
* **既定は英語**。 字を直接日本語へ書き換えると、英語で使う人の図まで変わり、戻す口も無い。
|
|
100
|
+
* 指定の無い図は変更前と同じ字で描く。
|
|
101
|
+
*
|
|
102
|
+
* **JSX を持たない module に置く**。 型の定義 (`types.ts`) と配置 (`layout.ts`) からも読むため、
|
|
103
|
+
* ここから React を引き込むと字の幅を測る検査の読込みが重くなる (`kinds/text-width.ts` の注記と同じ)。
|
|
104
|
+
*
|
|
105
|
+
* 言語は `CdlStage` → `CdlNodeView` → 形の部品へ引数 (`lang`) で届く。
|
|
106
|
+
*/
|
|
107
|
+
/** 図の言語。 書かない図は `"en"` で描く */
|
|
108
|
+
type CdlLang = "en" | "ja";
|
|
109
|
+
/**
|
|
110
|
+
* 記法から届いた値を言語に直す。 型の外の値 (記法の文字列の書き損じ等) は既定の `"en"` に落とす。
|
|
111
|
+
*
|
|
112
|
+
* 落とす先を英語にするのは、指定の無い図と同じ見え方になるため。 書き損じで一部の字だけ
|
|
113
|
+
* 日本語になる形は作らない。
|
|
114
|
+
*/
|
|
115
|
+
declare function resolveLang(value: unknown): CdlLang;
|
|
116
|
+
|
|
93
117
|
/** 意味付きの色の名前。 検査・描画・test はこの 1 つの列を出所にする。 */
|
|
94
118
|
declare const TONES: readonly ["accent", "teal", "success", "error", "warning", "info"];
|
|
95
119
|
type Tone = (typeof TONES)[number];
|
|
@@ -2532,6 +2556,15 @@ type CdlDiagram = {
|
|
|
2532
2556
|
* 既定の図にも当たる。
|
|
2533
2557
|
*/
|
|
2534
2558
|
palette?: string;
|
|
2559
|
+
/**
|
|
2560
|
+
* 描画側が書く固定の字を、どの言語で描くか (#847)。 書かない図は `"en"` で描く。
|
|
2561
|
+
*
|
|
2562
|
+
* 引き替わるのは描画側が持つ字 (形の看板 / 絵の中の見本の値 / 行の名前) だけで、書き手の字
|
|
2563
|
+
* (`title` / `subtitle` / 札) は変わらない。 字の一覧は `src/lang.ts` が持つ。
|
|
2564
|
+
*
|
|
2565
|
+
* 型の外の値は `layout` が既定に落とす (記法から文字列で届く場合の書き損じ)。
|
|
2566
|
+
*/
|
|
2567
|
+
lang?: CdlLang;
|
|
2535
2568
|
/**
|
|
2536
2569
|
* この図がどの種類か (#645)。 書かない図は種類を持たない。
|
|
2537
2570
|
*
|
|
@@ -2752,6 +2785,11 @@ type LaidDiagram = {
|
|
|
2752
2785
|
topic: string;
|
|
2753
2786
|
/** どの配色で描くか (#1553)。 `CdlDiagram.palette` をそのまま持ち越す */
|
|
2754
2787
|
palette?: string;
|
|
2788
|
+
/**
|
|
2789
|
+
* 描画側の固定の字の言語 (#847)。 `CdlDiagram.lang` を既定以外の時だけ持ち越す。
|
|
2790
|
+
* 無い時は `"en"` で描く。
|
|
2791
|
+
*/
|
|
2792
|
+
lang?: CdlLang;
|
|
2755
2793
|
/** どの種類の図か (#645)。 `CdlDiagram.type` をそのまま持ち越す */
|
|
2756
2794
|
type?: string;
|
|
2757
2795
|
viewBox: {
|
|
@@ -2954,4 +2992,4 @@ type CdlDiagramViewProps = {
|
|
|
2954
2992
|
};
|
|
2955
2993
|
declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
|
|
2956
2994
|
|
|
2957
|
-
export {
|
|
2995
|
+
export { computeInputSignalKey as $, EDGE_HEAD_FILLS as A, type BBox as B, type CdlDiagram as C, EDGE_HEAD_FILL_DEFAULT as D, type EdgeStyle as E, EDGE_REVEALS as F, EDGE_REVEAL_DEFAULT as G, EDGE_STYLES as H, type EdgeReveal as I, type JourneyEmotion as J, type InteractiveHandlerMap as K, type LaidDiagram as L, type InteractiveSignalsAccessor as M, type NodeKind as N, type LaidLane as O, NODE_KINDS as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, RELATION_FOCUSES as U, RELATION_FOCUS_DEFAULT as V, type RelationFocus as W, type ScrollProgressHandle as X, TONES as Y, computeEventBindingKey as Z, computeFormulaKey as _, type CdlInput as a, computeScrollTriggerKey as a0, computed as a1, createInteractiveSignalsAccessor as a2, createScrollProgressHandle as a3, createScrollProgressSignals as a4, hasInteractivePrimitives as a5, resolveLang as a6, sequenceBoardMetrics as a7, sequenceStepId as a8, signal as a9, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type CdlLang as j, type Computed as k, type CdlDerivedValue as l, type CdlScrollTrigger as m, type CdlDiagramViewProps as n, type LaidEdge as o, type LaidNode as p, type CdlEdge as q, CdlDiagramView as r, type CdlEventBinding as s, type CdlEventKind as t, type CdlFormula as u, type CdlPhase as v, type ChartPieForm as w, type ChartSlopeForm as x, EDGE_HEADS as y, EDGE_HEAD_DEFAULT as z };
|
|
@@ -90,6 +90,30 @@ type SequenceBoardMetrics = {
|
|
|
90
90
|
*/
|
|
91
91
|
declare function sequenceBoardMetrics(data: SequenceBoardData): SequenceBoardMetrics;
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* 描画側が書く固定の字の言語 (#847)。
|
|
95
|
+
*
|
|
96
|
+
* 書き手が何を渡しても描かれる字 (形の看板 / 絵の中の見本の値 / 行の名前) を 1 つの辞書に集め、
|
|
97
|
+
* 図の `lang` で引き替える。 書き手の字 (`title` / `subtitle` / 行 / 札) はこの辞書を通らない。
|
|
98
|
+
*
|
|
99
|
+
* **既定は英語**。 字を直接日本語へ書き換えると、英語で使う人の図まで変わり、戻す口も無い。
|
|
100
|
+
* 指定の無い図は変更前と同じ字で描く。
|
|
101
|
+
*
|
|
102
|
+
* **JSX を持たない module に置く**。 型の定義 (`types.ts`) と配置 (`layout.ts`) からも読むため、
|
|
103
|
+
* ここから React を引き込むと字の幅を測る検査の読込みが重くなる (`kinds/text-width.ts` の注記と同じ)。
|
|
104
|
+
*
|
|
105
|
+
* 言語は `CdlStage` → `CdlNodeView` → 形の部品へ引数 (`lang`) で届く。
|
|
106
|
+
*/
|
|
107
|
+
/** 図の言語。 書かない図は `"en"` で描く */
|
|
108
|
+
type CdlLang = "en" | "ja";
|
|
109
|
+
/**
|
|
110
|
+
* 記法から届いた値を言語に直す。 型の外の値 (記法の文字列の書き損じ等) は既定の `"en"` に落とす。
|
|
111
|
+
*
|
|
112
|
+
* 落とす先を英語にするのは、指定の無い図と同じ見え方になるため。 書き損じで一部の字だけ
|
|
113
|
+
* 日本語になる形は作らない。
|
|
114
|
+
*/
|
|
115
|
+
declare function resolveLang(value: unknown): CdlLang;
|
|
116
|
+
|
|
93
117
|
/** 意味付きの色の名前。 検査・描画・test はこの 1 つの列を出所にする。 */
|
|
94
118
|
declare const TONES: readonly ["accent", "teal", "success", "error", "warning", "info"];
|
|
95
119
|
type Tone = (typeof TONES)[number];
|
|
@@ -2532,6 +2556,15 @@ type CdlDiagram = {
|
|
|
2532
2556
|
* 既定の図にも当たる。
|
|
2533
2557
|
*/
|
|
2534
2558
|
palette?: string;
|
|
2559
|
+
/**
|
|
2560
|
+
* 描画側が書く固定の字を、どの言語で描くか (#847)。 書かない図は `"en"` で描く。
|
|
2561
|
+
*
|
|
2562
|
+
* 引き替わるのは描画側が持つ字 (形の看板 / 絵の中の見本の値 / 行の名前) だけで、書き手の字
|
|
2563
|
+
* (`title` / `subtitle` / 札) は変わらない。 字の一覧は `src/lang.ts` が持つ。
|
|
2564
|
+
*
|
|
2565
|
+
* 型の外の値は `layout` が既定に落とす (記法から文字列で届く場合の書き損じ)。
|
|
2566
|
+
*/
|
|
2567
|
+
lang?: CdlLang;
|
|
2535
2568
|
/**
|
|
2536
2569
|
* この図がどの種類か (#645)。 書かない図は種類を持たない。
|
|
2537
2570
|
*
|
|
@@ -2752,6 +2785,11 @@ type LaidDiagram = {
|
|
|
2752
2785
|
topic: string;
|
|
2753
2786
|
/** どの配色で描くか (#1553)。 `CdlDiagram.palette` をそのまま持ち越す */
|
|
2754
2787
|
palette?: string;
|
|
2788
|
+
/**
|
|
2789
|
+
* 描画側の固定の字の言語 (#847)。 `CdlDiagram.lang` を既定以外の時だけ持ち越す。
|
|
2790
|
+
* 無い時は `"en"` で描く。
|
|
2791
|
+
*/
|
|
2792
|
+
lang?: CdlLang;
|
|
2755
2793
|
/** どの種類の図か (#645)。 `CdlDiagram.type` をそのまま持ち越す */
|
|
2756
2794
|
type?: string;
|
|
2757
2795
|
viewBox: {
|
|
@@ -2954,4 +2992,4 @@ type CdlDiagramViewProps = {
|
|
|
2954
2992
|
};
|
|
2955
2993
|
declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
|
|
2956
2994
|
|
|
2957
|
-
export {
|
|
2995
|
+
export { computeInputSignalKey as $, EDGE_HEAD_FILLS as A, type BBox as B, type CdlDiagram as C, EDGE_HEAD_FILL_DEFAULT as D, type EdgeStyle as E, EDGE_REVEALS as F, EDGE_REVEAL_DEFAULT as G, EDGE_STYLES as H, type EdgeReveal as I, type JourneyEmotion as J, type InteractiveHandlerMap as K, type LaidDiagram as L, type InteractiveSignalsAccessor as M, type NodeKind as N, type LaidLane as O, NODE_KINDS as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, RELATION_FOCUSES as U, RELATION_FOCUS_DEFAULT as V, type RelationFocus as W, type ScrollProgressHandle as X, TONES as Y, computeEventBindingKey as Z, computeFormulaKey as _, type CdlInput as a, computeScrollTriggerKey as a0, computed as a1, createInteractiveSignalsAccessor as a2, createScrollProgressHandle as a3, createScrollProgressSignals as a4, hasInteractivePrimitives as a5, resolveLang as a6, sequenceBoardMetrics as a7, sequenceStepId as a8, signal as a9, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeRole as e, type EdgeHead as f, type EdgeHeadFill as g, type CdlState as h, type CdlEventTarget as i, type CdlLang as j, type Computed as k, type CdlDerivedValue as l, type CdlScrollTrigger as m, type CdlDiagramViewProps as n, type LaidEdge as o, type LaidNode as p, type CdlEdge as q, CdlDiagramView as r, type CdlEventBinding as s, type CdlEventKind as t, type CdlFormula as u, type CdlPhase as v, type ChartPieForm as w, type ChartSlopeForm as x, EDGE_HEADS as y, EDGE_HEAD_DEFAULT as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.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",
|
|
@@ -57,16 +57,6 @@
|
|
|
57
57
|
"node": ">=18"
|
|
58
58
|
},
|
|
59
59
|
"sideEffects": false,
|
|
60
|
-
"scripts": {
|
|
61
|
-
"build": "tsup",
|
|
62
|
-
"dev": "tsup --watch",
|
|
63
|
-
"typecheck": "tsc --noEmit",
|
|
64
|
-
"test": "cd ../.. && vitest run packages/cdl",
|
|
65
|
-
"lint": "tsc --noEmit",
|
|
66
|
-
"prepublishOnly": "pnpm run typecheck && pnpm run build",
|
|
67
|
-
"prepack": "node scripts/prepack-check.mjs",
|
|
68
|
-
"postpack": "node scripts/prepack-check.mjs"
|
|
69
|
-
},
|
|
70
60
|
"peerDependencies": {
|
|
71
61
|
"react": "^19.0.0",
|
|
72
62
|
"react-dom": "^19.0.0"
|
|
@@ -78,5 +68,12 @@
|
|
|
78
68
|
"typedoc": "^0.28.19",
|
|
79
69
|
"typedoc-plugin-markdown": "^4.12.0",
|
|
80
70
|
"typescript": "^5.8.0"
|
|
71
|
+
},
|
|
72
|
+
"scripts": {
|
|
73
|
+
"build": "tsup",
|
|
74
|
+
"dev": "tsup --watch",
|
|
75
|
+
"typecheck": "tsc --noEmit",
|
|
76
|
+
"test": "cd ../.. && vitest run packages/cdl",
|
|
77
|
+
"lint": "tsc --noEmit"
|
|
81
78
|
}
|
|
82
|
-
}
|
|
79
|
+
}
|
package/src/builder.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseFormula } from "./formula";
|
|
2
|
+
import type { CdlLang } from "./lang";
|
|
2
3
|
import type {
|
|
3
4
|
CdlDiagram,
|
|
4
5
|
CdlEdge,
|
|
@@ -1650,6 +1651,10 @@ export function diagram(
|
|
|
1650
1651
|
* この図をどの配色で描くか (#1553)。 詳細は `CdlDiagram.palette` の doc 参照。
|
|
1651
1652
|
*/
|
|
1652
1653
|
palette?: string;
|
|
1654
|
+
/**
|
|
1655
|
+
* 描画側が書く固定の字の言語 (#847)。 詳しくは `CdlDiagram.lang` の説明を参照。
|
|
1656
|
+
*/
|
|
1657
|
+
lang?: CdlLang;
|
|
1653
1658
|
/**
|
|
1654
1659
|
* この図がどの種類か (#645)。 詳しくは `CdlDiagram.type` の説明を参照。
|
|
1655
1660
|
*/
|
|
@@ -3796,6 +3801,8 @@ export function diagram(
|
|
|
3796
3801
|
...(options.structuredData === "exclude" ? { structuredData: "exclude" as const } : {}),
|
|
3797
3802
|
// 配色の名前は素通しする。 空文字の遮断は `layout` が持つ (後段が必ず通るため)
|
|
3798
3803
|
...(options.palette !== undefined ? { palette: options.palette } : {}),
|
|
3804
|
+
// 言語も素通しする。 型の外の値を既定に落とすのは `layout` の 1 箇所に置く
|
|
3805
|
+
...(options.lang !== undefined ? { lang: options.lang } : {}),
|
|
3799
3806
|
// 種類の名前も同じ経路で渡し、空文字の扱いを `layout` の 1 箇所に揃える
|
|
3800
3807
|
...(options.type !== undefined ? { type: options.type } : {}),
|
|
3801
3808
|
// inputs / formulas / scrollTriggers / eventBindings は空なら省略 (static diagram の JSON 形状維持)
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,12 @@ export { createInputSignals, inputDefaultValue } from "./input-signals";
|
|
|
10
10
|
export type { InputChain } from "./builder";
|
|
11
11
|
export type { CdlInput } from "./types";
|
|
12
12
|
|
|
13
|
+
// 描画側が書く固定の字の言語 (#847)。 図の `lang` に渡す値と、記法の文字列を言語に直す関数。
|
|
14
|
+
// 辞書そのものは公開しない = 字の一覧は描画の実装に属し、利用側が辞書の中身に依存すると
|
|
15
|
+
// 字を直すたびに利用側が壊れる
|
|
16
|
+
export { resolveLang } from "./lang";
|
|
17
|
+
export type { CdlLang } from "./lang";
|
|
18
|
+
|
|
13
19
|
// formula primitive (CAR #244) — builder chain `.formula(id, "gasBase * 2")` で safe subset の
|
|
14
20
|
// algebraic expression を追加、 createFormulaComputeds(diagram, signals) で computed を得て
|
|
15
21
|
// signal と reactive bind する (Step 2 の computed 経路に統合)。
|
|
@@ -3,6 +3,7 @@ import type { LaidNode } from "../types";
|
|
|
3
3
|
import { fitArt, labelPlan, shapeRegion, textWidth, type ArtExtent } from "./shape-region";
|
|
4
4
|
import { 幅で切る } from "./box-lines";
|
|
5
5
|
import { MONO_ADVANCE_RATIO, displayWidth } from "./row-align";
|
|
6
|
+
import { 字引きを作る, type CdlLang, type CdlTextKey } from "../lang";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Shape-driven blockchain / web3 10 kinds (CAR-1111 Phase 2-D)。
|
|
@@ -16,6 +17,8 @@ import { MONO_ADVANCE_RATIO, displayWidth } from "./row-align";
|
|
|
16
17
|
type ShapeProps = {
|
|
17
18
|
node: LaidNode;
|
|
18
19
|
active: boolean;
|
|
20
|
+
/** 描画側の固定の字の言語 (#847)。 渡さない呼び方は英語で描く */
|
|
21
|
+
lang?: CdlLang;
|
|
19
22
|
};
|
|
20
23
|
|
|
21
24
|
const FRAME_SW_ACTIVE = 3;
|
|
@@ -171,7 +174,8 @@ function EthereumDiamond({ cx, cy, h, colors }: { cx: number; cy: number; h: num
|
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
/** shape-smart-contract = 契約書 (前バージョン: document + 契約書テキスト + function 表示 + 底に回転 gear) */
|
|
174
|
-
export function ShapeSmartContractNode({ node, active }: ShapeProps): JSX.Element {
|
|
177
|
+
export function ShapeSmartContractNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
178
|
+
const 字引 = 字引きを作る(lang);
|
|
175
179
|
const frame = commonFrame(active);
|
|
176
180
|
const r = shapeRegion(node);
|
|
177
181
|
const docW = SMART_CONTRACT_W;
|
|
@@ -214,7 +218,7 @@ export function ShapeSmartContractNode({ node, active }: ShapeProps): JSX.Elemen
|
|
|
214
218
|
))}
|
|
215
219
|
{/* function signature */}
|
|
216
220
|
<text x={x + 16} y={y + docH - 46} fontSize={11} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fill="var(--cdl-tone-accent, #2d6a8f)">
|
|
217
|
-
{"
|
|
221
|
+
{字引("smartContract.call")}
|
|
218
222
|
</text>
|
|
219
223
|
{/* gear (auto-execution 記号) */}
|
|
220
224
|
<polygon
|
|
@@ -251,17 +255,25 @@ export function ShapeSmartContractNode({ node, active }: ShapeProps): JSX.Elemen
|
|
|
251
255
|
const 字の幅 = (text: string, size: number): number =>
|
|
252
256
|
Math.max(displayWidth(text) * size * MONO_ADVANCE_RATIO, textWidth(text, size));
|
|
253
257
|
|
|
254
|
-
/**
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
258
|
+
/**
|
|
259
|
+
* 絵の中の 5 行の既定値。 書き手が渡さなかった欄はこれで描く (#469)。
|
|
260
|
+
*
|
|
261
|
+
* **行の名前 (`key`) と描く字を分ける** (#847)。 `key` は副題を差し込む行の判定と
|
|
262
|
+
* `data-cdl-role` の目印に使う識別子で、言語で変えると差し込みと目印が壊れる。 描く字は
|
|
263
|
+
* 辞書 (`src/lang.ts`) から引く。 16 進の値と数は言語に依らないのでここに残す。
|
|
264
|
+
*/
|
|
265
|
+
const BLOCK_DEFAULT_FIELDS: readonly {
|
|
266
|
+
key: string;
|
|
267
|
+
label: CdlTextKey;
|
|
268
|
+
/** 言語に依らない既定値 (16 進の値と数) と、辞書から引く既定値 (単位を持つ値) のどちらか */
|
|
269
|
+
value: { text: string } | { 辞書: CdlTextKey };
|
|
270
|
+
}[] = [
|
|
271
|
+
{ key: "hash", label: "blockchainBlock.hash", value: { text: "0xaf31c9d2..." } },
|
|
272
|
+
{ key: "prev", label: "blockchainBlock.prev", value: { text: "0x7b3f92c1..." } },
|
|
273
|
+
{ key: "merkle", label: "blockchainBlock.merkle", value: { text: "0xc1892f4a..." } },
|
|
274
|
+
{ key: "nonce", label: "blockchainBlock.nonce", value: { text: "82,914" } },
|
|
275
|
+
{ key: "tx", label: "blockchainBlock.tx", value: { 辞書: "blockchainBlock.txCount" } },
|
|
276
|
+
];
|
|
265
277
|
|
|
266
278
|
/**
|
|
267
279
|
* shape-blockchain-block = 単一 block 詳細 (header + 5 fields: hash/prev/merkle/nonce/tx + chain link icon)。
|
|
@@ -284,7 +296,8 @@ const BLOCK_DEFAULT_TITLE = "Block #421,873";
|
|
|
284
296
|
* 位置が node の大きさに依存する。 `rowBaselineY(kind, index)` は node の大きさを受け取らない
|
|
285
297
|
* ので、 この種別の位置を表せない。 開くなら述語の形から変える話になる (#469 の対象外 scope)。
|
|
286
298
|
*/
|
|
287
|
-
export function ShapeBlockchainBlockNode({ node, active }: ShapeProps): JSX.Element {
|
|
299
|
+
export function ShapeBlockchainBlockNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
300
|
+
const 字引 = 字引きを作る(lang);
|
|
288
301
|
const frame = commonFrame(active);
|
|
289
302
|
const r = shapeRegion(node);
|
|
290
303
|
const bw = BLOCK_W;
|
|
@@ -296,11 +309,15 @@ export function ShapeBlockchainBlockNode({ node, active }: ShapeProps): JSX.Elem
|
|
|
296
309
|
|
|
297
310
|
// 書き手の値で置き換える。 空文字と空白だけの値は「渡していない」 と同じ扱いにする
|
|
298
311
|
const 渡された = (v: string | undefined): string => (v ?? "").trim();
|
|
299
|
-
const 見出し = 渡された(node.title) ||
|
|
300
|
-
const fields = BLOCK_DEFAULT_FIELDS.map((f) =>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
312
|
+
const 見出し = 渡された(node.title) || 字引("blockchainBlock.title");
|
|
313
|
+
const fields = BLOCK_DEFAULT_FIELDS.map((f) => {
|
|
314
|
+
const 既定値 = "text" in f.value ? f.value.text : 字引(f.value.辞書);
|
|
315
|
+
return {
|
|
316
|
+
key: f.key,
|
|
317
|
+
label: 字引(f.label),
|
|
318
|
+
value: f.key === "hash" ? 渡された(node.subtitle) || 既定値 : 既定値,
|
|
319
|
+
};
|
|
320
|
+
});
|
|
304
321
|
|
|
305
322
|
// 見出しは右上の丸 (半径 5.5、 中心が bw - 16) に掛からないところまで
|
|
306
323
|
const 見出しの幅 = bw - 14 - 30;
|
|
@@ -321,7 +338,7 @@ export function ShapeBlockchainBlockNode({ node, active }: ShapeProps): JSX.Elem
|
|
|
321
338
|
<text x={x + 14} y={y + 54 + i * 22} fontSize={10.5} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fill="var(--cdl-text-dim, #5a6270)">
|
|
322
339
|
{f.label}
|
|
323
340
|
</text>
|
|
324
|
-
<text data-cdl-role={`blockchain-block-${f.
|
|
341
|
+
<text data-cdl-role={`blockchain-block-${f.key}`} x={x + bw - 14} y={y + 54 + i * 22} fontSize={11} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fontWeight={600} textAnchor="end" fill="var(--cdl-text, #1a1f2a)">
|
|
325
342
|
{幅で切る(f.value, 11, bw - 28 - 字の幅(f.label, 10.5) - 8, 字の幅)}
|
|
326
343
|
</text>
|
|
327
344
|
<line x1={x + 14} y1={y + 60 + i * 22} x2={x + bw - 14} y2={y + 60 + i * 22} stroke="var(--cdl-divider, #d4d4d8)" strokeWidth={0.5} opacity={0.5} />
|
|
@@ -568,7 +585,8 @@ export function ShapeBlockchainNodeNode({ node, active }: ShapeProps): JSX.Eleme
|
|
|
568
585
|
}
|
|
569
586
|
|
|
570
587
|
/** shape-rpc-node = JSON-RPC provider */
|
|
571
|
-
export function ShapeRpcNodeNode({ node, active }: ShapeProps): JSX.Element {
|
|
588
|
+
export function ShapeRpcNodeNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
589
|
+
const 字引 = 字引きを作る(lang);
|
|
572
590
|
const frame = commonFrame(active);
|
|
573
591
|
const r = shapeRegion(node);
|
|
574
592
|
const cx = r.cx;
|
|
@@ -585,7 +603,7 @@ export function ShapeRpcNodeNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
585
603
|
<animate attributeName="opacity" values="0.4;1;0.4" dur="1.5s" repeatCount="indefinite" />
|
|
586
604
|
</circle>
|
|
587
605
|
<text x={x + 26} y={y + 20} fontSize={12} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fontWeight={700} fill="#7cd88f">
|
|
588
|
-
|
|
606
|
+
{字引("rpcNode.status")}
|
|
589
607
|
</text>
|
|
590
608
|
<text x={cx} y={cy + 6} fontSize={30} fontWeight={700} textAnchor="middle" fill="#e6edf3" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
591
609
|
{"{...}"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
|
-
import { shapeRegion, labelPlan, fitArt } from "./shape-region";
|
|
2
|
+
import { shapeRegion, labelPlan, fitArt, textWidth } from "./shape-region";
|
|
3
|
+
import { MONO_ADVANCE_RATIO, displayWidth } from "./row-align";
|
|
3
4
|
import type { LaidNode } from "../types";
|
|
5
|
+
import { 字引きを作る, type CdlLang } from "../lang";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Shape-driven commerce / web 6 kinds (CAR-1111 Phase 2-D)。
|
|
@@ -16,6 +18,8 @@ import type { LaidNode } from "../types";
|
|
|
16
18
|
type ShapeProps = {
|
|
17
19
|
node: LaidNode;
|
|
18
20
|
active: boolean;
|
|
21
|
+
/** 描画側の固定の字の言語 (#847)。 渡さない呼び方は英語で描く */
|
|
22
|
+
lang?: CdlLang;
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
const commonFrame = (active: boolean) => ({
|
|
@@ -179,7 +183,8 @@ export function ShapeWebsiteNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
/** shape-storefront = S-A シンプル shop (平屋根 + SHOP 看板 + 大 window (商品) + 中央 door + OPEN sign) */
|
|
182
|
-
export function ShapeStorefrontNode({ node, active }: ShapeProps): JSX.Element {
|
|
186
|
+
export function ShapeStorefrontNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
187
|
+
const 字引 = 字引きを作る(lang);
|
|
183
188
|
const frame = commonFrame(active);
|
|
184
189
|
const r = shapeRegion(node);
|
|
185
190
|
const cx = r.cx;
|
|
@@ -209,7 +214,7 @@ export function ShapeStorefrontNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
209
214
|
<ellipse cx={cx} cy={y + bh + 8} rx={bw * 0.5} ry={5} fill={frame.stroke} opacity={0.2} stroke="none" />
|
|
210
215
|
{/* SHOP 看板 (accent) */}
|
|
211
216
|
<rect x={x} y={y} width={bw} height={signH} fill={accent} stroke={accentDark} strokeWidth={2} />
|
|
212
|
-
<text x={cx} y={y + 18} fontSize={16} fontWeight={900} letterSpacing={8} textAnchor="middle" fill="#ffffff">
|
|
217
|
+
<text x={cx} y={y + 18} fontSize={16} fontWeight={900} letterSpacing={8} textAnchor="middle" fill="#ffffff">{字引("storefront.sign")}</text>
|
|
213
218
|
{/* facade (店舗本体 白ベース) */}
|
|
214
219
|
<rect data-cdl-role="node-body" x={x} y={facadeY} width={bw} height={facadeH} fill="#e0e4e8" stroke="#5a6270" strokeWidth={frame.strokeWidth} />
|
|
215
220
|
{/* 大 window (商品ディスプレイ、 左) */}
|
|
@@ -229,7 +234,7 @@ export function ShapeStorefrontNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
229
234
|
<line x1={doorX + 4} y1={doorY + doorH * 0.72} x2={doorX + doorW - 4} y2={doorY + doorH * 0.72} stroke={accentDarker} strokeWidth={1} />
|
|
230
235
|
{/* OPEN sign (door 下部に貼付) */}
|
|
231
236
|
<rect x={doorX + doorW / 2 - 20} y={doorY + doorH * 0.85} width={40} height={12} fill="#e5c07b" stroke="#a67c00" strokeWidth={1.5} />
|
|
232
|
-
<text x={doorX + doorW / 2} y={doorY + doorH * 0.85 + 9} fontSize={8} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#5a3a10">
|
|
237
|
+
<text x={doorX + doorW / 2} y={doorY + doorH * 0.85 + 9} fontSize={8} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#5a3a10">{字引("storefront.open")}</text>
|
|
233
238
|
{/* door handle (小さな dot) */}
|
|
234
239
|
<circle cx={doorX + 6} cy={doorY + doorH * 0.55} r={1.5} fill="#c15a4a" />
|
|
235
240
|
{/* base 床 (前 storefront 直下のみ) */}
|
|
@@ -262,7 +267,8 @@ const WAREHOUSE_W_MIN = 160;
|
|
|
262
267
|
const WAREHOUSE_W_MAX = 240;
|
|
263
268
|
|
|
264
269
|
/** shape-warehouse = W-A 大 shutter (平屋根 + WAREHOUSE 看板 + 中央大 shutter 10 rib + loading dock) */
|
|
265
|
-
export function ShapeWarehouseNode({ node, active }: ShapeProps): JSX.Element {
|
|
270
|
+
export function ShapeWarehouseNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
271
|
+
const 字引 = 字引きを作る(lang);
|
|
266
272
|
const frame = commonFrame(active);
|
|
267
273
|
const r = shapeRegion(node);
|
|
268
274
|
const cx = r.cx;
|
|
@@ -298,7 +304,7 @@ export function ShapeWarehouseNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
298
304
|
<rect data-cdl-role="node-body" x={x} y={y + roofH} width={bw} height={bh - roofH - 12} fill="#a89d8f" stroke="#5a6270" strokeWidth={frame.strokeWidth} />
|
|
299
305
|
{/* WAREHOUSE 看板 (赤帯) */}
|
|
300
306
|
<rect x={x} y={y + roofH} width={bw} height={signH} fill="#c15a4a" stroke="#8b3f2f" strokeWidth={1.5} />
|
|
301
|
-
<text x={cx} y={y + roofH + 17} fontSize={12} fontWeight={900} letterSpacing={6} textAnchor="middle" fill="#ffffff">
|
|
307
|
+
<text x={cx} y={y + roofH + 17} fontSize={12} fontWeight={900} letterSpacing={6} textAnchor="middle" fill="#ffffff">{字引("warehouse.sign")}</text>
|
|
302
308
|
{/* 中央大 shutter (rib 縞) */}
|
|
303
309
|
<rect x={shutterX} y={shutterY} width={shutterW} height={shutterH} fill="#8b949e" stroke={accentDarker} strokeWidth={2} />
|
|
304
310
|
{/* shutter 上部 shade (立体感) */}
|
|
@@ -499,7 +505,8 @@ const API_W_MIN = 200;
|
|
|
499
505
|
const API_W_MAX = 300;
|
|
500
506
|
|
|
501
507
|
/** shape-api-gateway = SaaS API panel (dark bg + method + path endpoints + status) */
|
|
502
|
-
export function ShapeApiGatewayNode({ node, active }: ShapeProps): JSX.Element {
|
|
508
|
+
export function ShapeApiGatewayNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
509
|
+
const 字引 = 字引きを作る(lang);
|
|
503
510
|
const frame = commonFrame(active);
|
|
504
511
|
const r = shapeRegion(node);
|
|
505
512
|
const cx = r.cx;
|
|
@@ -511,6 +518,11 @@ export function ShapeApiGatewayNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
511
518
|
const y = r.cy - 縦 / 2 + 余白;
|
|
512
519
|
const 広がり = { 上: 縦 / 2, 下: 縦 / 2, 左: bw / 2 + 余白, 右: bw / 2 + 余白 };
|
|
513
520
|
// 行は板の中で均す。 板が伸びたら間隔も伸びる = 下に空きだけが残らない
|
|
521
|
+
// 要求の種類の字は箱 (幅 54) に左右 3 ずつ空けて入る大きさで描く (#847)。 `GET` / `POST` / `DEL` は
|
|
522
|
+
// 11 のまま入り、長い綴り (日本語の辞書の `DELETE`) だけを縮める。 見積りは等幅と比例の大きい方
|
|
523
|
+
// (`shape-blockchain.tsx` の `字の幅` と同じ考え方で、どちらの書体で描かれても箱からはみ出さない)
|
|
524
|
+
const 種類の字 = (s: string): number =>
|
|
525
|
+
Math.min(11, (11 * 48) / Math.max(displayWidth(s) * 11 * MONO_ADVANCE_RATIO, textWidth(s, 11)));
|
|
514
526
|
const rowPitch = Math.max(
|
|
515
527
|
API_ROW_PITCH_MIN,
|
|
516
528
|
(bh - API_ROW_TOP - API_ROW_H - API_ROW_BOTTOM_PAD) / (API_ROWS - 1),
|
|
@@ -521,17 +533,17 @@ export function ShapeApiGatewayNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
521
533
|
<rect data-cdl-role="node-body" x={x} y={y} width={bw} height={bh} rx={10} fill="#1a2332" stroke={frame.stroke} strokeWidth={frame.strokeWidth} />
|
|
522
534
|
<rect x={x} y={y} width={bw} height={36} rx={10} fill="var(--cdl-tone-accent, #2d6a8f)" stroke="none" />
|
|
523
535
|
<text x={cx} y={y + 24} fontSize={14} fontWeight={700} letterSpacing={3} textAnchor="middle" fill="#ffffff" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
524
|
-
|
|
536
|
+
{字引("apiGateway.sign")}
|
|
525
537
|
</text>
|
|
526
538
|
{[
|
|
527
|
-
{ method: "GET", path: "
|
|
528
|
-
{ method: "POST", path: "
|
|
529
|
-
{ method: "
|
|
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" },
|
|
530
542
|
].map((e, i) => (
|
|
531
543
|
<g key={i} transform={`translate(${x + 16}, ${y + API_ROW_TOP + i * rowPitch})`}>
|
|
532
544
|
<rect x={0} y={0} width={bw - 32} height={API_ROW_H} rx={4} fill="#0f1419" stroke="none" />
|
|
533
545
|
<rect x={0} y={0} width={54} height={API_ROW_H} rx={4} fill={e.color} stroke="none" />
|
|
534
|
-
<text x={27} y={16} fontSize={
|
|
546
|
+
<text x={27} y={16} fontSize={種類の字(e.method)} fontWeight={700} textAnchor="middle" fill="#ffffff" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
535
547
|
{e.method}
|
|
536
548
|
</text>
|
|
537
549
|
<text x={64} y={16} fontSize={12} fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace" fill="#e6edf3">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
2
|
import { shapeRegion, labelPlan, fitArt } from "./shape-region";
|
|
3
3
|
import type { LaidNode } from "../types";
|
|
4
|
+
import { 字引きを作る, type CdlLang } from "../lang";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Shape-driven finance 7 kinds (CAR-1111 Phase 2-D)。
|
|
@@ -17,6 +18,8 @@ import type { LaidNode } from "../types";
|
|
|
17
18
|
type ShapeProps = {
|
|
18
19
|
node: LaidNode;
|
|
19
20
|
active: boolean;
|
|
21
|
+
/** 描画側の固定の字の言語 (#847)。 渡さない呼び方は英語で描く */
|
|
22
|
+
lang?: CdlLang;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
const commonFrame = (active: boolean) => ({
|
|
@@ -233,7 +236,8 @@ const TRUST_BLD_W_MIN = 140;
|
|
|
233
236
|
const TRUST_BLD_W_MAX = 280;
|
|
234
237
|
|
|
235
238
|
/** shape-trust-bank = 信託銀行 (王冠 + 神殿 3 columns、 中央柱に余計装飾なし) */
|
|
236
|
-
export function ShapeTrustBankNode({ node, active }: ShapeProps): JSX.Element {
|
|
239
|
+
export function ShapeTrustBankNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
240
|
+
const 字引 = 字引きを作る(lang);
|
|
237
241
|
const frame = commonFrame(active);
|
|
238
242
|
const r = shapeRegion(node);
|
|
239
243
|
const 線 = frame.strokeWidth / 2;
|
|
@@ -275,7 +279,7 @@ export function ShapeTrustBankNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
275
279
|
})}
|
|
276
280
|
<path d={`M ${x - 6} ${y + pedimentH} L ${r.cx} ${y + 2} L ${x + bldW + 6} ${y + pedimentH} Z`} fill="var(--cdl-node-fill, #ffffff)" stroke={frame.stroke} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
277
281
|
<text x={r.cx} y={y + pedimentH - 8} fontSize={15} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="var(--cdl-tone-accent, #2d6a8f)" fontFamily="Georgia, serif">
|
|
278
|
-
|
|
282
|
+
{字引("trustBank.sign")}
|
|
279
283
|
</text>
|
|
280
284
|
<rect x={x - 4} y={y + pedimentH} width={bldW + 8} height={architraveH} fill="var(--cdl-divider, #d4d4d8)" fillOpacity={0.4} stroke={frame.stroke} strokeWidth={frame.strokeWidth} />
|
|
281
285
|
{Array.from({ length: nCols }, (_, i) => i).map((i) => {
|
|
@@ -302,7 +306,8 @@ export function ShapeTrustBankNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
302
306
|
}
|
|
303
307
|
|
|
304
308
|
/** shape-payment-provider = P2-A base (中央 provider box + PAY header + processing spinner + PROCESSING label) */
|
|
305
|
-
export function ShapePaymentProviderNode({ node, active }: ShapeProps): JSX.Element {
|
|
309
|
+
export function ShapePaymentProviderNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
310
|
+
const 字引 = 字引きを作る(lang);
|
|
306
311
|
const frame = commonFrame(active);
|
|
307
312
|
const r = shapeRegion(node);
|
|
308
313
|
const cx = r.cx;
|
|
@@ -323,7 +328,7 @@ export function ShapePaymentProviderNode({ node, active }: ShapeProps): JSX.Elem
|
|
|
323
328
|
{/* PAY header */}
|
|
324
329
|
<rect x={x} y={y} width={boxW} height={headerH} rx={10} fill={accentDarker} />
|
|
325
330
|
<rect x={x} y={y + headerH - 8} width={boxW} height={8} fill={accentDarker} />
|
|
326
|
-
<text x={cx} y={y + 22} fontSize={16} fontWeight={700} letterSpacing={4} textAnchor="middle" fill="#e5c07b">
|
|
331
|
+
<text x={cx} y={y + 22} fontSize={16} fontWeight={700} letterSpacing={4} textAnchor="middle" fill="#e5c07b">{字引("paymentProvider.sign")}</text>
|
|
327
332
|
{/* processing spinner (rotate anim) */}
|
|
328
333
|
<g>
|
|
329
334
|
<circle cx={cx} cy={cy + 4} r={22} fill="none" stroke="#e5c07b" strokeWidth={3.5} strokeDasharray="38 24" strokeLinecap="round">
|
|
@@ -333,7 +338,7 @@ export function ShapePaymentProviderNode({ node, active }: ShapeProps): JSX.Elem
|
|
|
333
338
|
<text x={cx} y={cy + 9} fontSize={13} fontWeight={700} textAnchor="middle" fill={accentDarker} fontFamily="Georgia, serif">$</text>
|
|
334
339
|
</g>
|
|
335
340
|
{/* PROCESSING label */}
|
|
336
|
-
<text x={cx} y={y + boxH - 16} fontSize={9} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#a4b5f2">
|
|
341
|
+
<text x={cx} y={y + boxH - 16} fontSize={9} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#a4b5f2">{字引("paymentProvider.status")}</text>
|
|
337
342
|
{bottomLabel(node, r.cx, r.label)}
|
|
338
343
|
</g>
|
|
339
344
|
);
|
|
@@ -416,7 +421,8 @@ const BROKERAGE_W_MAX = 140;
|
|
|
416
421
|
const BROKERAGE_H_MIN = BROKERAGE_TICK_H + BROKERAGE_LOGO_H + BROKERAGE_BASE_H;
|
|
417
422
|
|
|
418
423
|
/** shape-brokerage = B2-A 大和証券風 (縦長本社 + 上部電光 + $ SECURITIES ロゴ帯 + window grid + entrance 回転扉) */
|
|
419
|
-
export function ShapeBrokerageNode({ node, active }: ShapeProps): JSX.Element {
|
|
424
|
+
export function ShapeBrokerageNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
425
|
+
const 字引 = 字引きを作る(lang);
|
|
420
426
|
const frame = commonFrame(active);
|
|
421
427
|
const r = shapeRegion(node);
|
|
422
428
|
const cx = r.cx;
|
|
@@ -460,12 +466,12 @@ export function ShapeBrokerageNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
460
466
|
<rect x={x} y={y} width={w} height={BROKERAGE_TICK_H} fill="#0f1830" stroke="none" />
|
|
461
467
|
<rect x={x + 2} y={y + 2} width={w - 4} height={8} fill="#1a2340" stroke="none" />
|
|
462
468
|
<text x={cx} y={y + 9} fontSize={5.5} fontWeight={700} textAnchor="middle" fill="#4ea36a" fontFamily="ui-monospace, SFMono-Regular, Menlo, monospace">
|
|
463
|
-
|
|
469
|
+
{字引("brokerage.ticker")}
|
|
464
470
|
</text>
|
|
465
471
|
{/* $ SECURITIES ロゴ帯 */}
|
|
466
472
|
<rect x={x} y={y + BROKERAGE_TICK_H} width={w} height={BROKERAGE_LOGO_H} fill="#e5c07b" stroke="none" />
|
|
467
473
|
<text x={cx} y={y + 30} fontSize={12} fontWeight={700} letterSpacing={2.5} textAnchor="middle" fill="#0f1830">
|
|
468
|
-
|
|
474
|
+
{字引("brokerage.sign")}
|
|
469
475
|
</text>
|
|
470
476
|
{/* window grid (段数は高さ次第、 列は 6 固定) */}
|
|
471
477
|
{Array.from({ length: rows }).map((_, ri) =>
|
|
@@ -496,7 +502,8 @@ export function ShapeBrokerageNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
496
502
|
}
|
|
497
503
|
|
|
498
504
|
/** shape-exchange = E2-A 中央 clearing house (hexagon EXCHANGE + 放射 8 node + 双方向 tx dots) */
|
|
499
|
-
export function ShapeExchangeNode({ node, active }: ShapeProps): JSX.Element {
|
|
505
|
+
export function ShapeExchangeNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
506
|
+
const 字引 = 字引きを作る(lang);
|
|
500
507
|
const frame = commonFrame(active);
|
|
501
508
|
const r = shapeRegion(node);
|
|
502
509
|
const cx = r.cx;
|
|
@@ -560,11 +567,11 @@ export function ShapeExchangeNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
560
567
|
})}
|
|
561
568
|
{/* 中央 hexagon EXCHANGE (単色 #255a7a、 縦向き正六角形) */}
|
|
562
569
|
<path d={hexPath} fill="#255a7a" stroke={accentDarker} strokeWidth={frame.strokeWidth} strokeLinejoin="round" />
|
|
563
|
-
<text x={cx} y={cy - 8} fontSize={10} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">
|
|
570
|
+
<text x={cx} y={cy - 8} fontSize={10} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("exchange.sign")}</text>
|
|
564
571
|
{/* swap 記号 */}
|
|
565
572
|
<text data-cdl-role="node-body" x={cx} y={cy + 12} fontSize={22} fontWeight={700} textAnchor="middle" fill="#e5c07b">⇄</text>
|
|
566
573
|
{/* clearing label */}
|
|
567
|
-
<text x={cx} y={cy + 26} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">
|
|
574
|
+
<text x={cx} y={cy + 26} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">{字引("exchange.sub")}</text>
|
|
568
575
|
{/* 8 外周 node (buyer/seller) */}
|
|
569
576
|
{nodes.map((n, i) => (
|
|
570
577
|
<circle key={`n${i}`} cx={n.cx} cy={n.cy} r={8} fill={n.fill} stroke={accentDarker} strokeWidth={1.5} />
|
|
@@ -610,7 +617,8 @@ const ATM_W_MAX = 140;
|
|
|
610
617
|
const ATM_H_MIN = ATM_SIGN_H + ATM_SIGN_GAP + 30 + ATM_FLOOR_RESERVE;
|
|
611
618
|
|
|
612
619
|
/** shape-atm = A3-C1 (支店内 ATM 単体、 上部 ATM CORNER 天井看板 + 中央 ATM 大 + 直下床帯) */
|
|
613
|
-
export function ShapeAtmNode({ node, active }: ShapeProps): JSX.Element {
|
|
620
|
+
export function ShapeAtmNode({ node, active, lang }: ShapeProps): JSX.Element {
|
|
621
|
+
const 字引 = 字引きを作る(lang);
|
|
614
622
|
const frame = commonFrame(active);
|
|
615
623
|
const r = shapeRegion(node);
|
|
616
624
|
const cx = r.cx;
|
|
@@ -652,21 +660,21 @@ export function ShapeAtmNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
652
660
|
<ellipse cx={cx} cy={y + totalH + ATM_SHADOW_DY} rx={totalW * ATM_SHADOW_RX_RATIO} ry={ATM_SHADOW_RY} fill={frame.stroke} opacity={0.15} stroke="none" />
|
|
653
661
|
{/* 天井 ATM CORNER 看板 */}
|
|
654
662
|
<rect x={centerX - totalW / 2} y={signY} width={totalW} height={signH} fill={accentDarker} stroke="#000" strokeWidth={ATM_SIGN_SW} />
|
|
655
|
-
<text x={centerX} y={signY + 17} fontSize={11} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">
|
|
663
|
+
<text x={centerX} y={signY + 17} fontSize={11} fontWeight={700} letterSpacing={2} textAnchor="middle" fill="#e5c07b">{字引("atm.sign")}</text>
|
|
656
664
|
{/* ATM body */}
|
|
657
665
|
<rect data-cdl-role="node-body" x={atmX} y={atmY} width={atmW} height={atmH} rx={6} fill="#255a7a" stroke={accentDarker} strokeWidth={frame.strokeWidth} />
|
|
658
666
|
<g transform={`translate(${centerX} ${atmY}) scale(${面})`}>
|
|
659
667
|
{/* screen */}
|
|
660
668
|
<rect x={面左 + 8} y={10} width={ATM_PANEL_W - 16} height={52} rx={3} fill="#0f1830" stroke="#000" strokeWidth={1.5} />
|
|
661
669
|
<text x={0} y={30} fontSize={10} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">お引出し</text>
|
|
662
|
-
<text x={0} y={44} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">
|
|
670
|
+
<text x={0} y={44} fontSize={8} fontWeight={700} textAnchor="middle" fill="#a4b5f2">{字引("atm.screen")}</text>
|
|
663
671
|
<text x={0} y={56} fontSize={10} fontWeight={700} textAnchor="middle" fill="#4ea36a">¥ 20,000</text>
|
|
664
672
|
{/* keypad 5x2 */}
|
|
665
673
|
<rect x={面左 + 8} y={68} width={ATM_PANEL_W - 16} height={42} rx={2} fill="#8b949e" stroke="#5a6270" strokeWidth={1} />
|
|
666
674
|
{(() => {
|
|
667
675
|
const keys = [
|
|
668
676
|
["1", "#5a6270"], ["2", "#5a6270"], ["3", "#5a6270"], ["C", "#5a6270"], ["X", "#c15a4a"],
|
|
669
|
-
["4", "#5a6270"], ["5", "#5a6270"], ["6", "#5a6270"], ["0", "#5a6270"], ["
|
|
677
|
+
["4", "#5a6270"], ["5", "#5a6270"], ["6", "#5a6270"], ["0", "#5a6270"], [字引("atm.ok"), "#4ea36a"],
|
|
670
678
|
];
|
|
671
679
|
const keyW = 18;
|
|
672
680
|
const keyH = 10;
|
|
@@ -680,7 +688,7 @@ export function ShapeAtmNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
680
688
|
return (
|
|
681
689
|
<g key={`k${i}`}>
|
|
682
690
|
<rect x={kx} y={ky} width={keyW} height={keyH} fill={k[1]} stroke="#0f1830" strokeWidth={0.8} />
|
|
683
|
-
<text x={kx + keyW / 2} y={ky + 7} fontSize={
|
|
691
|
+
<text x={kx + keyW / 2} y={ky + 7} fontSize={/* 決める鍵 (末尾) は 2 字あるので小さく描く。 字は言語で変わるため位置で見分ける */ i === keys.length - 1 ? 6 : 7} fontWeight={700} textAnchor="middle" fill="#ffffff">{k[0]}</text>
|
|
684
692
|
</g>
|
|
685
693
|
);
|
|
686
694
|
});
|
|
@@ -688,7 +696,7 @@ export function ShapeAtmNode({ node, active }: ShapeProps): JSX.Element {
|
|
|
688
696
|
{/* card slot */}
|
|
689
697
|
<rect x={面左 + 12} y={116} width={ATM_PANEL_W - 24} height={8} rx={1.5} fill="#0f1830" stroke={accentDarker} strokeWidth={1} />
|
|
690
698
|
<rect x={面左 + 15} y={118} width={ATM_PANEL_W - 30} height={4} rx={0.5} fill="#e5c07b" />
|
|
691
|
-
<text x={0} y={132} fontSize={6} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">
|
|
699
|
+
<text x={0} y={132} fontSize={6} fontWeight={700} letterSpacing={1} textAnchor="middle" fill="#e5c07b">{字引("atm.cardSlot")}</text>
|
|
692
700
|
{/* cash slot */}
|
|
693
701
|
<rect x={面左 + 12} y={136} width={ATM_PANEL_W - 24} height={4} rx={1} fill="#0f1830" />
|
|
694
702
|
</g>
|