react-native-lich-am 1.0.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +248 -0
  3. package/core/index.d.ts +1 -0
  4. package/core/index.js +1 -0
  5. package/core/package.json +5 -0
  6. package/dataset/2024.d.ts +1 -0
  7. package/dataset/2024.js +1 -0
  8. package/dataset/2025.d.ts +1 -0
  9. package/dataset/2025.js +1 -0
  10. package/dataset/2026.d.ts +1 -0
  11. package/dataset/2026.js +1 -0
  12. package/dataset/2027.d.ts +1 -0
  13. package/dataset/2027.js +1 -0
  14. package/dataset/2028.d.ts +1 -0
  15. package/dataset/2028.js +1 -0
  16. package/dataset/index.d.ts +1 -0
  17. package/dataset/index.js +1 -0
  18. package/dataset/package.json +5 -0
  19. package/lib/core/astro.d.ts +43 -0
  20. package/lib/core/astro.js +203 -0
  21. package/lib/core/canchi.d.ts +47 -0
  22. package/lib/core/canchi.js +78 -0
  23. package/lib/core/constants.d.ts +54 -0
  24. package/lib/core/constants.js +141 -0
  25. package/lib/core/day.d.ts +30 -0
  26. package/lib/core/day.js +103 -0
  27. package/lib/core/format.d.ts +26 -0
  28. package/lib/core/format.js +60 -0
  29. package/lib/core/huong.d.ts +26 -0
  30. package/lib/core/huong.js +44 -0
  31. package/lib/core/index.d.ts +16 -0
  32. package/lib/core/index.js +32 -0
  33. package/lib/core/lunar.d.ts +39 -0
  34. package/lib/core/lunar.js +130 -0
  35. package/lib/core/tietkhi.d.ts +40 -0
  36. package/lib/core/tietkhi.js +115 -0
  37. package/lib/core/truc.d.ts +47 -0
  38. package/lib/core/truc.js +70 -0
  39. package/lib/core/types.d.ts +66 -0
  40. package/lib/core/types.js +3 -0
  41. package/lib/dataset/2024.d.ts +30 -0
  42. package/lib/dataset/2024.js +69 -0
  43. package/lib/dataset/2025.d.ts +30 -0
  44. package/lib/dataset/2025.js +69 -0
  45. package/lib/dataset/2026.d.ts +30 -0
  46. package/lib/dataset/2026.js +69 -0
  47. package/lib/dataset/2027.d.ts +30 -0
  48. package/lib/dataset/2027.js +69 -0
  49. package/lib/dataset/2028.d.ts +30 -0
  50. package/lib/dataset/2028.js +69 -0
  51. package/lib/dataset/data/days-2024.json +1 -0
  52. package/lib/dataset/data/days-2025.json +1 -0
  53. package/lib/dataset/data/days-2026.json +1 -0
  54. package/lib/dataset/data/days-2027.json +1 -0
  55. package/lib/dataset/data/days-2028.json +1 -0
  56. package/lib/dataset/data/dict.json +1 -0
  57. package/lib/dataset/data/gio-table.json +1 -0
  58. package/lib/dataset/decode.d.ts +225 -0
  59. package/lib/dataset/decode.js +285 -0
  60. package/lib/dataset/index.d.ts +37 -0
  61. package/lib/dataset/index.js +87 -0
  62. package/lib/index.d.ts +21 -0
  63. package/lib/index.js +37 -0
  64. package/lib/ui/LunarCalendar.d.ts +58 -0
  65. package/lib/ui/LunarCalendar.js +311 -0
  66. package/lib/ui/LunarDayDetail.d.ts +32 -0
  67. package/lib/ui/LunarDayDetail.js +221 -0
  68. package/lib/ui/index.d.ts +9 -0
  69. package/lib/ui/index.js +18 -0
  70. package/lib/ui/theme.d.ts +46 -0
  71. package/lib/ui/theme.js +60 -0
  72. package/package.json +431 -0
  73. package/ui/index.d.ts +1 -0
  74. package/ui/index.js +1 -0
  75. package/ui/package.json +5 -0
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * react-native-lich-am / dataset
4
+ *
5
+ * Bộ dữ liệu chi tiết theo ngày, trích xuất từ app Lịch Việt
6
+ * (com.somestudio.lichvietnam) — phủ 01/01/2024 → 01/01/2028 (1.462 ngày).
7
+ *
8
+ * Gồm những thứ KHÔNG thể suy ra bằng thuật toán:
9
+ * sao tốt / sao xấu, việc nên làm / không nên làm, điểm từng giờ,
10
+ * hướng tốt theo sơn, tuổi xung, 4 giờ đại cát, giờ quý đăng thiên môn.
11
+ *
12
+ * Muốn nhẹ bundle hơn thì import từng năm:
13
+ * import { getDayData } from 'react-native-lich-am/dataset/2024';
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
27
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.RAW_DICT = exports.getQualityStats = exports.topDays = exports.findGoodDays = exports.listDays = exports.listDayKeys = exports.getDayDataBySolar = exports.getDayData = exports.hasDayData = exports.AVAILABLE_YEARS = void 0;
31
+ const decode_1 = require("./decode");
32
+ Object.defineProperty(exports, "RAW_DICT", { enumerable: true, get: function () { return decode_1.dict; } });
33
+ __exportStar(require("./decode"), exports);
34
+ const YEAR_KEYS = ['2024', '2025', '2026', '2027', '2028'];
35
+ // require tĩnh từng file — Metro chỉ bundle được đường dẫn literal.
36
+ // Đường dẫn trỏ thẳng về `src/dataset/data/` (thư mục dữ liệu được publish kèm)
37
+ // để bản JS trong `lib/` chạy được ngay mà không cần bước copy.
38
+ const YEARS = [
39
+ require('./data/days-2024.json'),
40
+ require('./data/days-2025.json'),
41
+ require('./data/days-2026.json'),
42
+ require('./data/days-2027.json'),
43
+ require('./data/days-2028.json'),
44
+ ];
45
+ const store = (0, decode_1.createStore)(YEARS);
46
+ /** Các năm có dữ liệu */
47
+ exports.AVAILABLE_YEARS = YEAR_KEYS.map(Number);
48
+ /** Có dữ liệu chi tiết cho ngày này hay không (chuỗi "YYYY-MM-DD") */
49
+ function hasDayData(date) {
50
+ return store.has(date);
51
+ }
52
+ exports.hasDayData = hasDayData;
53
+ /** Lấy thông tin chi tiết một ngày theo chuỗi "YYYY-MM-DD" */
54
+ function getDayData(date) {
55
+ return store.lookup(date);
56
+ }
57
+ exports.getDayData = getDayData;
58
+ /** Lấy theo ngày/tháng/năm dương */
59
+ function getDayDataBySolar(day, month, year) {
60
+ return store.lookup((0, decode_1.toIso)(year, month, day));
61
+ }
62
+ exports.getDayDataBySolar = getDayDataBySolar;
63
+ /** Toàn bộ ngày có dữ liệu, dạng "YYYY-MM-DD", đã sắp xếp */
64
+ function listDayKeys() {
65
+ return store.keys;
66
+ }
67
+ exports.listDayKeys = listDayKeys;
68
+ /** Toàn bộ ngày đã giải mã */
69
+ function listDays() {
70
+ return store.all();
71
+ }
72
+ exports.listDays = listDays;
73
+ /** Tìm ngày phù hợp cho một việc (xem `FindGoodDaysOptions`) */
74
+ function findGoodDays(options) {
75
+ return (0, decode_1.findGoodDaysIn)(store.keys, store.lookup, options);
76
+ }
77
+ exports.findGoodDays = findGoodDays;
78
+ /** Ngày đẹp nhất trong một khoảng */
79
+ function topDays(from, to, limit = 10) {
80
+ return (0, decode_1.topDaysIn)(store.keys, store.lookup, from, to, limit);
81
+ }
82
+ exports.topDays = topDays;
83
+ /** Thống kê chất lượng ngày trong một khoảng */
84
+ function getQualityStats(from, to) {
85
+ return (0, decode_1.qualityStatsIn)(store.keys, store.lookup, from, to);
86
+ }
87
+ exports.getQualityStats = getQualityStats;
package/lib/index.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * react-native-lich-am
3
+ *
4
+ * Thư viện lịch âm (âm lịch Việt Nam) cho React Native và JavaScript.
5
+ *
6
+ * - `react-native-lich-am` → core thuật toán (entry này)
7
+ * - `react-native-lich-am/dataset` → dữ liệu chi tiết theo ngày 2024–2028
8
+ * - `react-native-lich-am/ui` → component <LunarCalendar/> & <LunarDayDetail/>
9
+ *
10
+ * Core không phụ thuộc thư viện ngoài, không cần native module.
11
+ *
12
+ * @example
13
+ * import { getLunarDayInfo, getTodayLunar } from 'react-native-lich-am';
14
+ *
15
+ * const info = getLunarDayInfo(new Date());
16
+ * console.log(info.lunar.text); // "18/8/2026"
17
+ * console.log(info.canChi.day.name); // "Bính Ngọ"
18
+ * console.log(info.truc.name); // "Bình"
19
+ * console.log(info.gioHoangDao.map(g => g.chi)); // ["Tý","Sửu","Mão",...]
20
+ */
21
+ export * from './core';
package/lib/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * react-native-lich-am
4
+ *
5
+ * Thư viện lịch âm (âm lịch Việt Nam) cho React Native và JavaScript.
6
+ *
7
+ * - `react-native-lich-am` → core thuật toán (entry này)
8
+ * - `react-native-lich-am/dataset` → dữ liệu chi tiết theo ngày 2024–2028
9
+ * - `react-native-lich-am/ui` → component <LunarCalendar/> & <LunarDayDetail/>
10
+ *
11
+ * Core không phụ thuộc thư viện ngoài, không cần native module.
12
+ *
13
+ * @example
14
+ * import { getLunarDayInfo, getTodayLunar } from 'react-native-lich-am';
15
+ *
16
+ * const info = getLunarDayInfo(new Date());
17
+ * console.log(info.lunar.text); // "18/8/2026"
18
+ * console.log(info.canChi.day.name); // "Bính Ngọ"
19
+ * console.log(info.truc.name); // "Bình"
20
+ * console.log(info.gioHoangDao.map(g => g.chi)); // ["Tý","Sửu","Mão",...]
21
+ */
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
34
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
35
+ };
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ __exportStar(require("./core"), exports);
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import { type StyleProp, type ViewStyle } from 'react-native';
3
+ import type { LunarDayInfo } from '../core/types';
4
+ import type { LichVietDay } from '../dataset/decode';
5
+ import { type LunarTheme } from './theme';
6
+ export interface LunarCalendarProps {
7
+ /** Ngày đang chọn */
8
+ value?: Date | string | number | {
9
+ day: number;
10
+ month: number;
11
+ year: number;
12
+ };
13
+ /** Ngày hiển thị ban đầu (mặc định: `value` hoặc hôm nay) */
14
+ initialDate?: Date | string | number | {
15
+ day: number;
16
+ month: number;
17
+ year: number;
18
+ };
19
+ /** Gọi khi người dùng bấm một ngày */
20
+ onSelectDay?: (day: LunarDayInfo, data: LichVietDay | null) => void;
21
+ /** Gọi khi đổi tháng */
22
+ onMonthChange?: (month: number, year: number) => void;
23
+ /**
24
+ * Nguồn dữ liệu chi tiết theo ngày — truyền vào để tô màu chất lượng ngày.
25
+ * Ví dụ: `import { getDayData } from 'react-native-lich-am/dataset'`.
26
+ */
27
+ dayDataProvider?: (iso: string) => LichVietDay | null;
28
+ /** Ghi đè bảng màu */
29
+ theme?: Partial<LunarTheme>;
30
+ /** Bộ màu nền: 'light' | 'dark' (mặc định 'light') */
31
+ colorScheme?: 'light' | 'dark';
32
+ /** Bắt đầu tuần: 0 = Chủ nhật, 1 = Thứ hai (mặc định 1) */
33
+ weekStartsOn?: 0 | 1;
34
+ /** Hiện ngày âm trong ô (mặc định true) */
35
+ showLunar?: boolean;
36
+ /** Hiện chú thích màu chất lượng (mặc định true nếu có `dayDataProvider`) */
37
+ showLegend?: boolean;
38
+ /** Hiện nút "Hôm nay" (mặc định true) */
39
+ showTodayButton?: boolean;
40
+ /** Hiện phần tiêu đề tháng âm (mặc định true) */
41
+ showLunarHeader?: boolean;
42
+ locale?: 'vi' | 'en';
43
+ style?: StyleProp<ViewStyle>;
44
+ }
45
+ /**
46
+ * Lịch tháng dương–âm cho React Native.
47
+ *
48
+ * Chỉ dùng component gốc của React Native (View / Text / Pressable), không cần
49
+ * thư viện ngoài, không cần native module.
50
+ *
51
+ * @example
52
+ * import { LunarCalendar } from 'react-native-lich-am/ui';
53
+ * import { getDayData } from 'react-native-lich-am/dataset';
54
+ *
55
+ * <LunarCalendar dayDataProvider={getDayData} onSelectDay={(d) => console.log(d)} />
56
+ */
57
+ export declare function LunarCalendar(props: LunarCalendarProps): React.ReactElement;
58
+ export default LunarCalendar;
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.LunarCalendar = void 0;
27
+ const React = __importStar(require("react"));
28
+ const react_native_1 = require("react-native");
29
+ const astro_1 = require("../core/astro");
30
+ const format_1 = require("../core/format");
31
+ const day_1 = require("../core/day");
32
+ const theme_1 = require("./theme");
33
+ const WEEK_LABELS_VI = ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'];
34
+ const WEEK_LABELS_EN = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
35
+ const MONTH_LABELS_EN = [
36
+ '', 'January', 'February', 'March', 'April', 'May', 'June',
37
+ 'July', 'August', 'September', 'October', 'November', 'December',
38
+ ];
39
+ function daysInSolarMonth(month, year) {
40
+ const nextMonth = month === 12 ? 1 : month + 1;
41
+ const nextYear = month === 12 ? year + 1 : year;
42
+ return (0, astro_1.jdFromDate)(1, nextMonth, nextYear) - (0, astro_1.jdFromDate)(1, month, year);
43
+ }
44
+ function todayJd() {
45
+ const now = new Date();
46
+ return (0, astro_1.jdFromDate)(now.getDate(), now.getMonth() + 1, now.getFullYear());
47
+ }
48
+ /**
49
+ * Lịch tháng dương–âm cho React Native.
50
+ *
51
+ * Chỉ dùng component gốc của React Native (View / Text / Pressable), không cần
52
+ * thư viện ngoài, không cần native module.
53
+ *
54
+ * @example
55
+ * import { LunarCalendar } from 'react-native-lich-am/ui';
56
+ * import { getDayData } from 'react-native-lich-am/dataset';
57
+ *
58
+ * <LunarCalendar dayDataProvider={getDayData} onSelectDay={(d) => console.log(d)} />
59
+ */
60
+ function LunarCalendar(props) {
61
+ const { value, initialDate, onSelectDay, onMonthChange, dayDataProvider, theme: themeOverride, colorScheme = 'light', weekStartsOn = 1, showLunar = true, showLegend, showTodayButton = true, showLunarHeader = true, locale = 'vi', style, } = props;
62
+ const theme = React.useMemo(() => (0, theme_1.createTheme)(colorScheme === 'dark' ? theme_1.darkTheme : theme_1.lightTheme, themeOverride), [colorScheme, themeOverride]);
63
+ const anchor = React.useMemo(() => {
64
+ var _a;
65
+ const src = (_a = value !== null && value !== void 0 ? value : initialDate) !== null && _a !== void 0 ? _a : new Date();
66
+ return (0, day_1.resolveDate)(src);
67
+ }, [value, initialDate]);
68
+ const [view, setView] = React.useState({ month: anchor.month, year: anchor.year });
69
+ const [selectedJd, setSelectedJd] = React.useState(anchor.jd);
70
+ const [today] = React.useState(() => todayJd());
71
+ // đồng bộ khi `value` đổi từ bên ngoài
72
+ const lastValueRef = React.useRef(null);
73
+ React.useEffect(() => {
74
+ if (value === undefined)
75
+ return;
76
+ const r = (0, day_1.resolveDate)(value);
77
+ if (lastValueRef.current !== r.jd) {
78
+ lastValueRef.current = r.jd;
79
+ setSelectedJd(r.jd);
80
+ setView({ month: r.month, year: r.year });
81
+ }
82
+ }, [value]);
83
+ const goMonth = React.useCallback((delta) => {
84
+ setView((prev) => {
85
+ let m = prev.month + delta;
86
+ let y = prev.year;
87
+ while (m < 1) {
88
+ m += 12;
89
+ y -= 1;
90
+ }
91
+ while (m > 12) {
92
+ m -= 12;
93
+ y += 1;
94
+ }
95
+ onMonthChange === null || onMonthChange === void 0 ? void 0 : onMonthChange(m, y);
96
+ return { month: m, year: y };
97
+ });
98
+ }, [onMonthChange]);
99
+ const goToday = React.useCallback(() => {
100
+ const jd = todayJd();
101
+ const [d, m, y] = (0, astro_1.jdToDate)(jd);
102
+ setView({ month: m, year: y });
103
+ setSelectedJd(jd);
104
+ const info = (0, day_1.getLunarDayInfo)(jd);
105
+ onSelectDay === null || onSelectDay === void 0 ? void 0 : onSelectDay(info, dayDataProvider ? dayDataProvider(info.solar.iso) : null);
106
+ onMonthChange === null || onMonthChange === void 0 ? void 0 : onMonthChange(m, y);
107
+ }, [dayDataProvider, onSelectDay, onMonthChange]);
108
+ const handleSelect = React.useCallback((jd) => {
109
+ setSelectedJd(jd);
110
+ const info = (0, day_1.getLunarDayInfo)(jd);
111
+ onSelectDay === null || onSelectDay === void 0 ? void 0 : onSelectDay(info, dayDataProvider ? dayDataProvider(info.solar.iso) : null);
112
+ }, [dayDataProvider, onSelectDay]);
113
+ const grid = React.useMemo(() => {
114
+ const first = (0, astro_1.jdFromDate)(1, view.month, view.year);
115
+ const total = daysInSolarMonth(view.month, view.year);
116
+ const firstWeekday = (0, day_1.resolveDate)(first).weekday; // 0 = CN
117
+ const offset = (firstWeekday - weekStartsOn + 7) % 7;
118
+ const cells = [];
119
+ for (let i = 0; i < offset; i += 1)
120
+ cells.push(null);
121
+ for (let i = 0; i < total; i += 1) {
122
+ const jd = first + i;
123
+ cells.push({ jd, info: (0, day_1.getLunarDayInfo)(jd) });
124
+ }
125
+ while (cells.length % 7 !== 0)
126
+ cells.push(null);
127
+ const rows = [];
128
+ for (let i = 0; i < cells.length; i += 7)
129
+ rows.push(cells.slice(i, i + 7));
130
+ return rows;
131
+ }, [view.month, view.year, weekStartsOn]);
132
+ const lunarHeader = React.useMemo(() => {
133
+ const firstJd = (0, astro_1.jdFromDate)(1, view.month, view.year);
134
+ const info = (0, day_1.getLunarDayInfo)(firstJd);
135
+ const leap = info.lunar.leap ? ' nhuận' : '';
136
+ return locale === 'vi'
137
+ ? `Tháng ${info.lunar.month}${leap} · ${info.canChi.year.name}`
138
+ : `Lunar month ${info.lunar.month}${info.lunar.leap ? ' (leap)' : ''} · ${info.canChi.year.name}`;
139
+ }, [view.month, view.year, locale]);
140
+ const weekLabels = React.useMemo(() => {
141
+ const base = locale === 'vi' ? WEEK_LABELS_VI : WEEK_LABELS_EN;
142
+ return [...base.slice(weekStartsOn), ...base.slice(0, weekStartsOn)];
143
+ }, [locale, weekStartsOn]);
144
+ const title = locale === 'vi'
145
+ ? `Tháng ${view.month}/${view.year}`
146
+ : `${MONTH_LABELS_EN[view.month]} ${view.year}`;
147
+ const legendOn = showLegend !== null && showLegend !== void 0 ? showLegend : !!dayDataProvider;
148
+ return (React.createElement(react_native_1.View, { style: [styles.root, { backgroundColor: theme.card, borderRadius: theme.radius }, style] },
149
+ React.createElement(react_native_1.View, { style: styles.header },
150
+ React.createElement(react_native_1.Pressable, { onPress: () => goMonth(-1), style: [styles.navBtn, { borderColor: theme.border, borderRadius: theme.radius / 2 }], accessibilityLabel: locale === 'vi' ? 'Tháng trước' : 'Previous month' },
151
+ React.createElement(react_native_1.Text, { style: [styles.navTxt, { color: theme.text }] }, "\u2039")),
152
+ React.createElement(react_native_1.View, { style: styles.headerMid },
153
+ React.createElement(react_native_1.Text, { style: [styles.title, { color: theme.text }] }, title),
154
+ showLunarHeader ? (React.createElement(react_native_1.Text, { style: [styles.subtitle, { color: theme.primary }] }, lunarHeader)) : null),
155
+ React.createElement(react_native_1.Pressable, { onPress: () => goMonth(1), style: [styles.navBtn, { borderColor: theme.border, borderRadius: theme.radius / 2 }], accessibilityLabel: locale === 'vi' ? 'Tháng sau' : 'Next month' },
156
+ React.createElement(react_native_1.Text, { style: [styles.navTxt, { color: theme.text }] }, "\u203A"))),
157
+ React.createElement(react_native_1.View, { style: styles.weekRow }, weekLabels.map((w, i) => (React.createElement(react_native_1.View, { key: `${w}-${i}`, style: styles.cellWrap },
158
+ React.createElement(react_native_1.Text, { style: [styles.weekTxt, { color: theme.subtext }] }, w))))),
159
+ React.createElement(react_native_1.View, null, grid.map((row, ri) => (React.createElement(react_native_1.View, { key: `row-${ri}`, style: styles.weekRow }, row.map((cell, ci) => {
160
+ if (!cell) {
161
+ return React.createElement(react_native_1.View, { key: `empty-${ri}-${ci}`, style: styles.cellWrap });
162
+ }
163
+ const { jd, info } = cell;
164
+ const isSelected = jd === selectedJd;
165
+ const isToday = jd === today;
166
+ const weekend = info.solar.weekday === 0 || info.solar.weekday === 6;
167
+ const data = dayDataProvider ? dayDataProvider(info.solar.iso) : null;
168
+ const qualityColor = data ? theme.quality[data.chatLuong] : null;
169
+ const showQualityBg = !!data && data.chatLuong !== 'bt';
170
+ return (React.createElement(react_native_1.Pressable, { key: info.solar.iso, onPress: () => handleSelect(jd), style: styles.cellWrap, accessibilityRole: "button", accessibilityLabel: `${info.solar.day}/${info.solar.month}/${info.solar.year}, ${(0, format_1.getLunarDayName)(info.lunar.day)} tháng ${info.lunar.month}` },
171
+ React.createElement(react_native_1.View, { style: [
172
+ styles.cell,
173
+ { borderRadius: theme.radius / 1.5, borderColor: 'transparent' },
174
+ showQualityBg && {
175
+ backgroundColor: qualityColor,
176
+ opacity: isSelected ? 1 : 0.85,
177
+ },
178
+ isSelected && { backgroundColor: theme.selectedBg },
179
+ isToday && { borderColor: theme.todayBorder, borderWidth: 1.5 },
180
+ ] },
181
+ React.createElement(react_native_1.Text, { style: [
182
+ styles.solarTxt,
183
+ {
184
+ color: showQualityBg && !isSelected ? theme.primaryText : theme.text,
185
+ fontSize: theme.solarFontSize,
186
+ fontWeight: isSelected || isToday ? '700' : '500',
187
+ },
188
+ ] }, info.solar.day),
189
+ showLunar ? (React.createElement(react_native_1.Text, { style: [
190
+ styles.lunarTxt,
191
+ {
192
+ color: showQualityBg && !isSelected
193
+ ? theme.primaryText
194
+ : info.lunar.day === 1
195
+ ? theme.firstDayOfMonth
196
+ : weekend
197
+ ? theme.weekend
198
+ : theme.subtext,
199
+ fontSize: theme.lunarFontSize,
200
+ fontWeight: info.lunar.day === 1 ? '700' : '400',
201
+ },
202
+ ], numberOfLines: 1 }, info.lunar.day === 1 ? `1/${info.lunar.month}` : info.lunar.day)) : null)));
203
+ }))))),
204
+ legendOn && dayDataProvider ? (React.createElement(react_native_1.View, { style: [styles.legend, { borderTopColor: theme.border }] }, [
205
+ ['dep', locale === 'vi' ? 'Đẹp' : 'Great'],
206
+ ['tot', locale === 'vi' ? 'Tốt' : 'Good'],
207
+ ['bt', locale === 'vi' ? 'Bình thường' : 'Normal'],
208
+ ['xau', locale === 'vi' ? 'Xấu' : 'Bad'],
209
+ ['ratxau', locale === 'vi' ? 'Rất xấu' : 'Very bad'],
210
+ ].map(([key, label]) => (React.createElement(react_native_1.View, { key: key, style: styles.legendItem },
211
+ React.createElement(react_native_1.View, { style: [styles.dot, { backgroundColor: theme.quality[key] }] }),
212
+ React.createElement(react_native_1.Text, { style: [styles.legendTxt, { color: theme.subtext }] }, label)))))) : null,
213
+ showTodayButton ? (React.createElement(react_native_1.Pressable, { onPress: goToday, style: [styles.todayBtn, { borderColor: theme.primary, borderRadius: theme.radius }] },
214
+ React.createElement(react_native_1.Text, { style: [styles.todayTxt, { color: theme.primary }] }, locale === 'vi' ? 'Hôm nay' : 'Today'))) : null));
215
+ }
216
+ exports.LunarCalendar = LunarCalendar;
217
+ const styles = react_native_1.StyleSheet.create({
218
+ root: {
219
+ paddingHorizontal: 8,
220
+ paddingVertical: 10,
221
+ },
222
+ header: {
223
+ flexDirection: 'row',
224
+ alignItems: 'center',
225
+ justifyContent: 'space-between',
226
+ paddingHorizontal: 4,
227
+ marginBottom: 10,
228
+ },
229
+ headerMid: {
230
+ alignItems: 'center',
231
+ flex: 1,
232
+ },
233
+ navBtn: {
234
+ width: 36,
235
+ height: 36,
236
+ borderWidth: 1,
237
+ alignItems: 'center',
238
+ justifyContent: 'center',
239
+ },
240
+ navTxt: {
241
+ fontSize: 20,
242
+ lineHeight: 22,
243
+ },
244
+ title: {
245
+ fontSize: 17,
246
+ fontWeight: '700',
247
+ },
248
+ subtitle: {
249
+ fontSize: 12,
250
+ marginTop: 2,
251
+ },
252
+ weekRow: {
253
+ flexDirection: 'row',
254
+ },
255
+ cellWrap: {
256
+ flex: 1,
257
+ aspectRatio: 0.85,
258
+ padding: 1.5,
259
+ },
260
+ weekTxt: {
261
+ textAlign: 'center',
262
+ fontSize: 12,
263
+ fontWeight: '600',
264
+ },
265
+ cell: {
266
+ flex: 1,
267
+ alignItems: 'center',
268
+ justifyContent: 'center',
269
+ borderWidth: 0,
270
+ },
271
+ solarTxt: {
272
+ lineHeight: 20,
273
+ },
274
+ lunarTxt: {
275
+ marginTop: 1,
276
+ },
277
+ legend: {
278
+ flexDirection: 'row',
279
+ flexWrap: 'wrap',
280
+ justifyContent: 'center',
281
+ marginTop: 10,
282
+ paddingTop: 8,
283
+ borderTopWidth: react_native_1.StyleSheet.hairlineWidth,
284
+ gap: 10,
285
+ },
286
+ legendItem: {
287
+ flexDirection: 'row',
288
+ alignItems: 'center',
289
+ },
290
+ dot: {
291
+ width: 8,
292
+ height: 8,
293
+ borderRadius: 4,
294
+ marginRight: 4,
295
+ },
296
+ legendTxt: {
297
+ fontSize: 11,
298
+ },
299
+ todayBtn: {
300
+ marginTop: 10,
301
+ marginHorizontal: 4,
302
+ paddingVertical: 8,
303
+ borderWidth: 1,
304
+ alignItems: 'center',
305
+ },
306
+ todayTxt: {
307
+ fontSize: 13,
308
+ fontWeight: '600',
309
+ },
310
+ });
311
+ exports.default = LunarCalendar;
@@ -0,0 +1,32 @@
1
+ import * as React from 'react';
2
+ import { type StyleProp, type ViewStyle } from 'react-native';
3
+ import type { LunarDayInfo } from '../core/types';
4
+ import type { LichVietDay } from '../dataset/decode';
5
+ import { type LunarTheme } from './theme';
6
+ export type DetailSection = 'canchi' | 'gio' | 'sao' | 'viec' | 'huong' | 'tuoixung';
7
+ export interface LunarDayDetailProps {
8
+ /** Thông tin ngày (từ `getLunarDayInfo`) */
9
+ day: LunarDayInfo;
10
+ /** Dữ liệu chi tiết (từ `getDayData`) — tuỳ chọn, có thì hiện thêm sao/việc/hướng */
11
+ data?: LichVietDay | null;
12
+ /** Chọn phần muốn hiển thị, mặc định hiện hết những gì có */
13
+ sections?: DetailSection[];
14
+ theme?: Partial<LunarTheme>;
15
+ colorScheme?: 'light' | 'dark';
16
+ locale?: 'vi' | 'en';
17
+ style?: StyleProp<ViewStyle>;
18
+ /** Cho phép cuộn dọc bên trong (mặc định true) */
19
+ scrollable?: boolean;
20
+ }
21
+ /**
22
+ * Thẻ chi tiết một ngày: can chi, tiết khí, trực, giờ hoàng đạo,
23
+ * sao tốt/xấu, việc nên làm, hướng tốt, tuổi xung.
24
+ *
25
+ * @example
26
+ * import { LunarDayDetail } from 'react-native-lich-am/ui';
27
+ * import { getDayData } from 'react-native-lich-am/dataset';
28
+ *
29
+ * <LunarDayDetail day={getLunarDayInfo(new Date())} data={getDayData('2024-02-10')} />
30
+ */
31
+ export declare function LunarDayDetail(props: LunarDayDetailProps): React.ReactElement;
32
+ export default LunarDayDetail;