@cardenelabs/cdl 0.40.1 → 0.40.3

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 CHANGED
@@ -5,6 +5,48 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.40.3] - 2026-09-07
9
+
10
+ ### Fixed
11
+
12
+ - **半円ゲージの内訳の数字が隣とくっつくのを直した** (#731)
13
+
14
+ 下段の内訳は件数で横に等分し、**名前だけを区画に収まるまで切り詰めて数値はそのまま**
15
+ 置いていた。 件数が増えると数字が隣の区画へはみ出し、`10 5.4%11 5.9%` のように
16
+ くっついて読めなかった。 実測で件数 10 から重なり始め、12 で 10 組、24 で 43 組。
17
+
18
+ **区画の幅を中身から決める**。 数値の行が要る幅に区画どうしの間を足したものを 1 件の
19
+ 幅とし、枠に何件置けるかを出す。 入り切らない件は次の段へ送る。 段が増えたぶん弧は
20
+ 低くなる = 弧の高さは内訳を取り分けた残りから決めているので自動で縮む。
21
+
22
+ **数値も名前と同じ幅で切り詰める**。 1 行 1 件しか置けない細い枠では折り返せないため、
23
+ 切り詰めだけが最後の受けになる。 色の印も区画より広いときは区画に合わせて縮む。
24
+
25
+ 級を下げて 1 行に収める案は採らない = 件数 12 では級 7.7 が要り、この repo が他の図で
26
+ 使っている下限の 9 を下回る。
27
+
28
+ ## [0.40.2] - 2026-09-07
29
+
30
+ ### Fixed
31
+
32
+ - **円グラフで小さい取り分が続くと名札が重なるのを直した** (#727)
33
+
34
+ 名札 (割合と名前) は扇の中央角の向きに置いていたので、**角度が近い扇が続くと同じ場所に
35
+ 印字されて読めなかった**。 実測で 0.3% の小片 2 個が完全に重なり、割合の字 (級 19 の
36
+ 太字) が真っ黒な塊になっていた。 小片を 5 個にすると重なりは 20 組に増える。
37
+ 件数 12 の図でも上部の `5.4%` と `5.9%` がぶつかっていた。
38
+
39
+ **縦は重なりをほどく**。 傾き図で入れたのと同じ形 (#723) で、重なった連なりを元の位置の
40
+ 平均を中心にして等間隔に置き直す。 ほどきの計算は `kinds/label-stack.ts` に移して
41
+ 傾き図と共用する。
42
+
43
+ **横は左右の列に揃える**。 角度から決めたままだと、縦をずらした名札が円の上へ乗る。
44
+ 引き出し線の肘も列の手前に置くので、線が円を横切らない。
45
+
46
+ 扇と縁の点は動かさない = どの扇の名札かは引き出し線と縁の色の点が示す。
47
+
48
+ 段の `draw` の途中でも名札は動かない。 まだ開いていない扇も数に入れてほどくため。
49
+
8
50
  ## [0.40.1] - 2026-09-07
9
51
 
10
52
  ### Fixed
@@ -1801,7 +1843,9 @@ Initial OSS release.
1801
1843
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
1802
1844
  行き止まりになる。
1803
1845
 
1804
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.40.1...HEAD
1846
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.40.3...HEAD
1847
+ [0.40.3]: https://github.com/cardene777/cdl/compare/v0.40.2...v0.40.3
1848
+ [0.40.2]: https://github.com/cardene777/cdl/compare/v0.40.1...v0.40.2
1805
1849
  [0.40.1]: https://github.com/cardene777/cdl/compare/v0.40.0...v0.40.1
1806
1850
  [0.40.0]: https://github.com/cardene777/cdl/compare/v0.39.0...v0.40.0
1807
1851
  [0.39.0]: https://github.com/cardene777/cdl/compare/v0.38.0...v0.39.0
package/dist/index.cjs CHANGED
@@ -24358,6 +24358,38 @@ function interpolateColor(template, stateValues, fallback) {
24358
24358
  if (!template) return fallback;
24359
24359
  return interpolate(template, stateValues);
24360
24360
  }
24361
+
24362
+ // src/kinds/label-stack.ts
24363
+ function \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(\u771F\u306Ey, \u9593\u9694, \u4E0A\u9650, \u4E0B\u9650) {
24364
+ const \u4EF6\u6570 = \u771F\u306Ey.length;
24365
+ if (\u4EF6\u6570 === 0) return [];
24366
+ const \u4E26\u3073 = \u771F\u306Ey.map((y, i) => ({ y, i })).sort((a, b) => a.y - b.y || a.i - b.i);
24367
+ const \u7D50\u679C = new Array(\u4EF6\u6570);
24368
+ if (\u9593\u9694 * (\u4EF6\u6570 - 1) > \u4E0B\u9650 - \u4E0A\u9650) {
24369
+ \u4E26\u3073.forEach((e, k) => {
24370
+ \u7D50\u679C[e.i] = \u4EF6\u6570 > 1 ? \u4E0A\u9650 + (\u4E0B\u9650 - \u4E0A\u9650) / (\u4EF6\u6570 - 1) * k : (\u4E0A\u9650 + \u4E0B\u9650) / 2;
24371
+ });
24372
+ return \u7D50\u679C;
24373
+ }
24374
+ const \u584A\u305F\u3061 = [];
24375
+ \u4E26\u3073.forEach((e, k) => {
24376
+ \u584A\u305F\u3061.push({ \u5408\u8A08: e.y - \u9593\u9694 * k, \u4EF6\u6570: 1 });
24377
+ while (\u584A\u305F\u3061.length >= 2) {
24378
+ const \u5F8C = \u584A\u305F\u3061[\u584A\u305F\u3061.length - 1];
24379
+ const \u524D = \u584A\u305F\u3061[\u584A\u305F\u3061.length - 2];
24380
+ if (\u524D.\u5408\u8A08 / \u524D.\u4EF6\u6570 <= \u5F8C.\u5408\u8A08 / \u5F8C.\u4EF6\u6570) break;
24381
+ \u584A\u305F\u3061.splice(\u584A\u305F\u3061.length - 2, 2, { \u5408\u8A08: \u524D.\u5408\u8A08 + \u5F8C.\u5408\u8A08, \u4EF6\u6570: \u524D.\u4EF6\u6570 + \u5F8C.\u4EF6\u6570 });
24382
+ }
24383
+ });
24384
+ const \u307B\u3069\u3044\u305F = [];
24385
+ \u584A\u305F\u3061.forEach((\u584A) => {
24386
+ const \u5E73\u5747 = \u584A.\u5408\u8A08 / \u584A.\u4EF6\u6570;
24387
+ for (let j = 0; j < \u584A.\u4EF6\u6570; j++) \u307B\u3069\u3044\u305F.push(\u5E73\u5747 + \u9593\u9694 * \u307B\u3069\u3044\u305F.length);
24388
+ });
24389
+ const \u305A\u308C = Math.max(0, \u4E0A\u9650 - \u307B\u3069\u3044\u305F[0]) - Math.max(0, \u307B\u3069\u3044\u305F[\u4EF6\u6570 - 1] - \u4E0B\u9650);
24390
+ \u4E26\u3073.forEach((e, k) => \u7D50\u679C[e.i] = \u307B\u3069\u3044\u305F[k] + \u305A\u308C);
24391
+ return \u7D50\u679C;
24392
+ }
24361
24393
  function \u6247\u5F62\u306E\u5207\u308A\u629C\u304D(cx, cy, r, \u958B\u304D, \u8D77\u70B9 = -Math.PI / 2, \u5168\u5468 = Math.PI * 2) {
24362
24394
  if (\u958B\u304D <= 0) return null;
24363
24395
  if (\u958B\u304D >= 1 && \u5168\u5468 >= Math.PI * 2) return /* @__PURE__ */ jsxRuntime.jsx("circle", { cx, cy, r });
@@ -24438,6 +24470,26 @@ function ChartPieNode({
24438
24470
  const \u5207\u308A\u629C\u304Did = `cdl-pie-draw-${instanceId}`;
24439
24471
  const \u5F71id = `cdl-pie-shadow-${instanceId}`;
24440
24472
  const \u958B\u304D\u59CB\u3081\u305F = (startFrac) => !drawing || \u958B\u304D > startFrac;
24473
+ const \u540D\u672D\u306E\u884C = \u5272\u5408\u306E\u7D1A + \u540D\u524D\u306E\u7D1A + 3;
24474
+ const \u540D\u672D\u306E\u5074 = slices.map((s) => Math.cos(s.\u4E2D\u592E\u89D2) >= 0);
24475
+ const \u540D\u672D\u306E\u771F\u306Ey = slices.map((s) => cy + (radius + \u5F15\u304D\u51FA\u3057) * Math.sin(s.\u4E2D\u592E\u89D2));
24476
+ const \u540D\u672D\u306Ey = (() => {
24477
+ const \u51FA\u3059 = [...\u540D\u672D\u306E\u771F\u306Ey];
24478
+ for (const \u5074 of [true, false]) {
24479
+ const \u756A\u53F7 = \u540D\u672D\u306E\u5074.flatMap((\u53F3, i) => \u53F3 === \u5074 ? [i] : []);
24480
+ if (\u756A\u53F7.length === 0) continue;
24481
+ const \u76F4\u3057\u305F = \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(
24482
+ \u756A\u53F7.map((i) => \u540D\u672D\u306E\u771F\u306Ey[i]),
24483
+ \u540D\u672D\u306E\u884C,
24484
+ PAD_TOP2 + \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057,
24485
+ node.h - PAD_BOTTOM2 - \u540D\u672D\u306E\u7E26\u306E\u5F35\u308A\u51FA\u3057
24486
+ );
24487
+ \u756A\u53F7.forEach((i, k) => \u51FA\u3059[i] = \u76F4\u3057\u305F[k]);
24488
+ }
24489
+ return \u51FA\u3059;
24490
+ })();
24491
+ const \u8098\u306Ex = (\u53F3) => cx + (\u53F3 ? 1 : -1) * (radius + \u5F15\u304D\u51FA\u3057);
24492
+ const \u5B57\u306Ex = (\u53F3) => \u8098\u306Ex(\u53F3) + (\u53F3 ? \u5B57\u307E\u3067\u306E\u9593 : -\u5B57\u307E\u3067\u306E\u9593);
24441
24493
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x0} ${y0})`, children: [
24442
24494
  /* @__PURE__ */ jsxRuntime.jsx(
24443
24495
  "rect",
@@ -24510,12 +24562,12 @@ function ChartPieNode({
24510
24562
  ),
24511
24563
  slices.map((s, idx) => {
24512
24564
  if (!\u958B\u304D\u59CB\u3081\u305F(s.startFrac)) return null;
24513
- const \u53F3 = Math.cos(s.\u4E2D\u592E\u89D2) >= 0;
24565
+ const \u53F3 = \u540D\u672D\u306E\u5074[idx];
24514
24566
  const \u7E01x = cx + radius * Math.cos(s.\u4E2D\u592E\u89D2);
24515
24567
  const \u7E01y = cy + radius * Math.sin(s.\u4E2D\u592E\u89D2);
24516
- const \u6298\u308Cx = cx + (radius + \u5F15\u304D\u51FA\u3057) * Math.cos(s.\u4E2D\u592E\u89D2);
24517
- const \u6298\u308Cy = cy + (radius + \u5F15\u304D\u51FA\u3057) * Math.sin(s.\u4E2D\u592E\u89D2);
24518
- const \u5B57x = \u6298\u308Cx + (\u53F3 ? \u5B57\u307E\u3067\u306E\u9593 : -\u5B57\u307E\u3067\u306E\u9593);
24568
+ const \u6298\u308Cx = \u8098\u306Ex(\u53F3);
24569
+ const \u6298\u308Cy = \u540D\u672D\u306Ey[idx];
24570
+ const \u5B57x = \u5B57\u306Ex(\u53F3);
24519
24571
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
24520
24572
  /* @__PURE__ */ jsxRuntime.jsx(
24521
24573
  "path",
@@ -24836,8 +24888,18 @@ function ChartGaugeNode({
24836
24888
  const \u4F7F\u3048\u308B\u5E452 = node.w - PAD_SIDE * 2;
24837
24889
  const \u540D\u524D\u306E\u7D1A = 14;
24838
24890
  const \u6570\u5024\u306E\u7D1A = 13;
24839
- const \u5185\u8A33\u306E\u9AD8\u3055 = 56;
24891
+ const \u6BB5\u306E\u9AD8\u3055 = 56;
24840
24892
  const \u5F27\u3068\u5185\u8A33\u306E\u9593 = 16;
24893
+ const \u5370\u306E\u5E452 = 30;
24894
+ const \u533A\u753B\u306E\u9593 = 12;
24895
+ const \u5185\u8A33\u306E\u6570\u5024 = data.map((d) => `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u8868\u8A18(d.value / total)}`);
24896
+ const \u4EF6\u306B\u8981\u308B\u5E45 = Math.max(\u5370\u306E\u5E452, ...\u5185\u8A33\u306E\u6570\u5024.map((t) => textWidth(t, \u6570\u5024\u306E\u7D1A))) + \u533A\u753B\u306E\u9593;
24897
+ const \u884C\u306E\u4EF6\u6570 = Math.min(
24898
+ Math.max(1, Math.floor(\u4F7F\u3048\u308B\u5E452 / Math.max(\u4EF6\u306B\u8981\u308B\u5E45, 1))),
24899
+ Math.max(data.length, 1)
24900
+ );
24901
+ const \u5185\u8A33\u306E\u6BB5\u6570 = Math.ceil(Math.max(data.length, 1) / \u884C\u306E\u4EF6\u6570);
24902
+ const \u5185\u8A33\u306E\u9AD8\u3055 = \u6BB5\u306E\u9AD8\u3055 * \u5185\u8A33\u306E\u6BB5\u6570;
24841
24903
  const \u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055 = \u4F7F\u3048\u308B\u9AD8\u3055 - \u5185\u8A33\u306E\u9AD8\u3055 - \u5F27\u3068\u5185\u8A33\u306E\u9593;
24842
24904
  const radius = Math.max(24, Math.min(\u5F27\u306B\u4F7F\u3048\u308B\u9AD8\u3055, \u4F7F\u3048\u308B\u5E452 / 2));
24843
24905
  const \u5185\u534A\u5F84 = radius * 0.62;
@@ -24866,7 +24928,7 @@ function ChartGaugeNode({
24866
24928
  );
24867
24929
  const \u5408\u8A08\u306E\u7D1A = Math.max(11, Math.round(\u7D1A\u306E\u5019\u88DC));
24868
24930
  const \u898B\u51FA\u3057\u306E\u7D1A = Math.max(9, Math.round(\u5408\u8A08\u306E\u7D1A * 0.38));
24869
- const \u5185\u8A33\u306E\u5E45 = \u4F7F\u3048\u308B\u5E452 / Math.max(data.length, 1);
24931
+ const \u5185\u8A33\u306E\u5E45 = \u4F7F\u3048\u308B\u5E452 / \u884C\u306E\u4EF6\u6570;
24870
24932
  const \u5185\u8A33\u306Ey = cy + \u5F27\u3068\u5185\u8A33\u306E\u9593;
24871
24933
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
24872
24934
  const \u5207\u308A\u629C\u304Did = `cdl-gauge-draw-${react.useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
@@ -24924,22 +24986,35 @@ function ChartGaugeNode({
24924
24986
  }
24925
24987
  ),
24926
24988
  data.map((d, idx) => {
24927
- const x = PAD_SIDE + \u5185\u8A33\u306E\u5E45 * idx;
24928
- const \u6570\u5024 = `${\u5B9F\u5024\u8868\u8A18(d.value)} ${\u5272\u5408\u8868\u8A18(d.value / total)}`;
24989
+ const \u5217 = idx % \u884C\u306E\u4EF6\u6570;
24990
+ const \u6BB5 = Math.floor(idx / \u884C\u306E\u4EF6\u6570);
24991
+ const x = PAD_SIDE + \u5185\u8A33\u306E\u5E45 * \u5217;
24992
+ const y = \u5185\u8A33\u306Ey + \u6BB5\u306E\u9AD8\u3055 * \u6BB5;
24993
+ const \u53CE\u307E\u308B\u5E45 = \u5185\u8A33\u306E\u5E45 - \u533A\u753B\u306E\u9593;
24929
24994
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
24930
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x, y: \u5185\u8A33\u306Ey, width: 30, height: 4, rx: 2, fill: arcColor(d.tone, idx) }),
24995
+ /* @__PURE__ */ jsxRuntime.jsx(
24996
+ "rect",
24997
+ {
24998
+ x,
24999
+ y,
25000
+ width: Math.max(4, Math.min(\u5370\u306E\u5E452, \u53CE\u307E\u308B\u5E45)),
25001
+ height: 4,
25002
+ rx: 2,
25003
+ fill: arcColor(d.tone, idx)
25004
+ }
25005
+ ),
24931
25006
  /* @__PURE__ */ jsxRuntime.jsx(
24932
25007
  "text",
24933
25008
  {
24934
25009
  x,
24935
- y: \u5185\u8A33\u306Ey + 26,
25010
+ y: y + 26,
24936
25011
  fontSize: \u540D\u524D\u306E\u7D1A,
24937
25012
  fontWeight: 700,
24938
25013
  fill: "var(--cdl-text, #1a1f2a)",
24939
- children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u5185\u8A33\u306E\u5E45 - 12, \u540D\u524D\u306E\u7D1A)
25014
+ children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A)
24940
25015
  }
24941
25016
  ),
24942
- /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: \u5185\u8A33\u306Ey + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u6570\u5024 })
25017
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: y + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u5207\u308A\u8A70\u3081\u308B(\u5185\u8A33\u306E\u6570\u5024[idx] ?? "", \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A) })
24943
25018
  ] }, `legend-${idx}`);
