bazi-chart 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,646 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BaziChart: () => BaziChart,
24
+ ELEMENT_COLORS: () => ELEMENT_COLORS,
25
+ NEUTRAL_COLOR: () => NEUTRAL_COLOR,
26
+ PALETTES: () => PALETTES,
27
+ branchElement: () => branchElement,
28
+ branchZodiac: () => branchZodiac,
29
+ combine: () => combine,
30
+ detectEngine: () => detectEngine,
31
+ elementColor: () => elementColor,
32
+ elementKeyOf: () => elementKeyOf,
33
+ fromBaziObject: () => fromBaziObject,
34
+ fromPillarMap: () => fromPillarMap,
35
+ labelText: () => labelText,
36
+ normalize: () => normalize,
37
+ stemElement: () => stemElement,
38
+ valueText: () => valueText
39
+ });
40
+ module.exports = __toCommonJS(index_exports);
41
+
42
+ // src/adapters/baziObject.ts
43
+ var import_bazi_terms = require("bazi-terms");
44
+ var POSITION_ZH = {
45
+ \u5E74\u67F1: "year",
46
+ \u6708\u67F1: "month",
47
+ \u65E5\u67F1: "day",
48
+ \u65F6\u67F1: "hour"
49
+ };
50
+ function splitVoid(v) {
51
+ if (typeof v !== "string" || v.length === 0) return void 0;
52
+ return Array.from(v);
53
+ }
54
+ function branchesInText(desc) {
55
+ return Array.from(desc).filter((ch) => ch in import_bazi_terms.BRANCH_BY_CHAR);
56
+ }
57
+ function adaptPillar(position, raw) {
58
+ const hiddenRaw = Array.isArray(raw["\u85CF\u5E72\u8BE6\u60C5"]) ? raw["\u85CF\u5E72\u8BE6\u60C5"] : [];
59
+ const secondary = Array.isArray(raw["\u526F\u661F"]) ? raw["\u526F\u661F"] : [];
60
+ const hiddenStems = hiddenRaw.map((h, i) => ({
61
+ char: String(h["\u5E72"] ?? ""),
62
+ tenGod: secondary[i],
63
+ isMain: i === 0
64
+ }));
65
+ return {
66
+ position,
67
+ ganZhi: String(raw["\u5E72\u652F"] ?? ""),
68
+ stem: String(raw["\u5929\u5E72"] ?? ""),
69
+ branch: String(raw["\u5730\u652F"] ?? ""),
70
+ mainTenGod: raw["\u4E3B\u661F"] != null ? String(raw["\u4E3B\u661F"]) : void 0,
71
+ secondaryTenGods: secondary.length ? secondary : void 0,
72
+ hiddenStems,
73
+ naYin: raw["\u7EB3\u97F3"] != null ? String(raw["\u7EB3\u97F3"]) : void 0,
74
+ growthStage: raw["\u661F\u8FD0"] != null ? String(raw["\u661F\u8FD0"]) : void 0,
75
+ voidBranches: splitVoid(raw["\u7A7A\u4EA1"]),
76
+ shenSha: Array.isArray(raw["\u795E\u715E"]) ? raw["\u795E\u715E"] : void 0
77
+ };
78
+ }
79
+ function adaptInteractions(raw) {
80
+ const out = [];
81
+ const stems = Array.isArray(raw["\u5929\u5E72"]) ? raw["\u5929\u5E72"] : [];
82
+ const branches = Array.isArray(raw["\u5730\u652F"]) ? raw["\u5730\u652F"] : [];
83
+ for (const s of stems) {
84
+ const desc = String(s);
85
+ out.push({
86
+ typeKey: desc.includes("\u5408") ? "stemCombination" : void 0,
87
+ branches: branchesInText(desc),
88
+ description: desc
89
+ });
90
+ }
91
+ for (const b of branches) {
92
+ const desc = String(b);
93
+ out.push({
94
+ typeKey: (0, import_bazi_terms.interactionFromZh)(desc)?.key,
95
+ branches: branchesInText(desc),
96
+ description: desc
97
+ });
98
+ }
99
+ return out;
100
+ }
101
+ function adaptFiveElements(raw) {
102
+ if (!raw || typeof raw !== "object") return void 0;
103
+ const scores = [];
104
+ for (const el of ["\u91D1", "\u6728", "\u6C34", "\u706B", "\u571F"]) {
105
+ const entry = raw[el];
106
+ if (entry && typeof entry === "object") {
107
+ scores.push({
108
+ element: el,
109
+ score: typeof entry["\u5206\u503C"] === "number" ? entry["\u5206\u503C"] : void 0,
110
+ percent: entry["\u5360\u6BD4"] != null ? String(entry["\u5360\u6BD4"]) : void 0
111
+ });
112
+ }
113
+ }
114
+ return scores.length ? scores : void 0;
115
+ }
116
+ function adaptDaYun(list) {
117
+ if (!Array.isArray(list)) return [];
118
+ return list.map((raw) => ({
119
+ ganZhi: String(raw["\u5E72\u652F"] ?? ""),
120
+ stem: raw["\u5929\u5E72"] != null ? String(raw["\u5929\u5E72"]) : void 0,
121
+ branch: raw["\u5730\u652F"] != null ? String(raw["\u5730\u652F"]) : void 0,
122
+ stemTenGod: raw["\u4E3B\u661F"] != null ? String(raw["\u4E3B\u661F"]) : void 0,
123
+ startAge: typeof raw["\u8D77\u59CB\u5E74\u9F84"] === "number" ? raw["\u8D77\u59CB\u5E74\u9F84"] : void 0,
124
+ endAge: typeof raw["\u7ED3\u675F\u5E74\u9F84"] === "number" ? raw["\u7ED3\u675F\u5E74\u9F84"] : void 0,
125
+ startYear: typeof raw["\u8D77\u59CB\u5E74\u4EFD"] === "number" ? raw["\u8D77\u59CB\u5E74\u4EFD"] : void 0,
126
+ endYear: typeof raw["\u7ED3\u675F\u5E74\u4EFD"] === "number" ? raw["\u7ED3\u675F\u5E74\u4EFD"] : void 0,
127
+ naYin: raw["\u7EB3\u97F3"] != null ? String(raw["\u7EB3\u97F3"]) : void 0,
128
+ isCurrent: raw["\u5F53\u524D"] === true
129
+ }));
130
+ }
131
+ function fromBaziObject(data) {
132
+ const input = data["\u8F93\u5165"] ?? {};
133
+ const solarTimeRaw = data["\u771F\u592A\u9633\u65F6"] ?? {};
134
+ const bazi = data["\u516B\u5B57"] ?? {};
135
+ const detail = bazi["\u67F1\u4F4D\u8BE6\u7EC6"] ?? {};
136
+ const pillars = [];
137
+ for (const [zh, position] of Object.entries(POSITION_ZH)) {
138
+ const raw = detail[zh];
139
+ if (raw && typeof raw === "object") pillars.push(adaptPillar(position, raw));
140
+ }
141
+ const wuxing = bazi["\u4E94\u884C\u5206\u503C"] ?? {};
142
+ return {
143
+ meta: {
144
+ engine: "baziObject",
145
+ gender: input["\u6027\u522B"] != null ? String(input["\u6027\u522B"]) : void 0,
146
+ zodiac: bazi["\u751F\u8096"] != null ? String(bazi["\u751F\u8096"]) : void 0,
147
+ lunar: bazi["\u519C\u5386"] != null ? String(bazi["\u519C\u5386"]) : void 0,
148
+ solar: bazi["\u516C\u5386"] != null ? String(bazi["\u516C\u5386"]) : void 0
149
+ },
150
+ solarTime: {
151
+ clock: solarTimeRaw["\u949F\u8868\u65F6\u95F4"] != null ? String(solarTimeRaw["\u949F\u8868\u65F6\u95F4"]) : void 0,
152
+ trueSolar: solarTimeRaw["\u771F\u592A\u9633\u65F6"] != null ? String(solarTimeRaw["\u771F\u592A\u9633\u65F6"]) : void 0,
153
+ correctionMinutes: typeof solarTimeRaw["\u4FEE\u6B63\u5206\u949F"] === "number" ? solarTimeRaw["\u4FEE\u6B63\u5206\u949F"] : void 0,
154
+ shiChen: solarTimeRaw["\u65F6\u8FB0"] != null ? String(solarTimeRaw["\u65F6\u8FB0"]) : void 0
155
+ },
156
+ dayMaster: {
157
+ char: bazi["\u65E5\u4E3B"] != null ? String(bazi["\u65E5\u4E3B"]) : void 0,
158
+ element: wuxing["\u65E5\u4E3B\u4E94\u884C"] != null ? String(wuxing["\u65E5\u4E3B\u4E94\u884C"]) : void 0
159
+ },
160
+ pillars,
161
+ fiveElements: adaptFiveElements(wuxing),
162
+ dayMasterElement: wuxing["\u65E5\u4E3B\u4E94\u884C"] != null ? String(wuxing["\u65E5\u4E3B\u4E94\u884C"]) : void 0,
163
+ daYun: adaptDaYun(bazi["\u5927\u8FD0"]),
164
+ daYunOnset: bazi["\u8D77\u8FD0"] != null ? String(bazi["\u8D77\u8FD0"]) : void 0,
165
+ interactions: adaptInteractions(bazi["\u5211\u51B2\u5408\u4F1A"] ?? {}),
166
+ extras: {
167
+ mingGong: bazi["\u547D\u5BAB"] != null ? String(bazi["\u547D\u5BAB"]) : void 0,
168
+ shenGong: bazi["\u8EAB\u5BAB"] != null ? String(bazi["\u8EAB\u5BAB"]) : void 0,
169
+ taiYuan: bazi["\u80CE\u5143"] != null ? String(bazi["\u80CE\u5143"]) : void 0,
170
+ taiXi: bazi["\u80CE\u606F"] != null ? String(bazi["\u80CE\u606F"]) : void 0
171
+ }
172
+ };
173
+ }
174
+
175
+ // src/adapters/pillarMap.ts
176
+ var import_bazi_terms2 = require("bazi-terms");
177
+ var PILLAR_ORDER = [
178
+ { field: "year", position: "year" },
179
+ { field: "month", position: "month" },
180
+ { field: "day", position: "day" },
181
+ { field: "hour", position: "hour" }
182
+ ];
183
+ function str(v) {
184
+ return v == null ? void 0 : String(v);
185
+ }
186
+ function num(v) {
187
+ return typeof v === "number" ? v : void 0;
188
+ }
189
+ function adaptPillar2(position, raw) {
190
+ const hiddenRaw = Array.isArray(raw["hiddenStems"]) ? raw["hiddenStems"] : [];
191
+ const hiddenStems = hiddenRaw.map((h, i) => ({
192
+ char: String(h["stem"] ?? ""),
193
+ tenGod: str(h["tenGod"]),
194
+ isMain: h["isMain"] === true || h["isMain"] === void 0 && i === 0
195
+ }));
196
+ return {
197
+ position,
198
+ ganZhi: String(raw["ganZhi"] ?? ""),
199
+ stem: String(raw["stem"] ?? ""),
200
+ branch: String(raw["branch"] ?? ""),
201
+ mainTenGod: str(raw["stemTenGod"]),
202
+ hiddenStems,
203
+ naYin: str(raw["naYin"]),
204
+ growthStage: str(raw["growthStage"]),
205
+ voidBranches: Array.isArray(raw["voidBranches"]) ? raw["voidBranches"] : void 0,
206
+ xun: str(raw["xun"])
207
+ };
208
+ }
209
+ function adaptInteractions2(list) {
210
+ if (!Array.isArray(list)) return [];
211
+ return list.map((raw) => ({
212
+ typeKey: (0, import_bazi_terms2.interactionFromEnum)(String(raw["type"] ?? ""))?.key,
213
+ branches: Array.isArray(raw["branches"]) ? raw["branches"] : void 0,
214
+ pillars: Array.isArray(raw["pillars"]) ? raw["pillars"] : void 0,
215
+ description: str(raw["description"])
216
+ }));
217
+ }
218
+ function adaptDaYun2(daYun) {
219
+ const cycles = Array.isArray(daYun?.["cycles"]) ? daYun["cycles"] : [];
220
+ return cycles.map((c) => ({
221
+ ganZhi: String(c["ganZhi"] ?? ""),
222
+ stem: str(c["stem"]),
223
+ branch: str(c["branch"]),
224
+ stemTenGod: str(c["stemTenGod"]),
225
+ branchTenGod: str(c["branchTenGod"]),
226
+ startAge: num(c["startAge"]),
227
+ endAge: num(c["endAge"]),
228
+ startYear: num(c["startYear"]),
229
+ endYear: num(c["endYear"])
230
+ }));
231
+ }
232
+ function formatCalendarPart(part) {
233
+ if (!part || typeof part !== "object") return void 0;
234
+ const y = num(part["year"]);
235
+ const m = num(part["month"]);
236
+ const d = num(part["day"]);
237
+ if (y == null || m == null || d == null) return void 0;
238
+ const hh = num(part["hour"]);
239
+ const mm = num(part["minute"]);
240
+ const time = hh != null && mm != null ? ` ${String(hh).padStart(2, "0")}:${String(mm).padStart(2, "0")}` : "";
241
+ return `${y}-${String(m).padStart(2, "0")}-${String(d).padStart(2, "0")}${time}`;
242
+ }
243
+ function fromPillarMap(data) {
244
+ const rawPillars = data["pillars"] ?? {};
245
+ const pillars = [];
246
+ for (const { field, position } of PILLAR_ORDER) {
247
+ const raw = rawPillars[field];
248
+ if (raw && typeof raw === "object") pillars.push(adaptPillar2(position, raw));
249
+ }
250
+ const dm = data["dayMaster"] ?? {};
251
+ const daYun = data["daYun"] ?? {};
252
+ const solar = data["solarTimeInfo"] ?? {};
253
+ const calendar = data["calendar"] ?? {};
254
+ const lonCorr = num(solar["longitudeCorrectionMinutes"]);
255
+ const eotCorr = num(solar["equationOfTimeMinutes"]);
256
+ const correctionMinutes = lonCorr != null || eotCorr != null ? Math.round(((lonCorr ?? 0) + (eotCorr ?? 0)) * 100) / 100 : void 0;
257
+ return {
258
+ meta: {
259
+ engine: "pillarMap",
260
+ zodiac: str(calendar["zodiac"]),
261
+ lunar: formatCalendarPart(calendar["lunar"]),
262
+ solar: formatCalendarPart(calendar["civilSolar"] ?? calendar["calculationSolar"])
263
+ },
264
+ solarTime: {
265
+ trueSolar: str(solar["trueSolarDateTime"] ?? solar["trueSolarTime"]),
266
+ correctionMinutes
267
+ },
268
+ dayMaster: {
269
+ char: str(dm["char"]),
270
+ element: str(dm["element"]),
271
+ polarity: str(dm["polarity"])
272
+ },
273
+ pillars,
274
+ dayMasterElement: str(dm["element"]),
275
+ daYun: adaptDaYun2(daYun),
276
+ daYunDirection: daYun["isForward"] === true ? "forward" : daYun["isForward"] === false ? "backward" : void 0,
277
+ interactions: adaptInteractions2(data["interactions"])
278
+ };
279
+ }
280
+
281
+ // src/normalize.ts
282
+ function detectEngine(data) {
283
+ if (!data || typeof data !== "object") return "unknown";
284
+ const d = data;
285
+ if (d["\u516B\u5B57"] && typeof d["\u516B\u5B57"] === "object") return "baziObject";
286
+ if (d["meta"] && typeof d["meta"] === "object" && "engine" in d["meta"]) return "normalized";
287
+ if (Array.isArray(d["pillars"]) && d["pillars"][0] && typeof d["pillars"][0] === "object" && "position" in d["pillars"][0]) {
288
+ return "normalized";
289
+ }
290
+ if (d["pillars"] && typeof d["pillars"] === "object" && !Array.isArray(d["pillars"])) {
291
+ const year = d["pillars"]["year"];
292
+ if (year && typeof year === "object" && ("ganZhi" in year || "stem" in year)) return "pillarMap";
293
+ }
294
+ return "unknown";
295
+ }
296
+ function normalize(data) {
297
+ const engine = detectEngine(data);
298
+ switch (engine) {
299
+ case "baziObject":
300
+ return fromBaziObject(data);
301
+ case "pillarMap":
302
+ return fromPillarMap(data);
303
+ case "normalized":
304
+ return data;
305
+ default:
306
+ throw new Error(
307
+ "[bazi-chart] Unrecognized chart data. Expected a bazi-object chart, a pillar-map chart, or a pre-normalized NormalizedChart."
308
+ );
309
+ }
310
+ }
311
+
312
+ // src/theme.ts
313
+ var PALETTES = {
314
+ light: {
315
+ bg: "#ffffff",
316
+ card: "#fafafa",
317
+ cardAlt: "#f1f1f3",
318
+ border: "#e4e4e7",
319
+ text: "#18181b",
320
+ muted: "#71717a",
321
+ accent: "#a16207"
322
+ },
323
+ dark: {
324
+ bg: "#18181b",
325
+ card: "#27272a",
326
+ cardAlt: "#333338",
327
+ border: "#3f3f46",
328
+ text: "#fafafa",
329
+ muted: "#a1a1aa",
330
+ accent: "#fbbf24"
331
+ }
332
+ };
333
+ var ELEMENT_COLORS = {
334
+ wood: { light: "#15803d", dark: "#4ade80" },
335
+ fire: { light: "#dc2626", dark: "#f87171" },
336
+ earth: { light: "#a0522d", dark: "#d2a679" },
337
+ metal: { light: "#b8860b", dark: "#e6c34a" },
338
+ water: { light: "#2563eb", dark: "#60a5fa" }
339
+ };
340
+ var NEUTRAL_COLOR = {
341
+ light: "#52525b",
342
+ dark: "#d4d4d8"
343
+ };
344
+ function elementColor(key, theme) {
345
+ if (!key) return NEUTRAL_COLOR[theme];
346
+ return ELEMENT_COLORS[key]?.[theme] ?? NEUTRAL_COLOR[theme];
347
+ }
348
+
349
+ // src/i18n.ts
350
+ var import_bazi_terms3 = require("bazi-terms");
351
+ function combine(zh, en, lang) {
352
+ if (lang === "zh") return zh;
353
+ if (lang === "en") return en;
354
+ if (!en || en === zh) return zh;
355
+ return `${zh} \xB7 ${en}`;
356
+ }
357
+ function labelText(key, lang) {
358
+ return combine((0, import_bazi_terms3.t)(key, "zh"), (0, import_bazi_terms3.t)(key, "en"), lang);
359
+ }
360
+ function valueText(raw, lang) {
361
+ if (!raw) return "";
362
+ const zh = (0, import_bazi_terms3.translate)(raw, "zh") || raw;
363
+ const en = (0, import_bazi_terms3.translate)(raw, "en");
364
+ return combine(zh, en, lang);
365
+ }
366
+ function elementKeyOf(raw) {
367
+ if (!raw) return void 0;
368
+ return (0, import_bazi_terms3.elementOf)(raw)?.key;
369
+ }
370
+ function stemElement(char) {
371
+ if (!char) return void 0;
372
+ return (0, import_bazi_terms3.stemByChar)(char)?.element;
373
+ }
374
+ function branchElement(char) {
375
+ if (!char) return void 0;
376
+ return (0, import_bazi_terms3.branchByChar)(char)?.element;
377
+ }
378
+ function branchZodiac(char, lang) {
379
+ if (!char) return "";
380
+ const b = (0, import_bazi_terms3.branchByChar)(char);
381
+ if (!b) return "";
382
+ return combine(b.zodiacZh, b.zodiacEn, lang);
383
+ }
384
+
385
+ // src/components/BaziChart.tsx
386
+ var import_jsx_runtime = require("react/jsx-runtime");
387
+ var POS_LABEL = {
388
+ year: "yearPillar",
389
+ month: "monthPillar",
390
+ day: "dayPillar",
391
+ hour: "hourPillar"
392
+ };
393
+ function BaziChart(props) {
394
+ const {
395
+ lang = "both",
396
+ theme = "light",
397
+ showDaYun = true,
398
+ showInteractions = true,
399
+ showFiveElements = true,
400
+ showShenSha = true,
401
+ style
402
+ } = props;
403
+ const chart = props.chart ?? (props.data !== void 0 ? normalize(props.data) : void 0);
404
+ const p = PALETTES[theme];
405
+ const box = {
406
+ background: p.bg,
407
+ color: p.text,
408
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif',
409
+ fontSize: 14,
410
+ lineHeight: 1.5,
411
+ padding: 20,
412
+ borderRadius: 12,
413
+ border: `1px solid ${p.border}`,
414
+ boxSizing: "border-box",
415
+ maxWidth: 860
416
+ };
417
+ const card = {
418
+ background: p.card,
419
+ border: `1px solid ${p.border}`,
420
+ borderRadius: 10,
421
+ padding: 12,
422
+ boxSizing: "border-box"
423
+ };
424
+ const sectionTitle = {
425
+ fontSize: 13,
426
+ fontWeight: 600,
427
+ letterSpacing: 0.4,
428
+ color: p.accent,
429
+ textTransform: "uppercase",
430
+ margin: "20px 0 10px"
431
+ };
432
+ const muted = { color: p.muted, fontSize: 12 };
433
+ const bigChar = (color) => ({
434
+ color,
435
+ fontSize: 34,
436
+ fontWeight: 700,
437
+ lineHeight: 1.1
438
+ });
439
+ const chip = {
440
+ display: "inline-block",
441
+ background: p.cardAlt,
442
+ border: `1px solid ${p.border}`,
443
+ borderRadius: 999,
444
+ padding: "2px 9px",
445
+ fontSize: 12,
446
+ margin: "2px 4px 2px 0",
447
+ whiteSpace: "nowrap"
448
+ };
449
+ if (!chart) {
450
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...box, ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: muted, children: "No chart data. Pass `data` (engine output) or `chart` (NormalizedChart)." }) });
451
+ }
452
+ const dmElementKey = elementKeyOf(chart.dayMaster.element ?? chart.dayMasterElement);
453
+ const header = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", alignItems: "baseline", gap: 10 }, children: [
454
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { margin: 0, fontSize: 18, fontWeight: 700 }, children: labelText("bazi", lang) }),
455
+ chart.dayMaster.char ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: chip, children: [
456
+ labelText("dayMaster", lang),
457
+ ":",
458
+ " ",
459
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { color: elementColor(dmElementKey, theme) }, children: chart.dayMaster.char }),
460
+ dmElementKey ? ` (${valueText(dmElementKey, lang)})` : ""
461
+ ] }) : null,
462
+ chart.meta.zodiac ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: chip, children: [
463
+ labelText("shengXiao", lang),
464
+ ": ",
465
+ valueText(chart.meta.zodiac, lang)
466
+ ] }) : null,
467
+ chart.meta.gender ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: chip, children: [
468
+ labelText("gender", lang),
469
+ ": ",
470
+ valueText(chart.meta.gender, lang)
471
+ ] }) : null
472
+ ] });
473
+ const metaItems = [];
474
+ if (chart.meta.solar) metaItems.push(`${labelText("gongLi", lang)}: ${chart.meta.solar}`);
475
+ if (chart.meta.lunar) metaItems.push(`${labelText("nongLi", lang)}: ${chart.meta.lunar}`);
476
+ if (chart.solarTime?.trueSolar)
477
+ metaItems.push(`${labelText("zhenTaiYangShi", lang)}: ${chart.solarTime.trueSolar}`);
478
+ if (chart.solarTime?.shiChen)
479
+ metaItems.push(`${labelText("shiChen", lang)}: ${valueText(chart.solarTime.shiChen.replace("\u65F6", ""), lang)}`);
480
+ const metaBar = metaItems.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, marginTop: 8 }, children: metaItems.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { marginRight: 14, display: "inline-block" }, children: m }, i)) }) : null;
481
+ const renderPillar = (pillar) => {
482
+ const sColor = elementColor(stemElement(pillar.stem), theme);
483
+ const bColor = elementColor(branchElement(pillar.branch), theme);
484
+ const isDay = pillar.position === "day";
485
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
486
+ "div",
487
+ {
488
+ style: {
489
+ ...card,
490
+ flex: "1 1 150px",
491
+ minWidth: 150,
492
+ borderColor: isDay ? p.accent : p.border,
493
+ borderWidth: isDay ? 2 : 1
494
+ },
495
+ children: [
496
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, textAlign: "center", fontWeight: 600, marginBottom: 6 }, children: labelText(POS_LABEL[pillar.position], lang) }),
497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { textAlign: "center", fontSize: 12, minHeight: 18, color: p.muted }, children: pillar.mainTenGod ? valueText(pillar.mainTenGod, lang) : "" }),
498
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", margin: "6px 0" }, children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: bigChar(sColor), children: pillar.stem }),
500
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 11 }, children: stemElement(pillar.stem) ? valueText(stemElement(pillar.stem), lang) : "" })
501
+ ] }),
502
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", margin: "6px 0" }, children: [
503
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: bigChar(bColor), children: pillar.branch }),
504
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 11 }, children: branchZodiac(pillar.branch, lang) })
505
+ ] }),
506
+ pillar.hiddenStems.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: `1px solid ${p.border}`, marginTop: 8, paddingTop: 6 }, children: [
507
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 11, marginBottom: 4 }, children: labelText("hiddenStems", lang) }),
508
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { textAlign: "center" }, children: pillar.hiddenStems.map((h, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-block", margin: "0 4px", fontSize: 12 }, children: [
509
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { style: { color: elementColor(stemElement(h.char), theme) }, children: h.char }),
510
+ h.tenGod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...muted, fontSize: 10, display: "block" }, children: valueText(h.tenGod, lang) }) : null
511
+ ] }, i)) })
512
+ ] }) : null,
513
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: `1px solid ${p.border}`, marginTop: 8, paddingTop: 6, fontSize: 11, color: p.muted }, children: [
514
+ pillar.naYin ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
515
+ labelText("naYin", lang),
516
+ ": ",
517
+ valueText(pillar.naYin, lang)
518
+ ] }) : null,
519
+ pillar.growthStage ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
520
+ labelText("xingYun", lang),
521
+ ": ",
522
+ valueText(pillar.growthStage, lang)
523
+ ] }) : null,
524
+ pillar.voidBranches?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
525
+ labelText("kongWang", lang),
526
+ ": ",
527
+ pillar.voidBranches.join("")
528
+ ] }) : null
529
+ ] }),
530
+ showShenSha && pillar.shenSha?.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 8 }, children: pillar.shenSha.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...chip, fontSize: 11 }, children: valueText(s, lang) }, i)) }) : null
531
+ ]
532
+ },
533
+ pillar.position
534
+ );
535
+ };
536
+ const pillars = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, marginTop: 14 }, children: chart.pillars.map(renderPillar) });
537
+ const renderFiveElements = (scores) => {
538
+ const max = Math.max(...scores.map((s) => s.score ?? 0), 1);
539
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
540
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: sectionTitle, children: labelText("wuXingFenZhi", lang) }),
541
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: scores.map((s, i) => {
542
+ const key = elementKeyOf(s.element);
543
+ const width = Math.round((s.score ?? 0) / max * 100);
544
+ const isDm = s.element === chart.dayMasterElement;
545
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
546
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: 88, fontSize: 12, color: elementColor(key, theme), fontWeight: isDm ? 700 : 400 }, children: valueText(s.element, lang) }),
547
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, background: p.cardAlt, borderRadius: 6, height: 14, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: `${width}%`, height: "100%", background: elementColor(key, theme) } }) }),
548
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { width: 74, textAlign: "right", ...muted }, children: [
549
+ s.score != null ? s.score : "",
550
+ s.percent ? ` (${s.percent})` : ""
551
+ ] })
552
+ ] }, i);
553
+ }) })
554
+ ] });
555
+ };
556
+ const renderInteractions = (items) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
557
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: sectionTitle, children: labelText("interactions", lang) }),
558
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: items.map((it, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: chip, title: it.description ?? void 0, children: [
559
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: it.typeKey ? labelText(it.typeKey, lang) : it.description ?? "" }),
560
+ it.typeKey && it.branches?.length ? ` ${it.branches.join("")}` : ""
561
+ ] }, i)) })
562
+ ] });
563
+ const renderDaYun = (cycles) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
564
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: sectionTitle, children: [
565
+ labelText("daYun", lang),
566
+ chart.daYunDirection ? ` \xB7 ${labelText(chart.daYunDirection, lang)}` : "",
567
+ chart.daYunOnset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { ...muted, textTransform: "none", marginLeft: 8 }, children: chart.daYunOnset }) : null
568
+ ] }),
569
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: 8, overflowX: "auto", paddingBottom: 6 }, children: cycles.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
570
+ "div",
571
+ {
572
+ style: {
573
+ ...card,
574
+ minWidth: 92,
575
+ flex: "0 0 auto",
576
+ textAlign: "center",
577
+ borderColor: c.isCurrent ? p.accent : p.border,
578
+ borderWidth: c.isCurrent ? 2 : 1
579
+ },
580
+ children: [
581
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 20, fontWeight: 700 }, children: [
582
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: elementColor(stemElement(c.ganZhi[0]), theme) }, children: c.ganZhi[0] }),
583
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: elementColor(branchElement(c.ganZhi[1]), theme) }, children: c.ganZhi[1] })
584
+ ] }),
585
+ c.stemTenGod ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 11 }, children: valueText(c.stemTenGod, lang) }) : null,
586
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 11, marginTop: 4 }, children: c.startAge != null && c.endAge != null ? `${c.startAge}\u2013${c.endAge}` : "" }),
587
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...muted, fontSize: 10 }, children: c.startYear != null && c.endYear != null ? `${c.startYear}\u2013${c.endYear}` : "" }),
588
+ c.isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 10, color: p.accent, marginTop: 2 }, children: labelText("current", lang) }) : null
589
+ ]
590
+ },
591
+ i
592
+ )) })
593
+ ] });
594
+ const renderExtras = (chart2) => {
595
+ const ex = chart2.extras;
596
+ if (!ex) return null;
597
+ const rows = [
598
+ ["mingGong", ex.mingGong],
599
+ ["shenGong", ex.shenGong],
600
+ ["taiYuan", ex.taiYuan],
601
+ ["taiXi", ex.taiXi]
602
+ ];
603
+ const filled = rows.filter(([, v]) => v);
604
+ if (!filled.length) return null;
605
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: sectionTitle, children: combine("\u5BAB\u4F4D", "Palaces", lang) }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: filled.map(([k, v], i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: chip, children: [
608
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: muted, children: [
609
+ labelText(k, lang),
610
+ ":"
611
+ ] }),
612
+ " ",
613
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: v })
614
+ ] }, i)) })
615
+ ] });
616
+ };
617
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...box, ...style }, children: [
618
+ header,
619
+ metaBar,
620
+ pillars,
621
+ showFiveElements && chart.fiveElements?.length ? renderFiveElements(chart.fiveElements) : null,
622
+ showInteractions && chart.interactions.length ? renderInteractions(chart.interactions) : null,
623
+ showDaYun && chart.daYun.length ? renderDaYun(chart.daYun) : null,
624
+ renderExtras(chart)
625
+ ] });
626
+ }
627
+ // Annotate the CommonJS export names for ESM import in node:
628
+ 0 && (module.exports = {
629
+ BaziChart,
630
+ ELEMENT_COLORS,
631
+ NEUTRAL_COLOR,
632
+ PALETTES,
633
+ branchElement,
634
+ branchZodiac,
635
+ combine,
636
+ detectEngine,
637
+ elementColor,
638
+ elementKeyOf,
639
+ fromBaziObject,
640
+ fromPillarMap,
641
+ labelText,
642
+ normalize,
643
+ stemElement,
644
+ valueText
645
+ });
646
+ //# sourceMappingURL=index.cjs.map