24944
25019
  })
24945
25020
  ] });
@@ -25528,36 +25603,6 @@ function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A) {
25528
25603
  return out;
25529
25604
  }
25530
25605
  var \u7DDA\u306E\u6700\u5C0F\u5E45 = 120;
25531
- function \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(\u771F\u306Ey, \u9593\u9694, \u4E0A\u9650, \u4E0B\u9650) {
25532
- const \u4EF6\u6570 = \u771F\u306Ey.length;
25533
- if (\u4EF6\u6570 === 0) return [];
25534
- const \u4E26\u3073 = \u771F\u306Ey.map((y, i) => ({ y, i })).sort((a, b) => a.y - b.y || a.i - b.i);
25535
- const \u7D50\u679C = new Array(\u4EF6\u6570);
25536
- if (\u9593\u9694 * (\u4EF6\u6570 - 1) > \u4E0B\u9650 - \u4E0A\u9650) {
25537
- \u4E26\u3073.forEach((e, k) => {
25538
- \u7D50\u679C[e.i] = \u4EF6\u6570 > 1 ? \u4E0A\u9650 + (\u4E0B\u9650 - \u4E0A\u9650) / (\u4EF6\u6570 - 1) * k : (\u4E0A\u9650 + \u4E0B\u9650) / 2;
25539
- });
25540
- return \u7D50\u679C;
25541
- }
25542
- const \u584A\u305F\u3061 = [];
25543
- \u4E26\u3073.forEach((e, k) => {
25544
- \u584A\u305F\u3061.push({ \u5408\u8A08: e.y - \u9593\u9694 * k, \u4EF6\u6570: 1 });
25545
- while (\u584A\u305F\u3061.length >= 2) {
25546
- const \u5F8C = \u584A\u305F\u3061[\u584A\u305F\u3061.length - 1];
25547
- const \u524D = \u584A\u305F\u3061[\u584A\u305F\u3061.length - 2];
25548
- if (\u524D.\u5408\u8A08 / \u524D.\u4EF6\u6570 <= \u5F8C.\u5408\u8A08 / \u5F8C.\u4EF6\u6570) break;
25549
- \u584A\u305F\u3061.splice(\u584A\u305F\u3061.length - 2, 2, { \u5408\u8A08: \u524D.\u5408\u8A08 + \u5F8C.\u5408\u8A08, \u4EF6\u6570: \u524D.\u4EF6\u6570 + \u5F8C.\u4EF6\u6570 });
25550
- }
25551
- });
25552
- const \u307B\u3069\u3044\u305F = [];
25553
- \u584A\u305F\u3061.forEach((\u584A) => {
25554
- const \u5E73\u5747 = \u584A.\u5408\u8A08 / \u584A.\u4EF6\u6570;
25555
- for (let j = 0; j < \u584A.\u4EF6\u6570; j++) \u307B\u3069\u3044\u305F.push(\u5E73\u5747 + \u9593\u9694 * \u307B\u3069\u3044\u305F.length);
25556
- });
25557
- const \u305A\u308C = Math.max(0, \u4E0A\u9650 - \u307B\u3069\u3044\u305F[0]) - Math.max(0, \u307B\u3069\u3044\u305F[\u4EF6\u6570 - 1] - \u4E0B\u9650);
25558
- \u4E26\u3073.forEach((e, k) => \u7D50\u679C[e.i] = \u307B\u3069\u3044\u305F[k] + \u305A\u308C);
25559
- return \u7D50\u679C;
25560
- }
25561
25606
  function ChartSlopeNode({
25562
25607
  node,
25563
25608
  active,