mp-taro-kit 0.0.3 → 0.0.4

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 (139) hide show
  1. package/README.md +2 -2
  2. package/dist/core/configure.cjs +75 -0
  3. package/dist/core/configure.d.ts +18 -0
  4. package/dist/core/configure.js +69 -0
  5. package/dist/core/faces.cjs +2 -0
  6. package/dist/core/faces.d.ts +42 -0
  7. package/dist/core/faces.js +1 -0
  8. package/dist/core/index.cjs +30 -0
  9. package/dist/core/index.d.ts +6 -1
  10. package/dist/core/index.js +5 -1
  11. package/dist/core/request.cjs +60 -0
  12. package/dist/core/request.d.ts +27 -0
  13. package/dist/core/request.js +51 -0
  14. package/dist/core/router.cjs +71 -0
  15. package/dist/core/router.d.ts +11 -0
  16. package/dist/core/router.js +63 -0
  17. package/dist/core/storage.cjs +63 -0
  18. package/dist/core/storage.d.ts +6 -0
  19. package/dist/core/storage.js +57 -0
  20. package/dist/core/weapp.cjs +37 -0
  21. package/dist/core/weapp.d.ts +7 -0
  22. package/dist/core/weapp.js +32 -0
  23. package/dist/design/tokens.css +59 -9
  24. package/dist/runtime/index.cjs +13 -0
  25. package/dist/runtime/index.d.ts +5 -1
  26. package/dist/runtime/index.js +6 -1
  27. package/dist/runtime/loading-slot.cjs +44 -0
  28. package/dist/runtime/loading-slot.d.ts +15 -0
  29. package/dist/runtime/loading-slot.js +41 -0
  30. package/dist/runtime/notify.cjs +52 -0
  31. package/dist/runtime/notify.d.ts +19 -0
  32. package/dist/runtime/notify.js +49 -0
  33. package/dist/runtime/overlay-stack.cjs +49 -0
  34. package/dist/runtime/overlay-stack.d.ts +17 -0
  35. package/dist/runtime/overlay-stack.js +46 -0
  36. package/dist/runtime/singleton.cjs +17 -0
  37. package/dist/runtime/singleton.d.ts +6 -0
  38. package/dist/runtime/singleton.js +14 -0
  39. package/dist/runtime/thenable.cjs +17 -0
  40. package/dist/runtime/thenable.d.ts +7 -0
  41. package/dist/runtime/thenable.js +13 -0
  42. package/dist/styles/tokens.css +59 -9
  43. package/dist/ui/actions/Button.cjs +32 -0
  44. package/dist/ui/actions/Button.d.ts +13 -0
  45. package/dist/ui/actions/Button.js +29 -0
  46. package/dist/ui/actions/index.cjs +5 -0
  47. package/dist/ui/actions/index.d.ts +1 -0
  48. package/dist/ui/actions/index.js +1 -0
  49. package/dist/ui/actions/style/index.css +22 -0
  50. package/dist/ui/commands.cjs +86 -0
  51. package/dist/ui/commands.d.ts +21 -0
  52. package/dist/ui/commands.js +73 -0
  53. package/dist/ui/display/Badge.cjs +10 -0
  54. package/dist/ui/display/Badge.d.ts +9 -0
  55. package/dist/ui/display/Badge.js +7 -0
  56. package/dist/ui/display/Divider.cjs +9 -0
  57. package/dist/ui/display/Divider.d.ts +5 -0
  58. package/dist/ui/display/Divider.js +6 -0
  59. package/dist/ui/display/index.cjs +7 -0
  60. package/dist/ui/display/index.d.ts +2 -0
  61. package/dist/ui/display/index.js +2 -0
  62. package/dist/ui/display/style/index.css +30 -0
  63. package/dist/ui/feedback/Dialog.cjs +12 -0
  64. package/dist/ui/feedback/Dialog.d.ts +15 -0
  65. package/dist/ui/feedback/Dialog.js +9 -0
  66. package/dist/ui/feedback/Loading.cjs +12 -0
  67. package/dist/ui/feedback/Loading.d.ts +7 -0
  68. package/dist/ui/feedback/Loading.js +9 -0
  69. package/dist/ui/feedback/Toast.cjs +12 -0
  70. package/dist/ui/feedback/Toast.d.ts +9 -0
  71. package/dist/ui/feedback/Toast.js +9 -0
  72. package/dist/ui/feedback/index.cjs +9 -0
  73. package/dist/ui/feedback/index.d.ts +3 -0
  74. package/dist/ui/feedback/index.js +3 -0
  75. package/dist/ui/feedback/style/index.css +67 -0
  76. package/dist/ui/index.cjs +15 -0
  77. package/dist/ui/index.d.ts +4 -1
  78. package/dist/ui/index.js +2 -1
  79. package/dist/ui/infra/OverlayHost.cjs +33 -0
  80. package/dist/ui/infra/OverlayHost.d.ts +8 -0
  81. package/dist/ui/infra/OverlayHost.js +30 -0
  82. package/dist/ui/infra/SafeArea.cjs +10 -0
  83. package/dist/ui/infra/SafeArea.d.ts +8 -0
  84. package/dist/ui/infra/SafeArea.js +7 -0
  85. package/dist/ui/infra/index.cjs +11 -0
  86. package/dist/ui/infra/index.d.ts +3 -0
  87. package/dist/ui/infra/index.js +3 -0
  88. package/dist/ui/infra/style/index.css +83 -0
  89. package/dist/ui/infra/use-store.cjs +17 -0
  90. package/dist/ui/infra/use-store.d.ts +8 -0
  91. package/dist/ui/infra/use-store.js +12 -0
  92. package/dist/ui/layout/Mask.cjs +12 -0
  93. package/dist/ui/layout/Mask.d.ts +7 -0
  94. package/dist/ui/layout/Mask.js +9 -0
  95. package/dist/ui/layout/Overlay.cjs +11 -0
  96. package/dist/ui/layout/Overlay.d.ts +8 -0
  97. package/dist/ui/layout/Overlay.js +8 -0
  98. package/dist/ui/layout/Popup.cjs +13 -0
  99. package/dist/ui/layout/Popup.d.ts +11 -0
  100. package/dist/ui/layout/Popup.js +10 -0
  101. package/dist/ui/layout/index.cjs +9 -0
  102. package/dist/ui/layout/index.d.ts +3 -0
  103. package/dist/ui/layout/index.js +3 -0
  104. package/dist/ui/layout/style/index.css +51 -0
  105. package/dist/ui/navigation/Drawer.cjs +12 -0
  106. package/dist/ui/navigation/Drawer.d.ts +11 -0
  107. package/dist/ui/navigation/Drawer.js +9 -0
  108. package/dist/ui/navigation/Dropdown.cjs +12 -0
  109. package/dist/ui/navigation/Dropdown.d.ts +9 -0
  110. package/dist/ui/navigation/Dropdown.js +9 -0
  111. package/dist/ui/navigation/index.cjs +7 -0
  112. package/dist/ui/navigation/index.d.ts +2 -0
  113. package/dist/ui/navigation/index.js +2 -0
  114. package/dist/ui/navigation/style/index.css +42 -0
  115. package/dist/ui/state.cjs +20 -0
  116. package/dist/ui/state.d.ts +25 -0
  117. package/dist/ui/state.js +17 -0
  118. package/dist/utils/date.cjs +98 -0
  119. package/dist/utils/date.d.ts +18 -0
  120. package/dist/utils/date.js +89 -0
  121. package/dist/utils/i18n.cjs +31 -0
  122. package/dist/utils/i18n.d.ts +11 -0
  123. package/dist/utils/i18n.js +25 -0
  124. package/dist/utils/index.cjs +28 -0
  125. package/dist/utils/index.d.ts +5 -1
  126. package/dist/utils/index.js +6 -1
  127. package/dist/utils/messages.zh.cjs +13 -0
  128. package/dist/utils/messages.zh.d.ts +1 -0
  129. package/dist/utils/messages.zh.js +10 -0
  130. package/dist/utils/number.cjs +38 -0
  131. package/dist/utils/number.d.ts +6 -0
  132. package/dist/utils/number.js +33 -0
  133. package/dist/utils/path.cjs +33 -0
  134. package/dist/utils/path.d.ts +8 -0
  135. package/dist/utils/path.js +27 -0
  136. package/dist/utils/string.cjs +55 -0
  137. package/dist/utils/string.d.ts +8 -0
  138. package/dist/utils/string.js +50 -0
  139. package/package.json +4 -2
@@ -0,0 +1,42 @@
1
+ .mptk-drawer__mask,
2
+ .mptk-dropdown__mask {
3
+ position: fixed;
4
+ top: 0;
5
+ right: 0;
6
+ bottom: 0;
7
+ left: 0;
8
+ background-color: var(--mptk-fg);
9
+ opacity: 0.4;
10
+ }
11
+
12
+ .mptk-drawer__panel {
13
+ position: fixed;
14
+ top: 0;
15
+ bottom: 0;
16
+ background-color: var(--mptk-surface-1);
17
+ padding-top: var(--mptk-space-4);
18
+ padding-right: var(--mptk-space-4);
19
+ padding-bottom: var(--mptk-space-4);
20
+ padding-left: var(--mptk-space-4);
21
+ }
22
+
23
+ .mptk-drawer__panel--left {
24
+ left: 0;
25
+ }
26
+
27
+ .mptk-drawer__panel--right {
28
+ right: 0;
29
+ }
30
+
31
+ .mptk-dropdown__panel {
32
+ position: absolute;
33
+ left: 0;
34
+ right: 0;
35
+ background-color: var(--mptk-surface-1);
36
+ border-bottom-left-radius: var(--mptk-radius-md);
37
+ border-bottom-right-radius: var(--mptk-radius-md);
38
+ padding-top: var(--mptk-space-2);
39
+ padding-right: var(--mptk-space-3);
40
+ padding-bottom: var(--mptk-space-2);
41
+ padding-left: var(--mptk-space-3);
42
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uiState = uiState;
4
+ const singleton_js_1 = require("../runtime/singleton.cjs");
5
+ const overlay_stack_js_1 = require("../runtime/overlay-stack.cjs");
6
+ const notify_js_1 = require("../runtime/notify.cjs");
7
+ const loading_slot_js_1 = require("../runtime/loading-slot.cjs");
8
+ /**
9
+ * 全局唯一状态:用 runtime 的跨副本单例,保证命令式 API 与 <OverlayHost />
10
+ * 在主包 / 分包各副本里看到的是同一份栈、同一条通知队列、同一个 loading 槽。
11
+ */
12
+ function uiState() {
13
+ return (0, singleton_js_1.createSingleton)('ui', () => ({
14
+ overlays: (0, overlay_stack_js_1.createOverlayStack)(),
15
+ notices: (0, notify_js_1.createNotifyCenter)(),
16
+ loading: (0, loading_slot_js_1.createLoadingSlot)(),
17
+ mounted: false,
18
+ loadingHandles: new Set(),
19
+ }));
20
+ }
@@ -0,0 +1,25 @@
1
+ import type { OverlayStack } from '../runtime/overlay-stack.js';
2
+ import type { NotifyCenter } from '../runtime/notify.js';
3
+ import type { LoadingSlot } from '../runtime/loading-slot.js';
4
+ /** 弹窗条目的载荷:命令式 API 只把待渲染数据推进栈,resolve 由 <OverlayHost /> 调用。 */
5
+ export interface DialogPayload {
6
+ readonly kind: 'alert' | 'confirm';
7
+ readonly title: string | undefined;
8
+ readonly message: string;
9
+ readonly confirmText: string;
10
+ readonly cancelText: string;
11
+ readonly resolve: (confirmed: boolean) => void;
12
+ }
13
+ export interface UIState {
14
+ readonly overlays: OverlayStack<DialogPayload>;
15
+ readonly notices: NotifyCenter;
16
+ readonly loading: LoadingSlot;
17
+ /** 宿主是否已挂载 <OverlayHost />;命令式 API 靠它判定开发者契约。 */
18
+ mounted: boolean;
19
+ readonly loadingHandles: Set<number>;
20
+ }
21
+ /**
22
+ * 全局唯一状态:用 runtime 的跨副本单例,保证命令式 API 与 <OverlayHost />
23
+ * 在主包 / 分包各副本里看到的是同一份栈、同一条通知队列、同一个 loading 槽。
24
+ */
25
+ export declare function uiState(): UIState;
@@ -0,0 +1,17 @@
1
+ import { createSingleton } from '../runtime/singleton.js';
2
+ import { createOverlayStack } from '../runtime/overlay-stack.js';
3
+ import { createNotifyCenter } from '../runtime/notify.js';
4
+ import { createLoadingSlot } from '../runtime/loading-slot.js';
5
+ /**
6
+ * 全局唯一状态:用 runtime 的跨副本单例,保证命令式 API 与 <OverlayHost />
7
+ * 在主包 / 分包各副本里看到的是同一份栈、同一条通知队列、同一个 loading 槽。
8
+ */
9
+ export function uiState() {
10
+ return createSingleton('ui', () => ({
11
+ overlays: createOverlayStack(),
12
+ notices: createNotifyCenter(),
13
+ loading: createLoadingSlot(),
14
+ mounted: false,
15
+ loadingHandles: new Set(),
16
+ }));
17
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatYmd = formatYmd;
4
+ exports.formatClock = formatClock;
5
+ exports.formatDateTime = formatDateTime;
6
+ exports.formatDurationHms = formatDurationHms;
7
+ exports.sameDay = sameDay;
8
+ exports.overlaps = overlaps;
9
+ exports.relativeTime = relativeTime;
10
+ // 日期 / 时间格式化,全部走本机时区。解析失败一律返回 '—',不抛、不编造时间。
11
+ const i18n_js_1 = require("./i18n.cjs");
12
+ const FALLBACK = '—';
13
+ const MINUTE = 60000;
14
+ const HOUR = 60 * MINUTE;
15
+ const DAY = 24 * HOUR;
16
+ function pad2(value) {
17
+ return String(value).padStart(2, '0');
18
+ }
19
+ /** 字符串先试原生解析,再试 `-` → `/`(小程序 iOS 只认斜杠格式)。 */
20
+ function toDate(value) {
21
+ if (value instanceof Date)
22
+ return Number.isNaN(value.getTime()) ? null : value;
23
+ if (typeof value === 'number')
24
+ return Number.isFinite(value) ? new Date(value) : null;
25
+ if (typeof value !== 'string' || value.trim() === '')
26
+ return null;
27
+ let ms = Date.parse(value);
28
+ if (Number.isNaN(ms) && !value.includes('T'))
29
+ ms = Date.parse(value.replace(/-/g, '/'));
30
+ return Number.isNaN(ms) ? null : new Date(ms);
31
+ }
32
+ /** `YYYY-MM-DD`。 */
33
+ function formatYmd(value) {
34
+ const d = toDate(value);
35
+ if (!d)
36
+ return FALLBACK;
37
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
38
+ }
39
+ /** `HH:mm:ss`。 */
40
+ function formatClock(value) {
41
+ const d = toDate(value);
42
+ if (!d)
43
+ return FALLBACK;
44
+ return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
45
+ }
46
+ /** `YYYY-MM-DD HH:mm`。 */
47
+ function formatDateTime(value) {
48
+ const d = toDate(value);
49
+ if (!d)
50
+ return FALLBACK;
51
+ return `${formatYmd(d)} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
52
+ }
53
+ /** 时长:有小时 ⇒ `H:MM:SS`,不足 1 小时 ⇒ `MM:SS`;负数 / 非有限 ⇒ `—`。 */
54
+ function formatDurationHms(ms) {
55
+ if (!Number.isFinite(ms) || ms < 0)
56
+ return FALLBACK;
57
+ const total = Math.round(ms / 1000);
58
+ const h = Math.floor(total / 3600);
59
+ const m = Math.floor((total % 3600) / 60);
60
+ const s = total % 60;
61
+ return h > 0 ? `${h}:${pad2(m)}:${pad2(s)}` : `${pad2(m)}:${pad2(s)}`;
62
+ }
63
+ /** 两个时刻是否同一天(本机时区);任一无效 ⇒ false。 */
64
+ function sameDay(a, b) {
65
+ const x = toDate(a);
66
+ const y = toDate(b);
67
+ if (!x || !y)
68
+ return false;
69
+ return (x.getFullYear() === y.getFullYear() && x.getMonth() === y.getMonth() && x.getDate() === y.getDate());
70
+ }
71
+ /** 半开区间 `[aFrom, aTo)` 是否重叠;非有限数视为不重叠。 */
72
+ function overlaps(aFrom, aTo, bFrom, bTo) {
73
+ if (![aFrom, aTo, bFrom, bTo].every(Number.isFinite))
74
+ return false;
75
+ return aFrom < bTo && bFrom < aTo;
76
+ }
77
+ /**
78
+ * 相对时间:过去 ⇒ `N 分钟前`,未来 ⇒ `N 分钟后`;超过 7 天回退 `formatYmd`。
79
+ * 文案走 i18n,宿主注册其他语言后即随之切换;解析失败 ⇒ `—`。
80
+ */
81
+ function relativeTime(value, now = Date.now()) {
82
+ const target = toDate(value);
83
+ const base = toDate(now);
84
+ if (!target || !base)
85
+ return FALLBACK;
86
+ const diff = target.getTime() - base.getTime();
87
+ const abs = Math.abs(diff);
88
+ if (abs < MINUTE)
89
+ return (0, i18n_js_1.t)('relNow');
90
+ if (abs >= 7 * DAY)
91
+ return formatYmd(target);
92
+ const past = diff < 0;
93
+ if (abs < HOUR)
94
+ return (0, i18n_js_1.t)(past ? 'relMinutesAgo' : 'relMinutesLater', { n: Math.floor(abs / MINUTE) });
95
+ if (abs < DAY)
96
+ return (0, i18n_js_1.t)(past ? 'relHoursAgo' : 'relHoursLater', { n: Math.floor(abs / HOUR) });
97
+ return (0, i18n_js_1.t)(past ? 'relDaysAgo' : 'relDaysLater', { n: Math.floor(abs / DAY) });
98
+ }
@@ -0,0 +1,18 @@
1
+ export type DateLike = Date | number | string;
2
+ /** `YYYY-MM-DD`。 */
3
+ export declare function formatYmd(value: DateLike): string;
4
+ /** `HH:mm:ss`。 */
5
+ export declare function formatClock(value: DateLike): string;
6
+ /** `YYYY-MM-DD HH:mm`。 */
7
+ export declare function formatDateTime(value: DateLike): string;
8
+ /** 时长:有小时 ⇒ `H:MM:SS`,不足 1 小时 ⇒ `MM:SS`;负数 / 非有限 ⇒ `—`。 */
9
+ export declare function formatDurationHms(ms: number): string;
10
+ /** 两个时刻是否同一天(本机时区);任一无效 ⇒ false。 */
11
+ export declare function sameDay(a: DateLike, b: DateLike): boolean;
12
+ /** 半开区间 `[aFrom, aTo)` 是否重叠;非有限数视为不重叠。 */
13
+ export declare function overlaps(aFrom: number, aTo: number, bFrom: number, bTo: number): boolean;
14
+ /**
15
+ * 相对时间:过去 ⇒ `N 分钟前`,未来 ⇒ `N 分钟后`;超过 7 天回退 `formatYmd`。
16
+ * 文案走 i18n,宿主注册其他语言后即随之切换;解析失败 ⇒ `—`。
17
+ */
18
+ export declare function relativeTime(value: DateLike, now?: DateLike): string;
@@ -0,0 +1,89 @@
1
+ // 日期 / 时间格式化,全部走本机时区。解析失败一律返回 '—',不抛、不编造时间。
2
+ import { t } from './i18n.js';
3
+ const FALLBACK = '—';
4
+ const MINUTE = 60000;
5
+ const HOUR = 60 * MINUTE;
6
+ const DAY = 24 * HOUR;
7
+ function pad2(value) {
8
+ return String(value).padStart(2, '0');
9
+ }
10
+ /** 字符串先试原生解析,再试 `-` → `/`(小程序 iOS 只认斜杠格式)。 */
11
+ function toDate(value) {
12
+ if (value instanceof Date)
13
+ return Number.isNaN(value.getTime()) ? null : value;
14
+ if (typeof value === 'number')
15
+ return Number.isFinite(value) ? new Date(value) : null;
16
+ if (typeof value !== 'string' || value.trim() === '')
17
+ return null;
18
+ let ms = Date.parse(value);
19
+ if (Number.isNaN(ms) && !value.includes('T'))
20
+ ms = Date.parse(value.replace(/-/g, '/'));
21
+ return Number.isNaN(ms) ? null : new Date(ms);
22
+ }
23
+ /** `YYYY-MM-DD`。 */
24
+ export function formatYmd(value) {
25
+ const d = toDate(value);
26
+ if (!d)
27
+ return FALLBACK;
28
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
29
+ }
30
+ /** `HH:mm:ss`。 */
31
+ export function formatClock(value) {
32
+ const d = toDate(value);
33
+ if (!d)
34
+ return FALLBACK;
35
+ return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
36
+ }
37
+ /** `YYYY-MM-DD HH:mm`。 */
38
+ export function formatDateTime(value) {
39
+ const d = toDate(value);
40
+ if (!d)
41
+ return FALLBACK;
42
+ return `${formatYmd(d)} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
43
+ }
44
+ /** 时长:有小时 ⇒ `H:MM:SS`,不足 1 小时 ⇒ `MM:SS`;负数 / 非有限 ⇒ `—`。 */
45
+ export function formatDurationHms(ms) {
46
+ if (!Number.isFinite(ms) || ms < 0)
47
+ return FALLBACK;
48
+ const total = Math.round(ms / 1000);
49
+ const h = Math.floor(total / 3600);
50
+ const m = Math.floor((total % 3600) / 60);
51
+ const s = total % 60;
52
+ return h > 0 ? `${h}:${pad2(m)}:${pad2(s)}` : `${pad2(m)}:${pad2(s)}`;
53
+ }
54
+ /** 两个时刻是否同一天(本机时区);任一无效 ⇒ false。 */
55
+ export function sameDay(a, b) {
56
+ const x = toDate(a);
57
+ const y = toDate(b);
58
+ if (!x || !y)
59
+ return false;
60
+ return (x.getFullYear() === y.getFullYear() && x.getMonth() === y.getMonth() && x.getDate() === y.getDate());
61
+ }
62
+ /** 半开区间 `[aFrom, aTo)` 是否重叠;非有限数视为不重叠。 */
63
+ export function overlaps(aFrom, aTo, bFrom, bTo) {
64
+ if (![aFrom, aTo, bFrom, bTo].every(Number.isFinite))
65
+ return false;
66
+ return aFrom < bTo && bFrom < aTo;
67
+ }
68
+ /**
69
+ * 相对时间:过去 ⇒ `N 分钟前`,未来 ⇒ `N 分钟后`;超过 7 天回退 `formatYmd`。
70
+ * 文案走 i18n,宿主注册其他语言后即随之切换;解析失败 ⇒ `—`。
71
+ */
72
+ export function relativeTime(value, now = Date.now()) {
73
+ const target = toDate(value);
74
+ const base = toDate(now);
75
+ if (!target || !base)
76
+ return FALLBACK;
77
+ const diff = target.getTime() - base.getTime();
78
+ const abs = Math.abs(diff);
79
+ if (abs < MINUTE)
80
+ return t('relNow');
81
+ if (abs >= 7 * DAY)
82
+ return formatYmd(target);
83
+ const past = diff < 0;
84
+ if (abs < HOUR)
85
+ return t(past ? 'relMinutesAgo' : 'relMinutesLater', { n: Math.floor(abs / MINUTE) });
86
+ if (abs < DAY)
87
+ return t(past ? 'relHoursAgo' : 'relHoursLater', { n: Math.floor(abs / HOUR) });
88
+ return t(past ? 'relDaysAgo' : 'relDaysLater', { n: Math.floor(abs / DAY) });
89
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLocale = getLocale;
4
+ exports.setLocale = setLocale;
5
+ exports.registerMessages = registerMessages;
6
+ exports.t = t;
7
+ // 唯一可变状态是语言注册表。默认语言是唯一静态引入的语言包;
8
+ // 其他语言由宿主按需加载后 registerMessages 注入,库入口绝不静态引入全量语言包。
9
+ const messages_zh_js_1 = require("./messages.zh.cjs");
10
+ const DEFAULT_LOCALE = 'zh-CN';
11
+ const registry = new Map([[DEFAULT_LOCALE, messages_zh_js_1.ZH_CN]]);
12
+ let currentLocale = DEFAULT_LOCALE;
13
+ function getLocale() {
14
+ return currentLocale;
15
+ }
16
+ /** 未注册的语言回落默认中文,不抛。 */
17
+ function setLocale(locale) {
18
+ currentLocale = registry.has(locale) ? locale : DEFAULT_LOCALE;
19
+ }
20
+ /** 宿主按需加载语言包后注入;重复注册按 key 合并,不覆盖已有条目。 */
21
+ function registerMessages(locale, messages) {
22
+ const existing = registry.get(locale);
23
+ registry.set(locale, existing ? { ...existing, ...messages } : { ...messages });
24
+ }
25
+ /** 取当前语言 → 缺 key 回落中文 → 仍缺返回 key;{n} 插值;从不抛。 */
26
+ function t(key, params) {
27
+ const template = registry.get(currentLocale)?.[key] ?? registry.get(DEFAULT_LOCALE)?.[key] ?? key;
28
+ if (!params)
29
+ return template;
30
+ return template.replace(/\{(\w+)\}/g, (match, name) => Object.keys(params).includes(name) ? String(params[name]) : match);
31
+ }
@@ -0,0 +1,11 @@
1
+ export type Locale = string;
2
+ export type Messages = Record<string, string>;
3
+ export type MessageParams = Record<string, string | number>;
4
+ export type Translate = (key: string, params?: MessageParams) => string;
5
+ export declare function getLocale(): Locale;
6
+ /** 未注册的语言回落默认中文,不抛。 */
7
+ export declare function setLocale(locale: Locale): void;
8
+ /** 宿主按需加载语言包后注入;重复注册按 key 合并,不覆盖已有条目。 */
9
+ export declare function registerMessages(locale: Locale, messages: Messages): void;
10
+ /** 取当前语言 → 缺 key 回落中文 → 仍缺返回 key;{n} 插值;从不抛。 */
11
+ export declare function t(key: string, params?: MessageParams): string;
@@ -0,0 +1,25 @@
1
+ // 唯一可变状态是语言注册表。默认语言是唯一静态引入的语言包;
2
+ // 其他语言由宿主按需加载后 registerMessages 注入,库入口绝不静态引入全量语言包。
3
+ import { ZH_CN } from './messages.zh.js';
4
+ const DEFAULT_LOCALE = 'zh-CN';
5
+ const registry = new Map([[DEFAULT_LOCALE, ZH_CN]]);
6
+ let currentLocale = DEFAULT_LOCALE;
7
+ export function getLocale() {
8
+ return currentLocale;
9
+ }
10
+ /** 未注册的语言回落默认中文,不抛。 */
11
+ export function setLocale(locale) {
12
+ currentLocale = registry.has(locale) ? locale : DEFAULT_LOCALE;
13
+ }
14
+ /** 宿主按需加载语言包后注入;重复注册按 key 合并,不覆盖已有条目。 */
15
+ export function registerMessages(locale, messages) {
16
+ const existing = registry.get(locale);
17
+ registry.set(locale, existing ? { ...existing, ...messages } : { ...messages });
18
+ }
19
+ /** 取当前语言 → 缺 key 回落中文 → 仍缺返回 key;{n} 插值;从不抛。 */
20
+ export function t(key, params) {
21
+ const template = registry.get(currentLocale)?.[key] ?? registry.get(DEFAULT_LOCALE)?.[key] ?? key;
22
+ if (!params)
23
+ return template;
24
+ return template.replace(/\{(\w+)\}/g, (match, name) => Object.keys(params).includes(name) ? String(params[name]) : match);
25
+ }
@@ -1,2 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerMessages = exports.t = exports.setLocale = exports.getLocale = exports.crumbsOf = exports.extOf = exports.parentOf = exports.joinPath = exports.clamp = exports.formatCount = exports.formatBytes = exports.baseNameOf = exports.truncateBytes = exports.safeTrim = exports.overlaps = exports.sameDay = exports.relativeTime = exports.formatDurationHms = exports.formatDateTime = exports.formatClock = exports.formatYmd = void 0;
4
+ // utils 层单点出口:只做具名 re-export,不含实现。
5
+ var date_js_1 = require("./date.cjs");
6
+ Object.defineProperty(exports, "formatYmd", { enumerable: true, get: function () { return date_js_1.formatYmd; } });
7
+ Object.defineProperty(exports, "formatClock", { enumerable: true, get: function () { return date_js_1.formatClock; } });
8
+ Object.defineProperty(exports, "formatDateTime", { enumerable: true, get: function () { return date_js_1.formatDateTime; } });
9
+ Object.defineProperty(exports, "formatDurationHms", { enumerable: true, get: function () { return date_js_1.formatDurationHms; } });
10
+ Object.defineProperty(exports, "relativeTime", { enumerable: true, get: function () { return date_js_1.relativeTime; } });
11
+ Object.defineProperty(exports, "sameDay", { enumerable: true, get: function () { return date_js_1.sameDay; } });
12
+ Object.defineProperty(exports, "overlaps", { enumerable: true, get: function () { return date_js_1.overlaps; } });
13
+ var string_js_1 = require("./string.cjs");
14
+ Object.defineProperty(exports, "safeTrim", { enumerable: true, get: function () { return string_js_1.safeTrim; } });
15
+ Object.defineProperty(exports, "truncateBytes", { enumerable: true, get: function () { return string_js_1.truncateBytes; } });
16
+ Object.defineProperty(exports, "baseNameOf", { enumerable: true, get: function () { return string_js_1.baseNameOf; } });
17
+ var number_js_1 = require("./number.cjs");
18
+ Object.defineProperty(exports, "formatBytes", { enumerable: true, get: function () { return number_js_1.formatBytes; } });
19
+ Object.defineProperty(exports, "formatCount", { enumerable: true, get: function () { return number_js_1.formatCount; } });
20
+ Object.defineProperty(exports, "clamp", { enumerable: true, get: function () { return number_js_1.clamp; } });
21
+ var path_js_1 = require("./path.cjs");
22
+ Object.defineProperty(exports, "joinPath", { enumerable: true, get: function () { return path_js_1.joinPath; } });
23
+ Object.defineProperty(exports, "parentOf", { enumerable: true, get: function () { return path_js_1.parentOf; } });
24
+ Object.defineProperty(exports, "extOf", { enumerable: true, get: function () { return path_js_1.extOf; } });
25
+ Object.defineProperty(exports, "crumbsOf", { enumerable: true, get: function () { return path_js_1.crumbsOf; } });
26
+ var i18n_js_1 = require("./i18n.cjs");
27
+ Object.defineProperty(exports, "getLocale", { enumerable: true, get: function () { return i18n_js_1.getLocale; } });
28
+ Object.defineProperty(exports, "setLocale", { enumerable: true, get: function () { return i18n_js_1.setLocale; } });
29
+ Object.defineProperty(exports, "t", { enumerable: true, get: function () { return i18n_js_1.t; } });
30
+ Object.defineProperty(exports, "registerMessages", { enumerable: true, get: function () { return i18n_js_1.registerMessages; } });
@@ -1 +1,5 @@
1
- export {};
1
+ export { formatYmd, formatClock, formatDateTime, formatDurationHms, relativeTime, sameDay, overlaps, type DateLike, } from './date.js';
2
+ export { safeTrim, truncateBytes, baseNameOf } from './string.js';
3
+ export { formatBytes, formatCount, clamp } from './number.js';
4
+ export { joinPath, parentOf, extOf, crumbsOf } from './path.js';
5
+ export { getLocale, setLocale, t, registerMessages, type Locale, type Messages, type MessageParams, type Translate, } from './i18n.js';
@@ -1 +1,6 @@
1
- export {};
1
+ // utils 层单点出口:只做具名 re-export,不含实现。
2
+ export { formatYmd, formatClock, formatDateTime, formatDurationHms, relativeTime, sameDay, overlaps, } from './date.js';
3
+ export { safeTrim, truncateBytes, baseNameOf } from './string.js';
4
+ export { formatBytes, formatCount, clamp } from './number.js';
5
+ export { joinPath, parentOf, extOf, crumbsOf } from './path.js';
6
+ export { getLocale, setLocale, t, registerMessages, } from './i18n.js';
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZH_CN = void 0;
4
+ // 默认中文极小字典:只收 utils 自己要吐的文案;界面文案由宿主自管。
5
+ exports.ZH_CN = {
6
+ relNow: '刚刚',
7
+ relMinutesAgo: '{n} 分钟前',
8
+ relHoursAgo: '{n} 小时前',
9
+ relDaysAgo: '{n} 天前',
10
+ relMinutesLater: '{n} 分钟后',
11
+ relHoursLater: '{n} 小时后',
12
+ relDaysLater: '{n} 天后',
13
+ };
@@ -0,0 +1 @@
1
+ export declare const ZH_CN: Record<string, string>;
@@ -0,0 +1,10 @@
1
+ // 默认中文极小字典:只收 utils 自己要吐的文案;界面文案由宿主自管。
2
+ export const ZH_CN = {
3
+ relNow: '刚刚',
4
+ relMinutesAgo: '{n} 分钟前',
5
+ relHoursAgo: '{n} 小时前',
6
+ relDaysAgo: '{n} 天前',
7
+ relMinutesLater: '{n} 分钟后',
8
+ relHoursLater: '{n} 小时后',
9
+ relDaysLater: '{n} 天后',
10
+ };
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatBytes = formatBytes;
4
+ exports.formatCount = formatCount;
5
+ exports.clamp = clamp;
6
+ const FALLBACK = '—';
7
+ /** 字节数 → 人话(`12 KB` / `3.4 MB`);0 / 负数 / 非有限 ⇒ `—`。 */
8
+ function formatBytes(bytes) {
9
+ if (!Number.isFinite(bytes) || bytes <= 0)
10
+ return FALLBACK;
11
+ if (bytes < 1024)
12
+ return `${bytes} B`;
13
+ const units = ['KB', 'MB', 'GB', 'TB'];
14
+ let value = bytes / 1024;
15
+ let unit = 0;
16
+ while (value >= 1024 && unit < units.length - 1) {
17
+ value /= 1024;
18
+ unit += 1;
19
+ }
20
+ return `${value >= 10 ? String(Math.round(value)) : value.toFixed(1)} ${units[unit]}`;
21
+ }
22
+ /** 计数的大众格式:≥1K 用 K、≥1M 用 M(`1234` → `1.2K`)。 */
23
+ function formatCount(n) {
24
+ if (!Number.isFinite(n))
25
+ return FALLBACK;
26
+ const trim = (v) => Math.abs(v) >= 100 ? String(Math.round(v)) : v.toFixed(1).replace(/\.0$/, '');
27
+ if (Math.abs(n) >= 1000000)
28
+ return `${trim(n / 1000000)}M`;
29
+ if (Math.abs(n) >= 1000)
30
+ return `${trim(n / 1000)}K`;
31
+ return String(n);
32
+ }
33
+ /** 夹到 `[min, max]`;非有限值或 min > max 时返回 min,不抛。 */
34
+ function clamp(value, min, max) {
35
+ if (!Number.isFinite(value) || !Number.isFinite(min) || !Number.isFinite(max) || min > max)
36
+ return min;
37
+ return Math.min(Math.max(value, min), max);
38
+ }
@@ -0,0 +1,6 @@
1
+ /** 字节数 → 人话(`12 KB` / `3.4 MB`);0 / 负数 / 非有限 ⇒ `—`。 */
2
+ export declare function formatBytes(bytes: number): string;
3
+ /** 计数的大众格式:≥1K 用 K、≥1M 用 M(`1234` → `1.2K`)。 */
4
+ export declare function formatCount(n: number): string;
5
+ /** 夹到 `[min, max]`;非有限值或 min > max 时返回 min,不抛。 */
6
+ export declare function clamp(value: number, min: number, max: number): number;
@@ -0,0 +1,33 @@
1
+ const FALLBACK = '—';
2
+ /** 字节数 → 人话(`12 KB` / `3.4 MB`);0 / 负数 / 非有限 ⇒ `—`。 */
3
+ export function formatBytes(bytes) {
4
+ if (!Number.isFinite(bytes) || bytes <= 0)
5
+ return FALLBACK;
6
+ if (bytes < 1024)
7
+ return `${bytes} B`;
8
+ const units = ['KB', 'MB', 'GB', 'TB'];
9
+ let value = bytes / 1024;
10
+ let unit = 0;
11
+ while (value >= 1024 && unit < units.length - 1) {
12
+ value /= 1024;
13
+ unit += 1;
14
+ }
15
+ return `${value >= 10 ? String(Math.round(value)) : value.toFixed(1)} ${units[unit]}`;
16
+ }
17
+ /** 计数的大众格式:≥1K 用 K、≥1M 用 M(`1234` → `1.2K`)。 */
18
+ export function formatCount(n) {
19
+ if (!Number.isFinite(n))
20
+ return FALLBACK;
21
+ const trim = (v) => Math.abs(v) >= 100 ? String(Math.round(v)) : v.toFixed(1).replace(/\.0$/, '');
22
+ if (Math.abs(n) >= 1000000)
23
+ return `${trim(n / 1000000)}M`;
24
+ if (Math.abs(n) >= 1000)
25
+ return `${trim(n / 1000)}K`;
26
+ return String(n);
27
+ }
28
+ /** 夹到 `[min, max]`;非有限值或 min > max 时返回 min,不抛。 */
29
+ export function clamp(value, min, max) {
30
+ if (!Number.isFinite(value) || !Number.isFinite(min) || !Number.isFinite(max) || min > max)
31
+ return min;
32
+ return Math.min(Math.max(value, min), max);
33
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ // 纯路径方法:只做字符串切分 / 拼接,不碰宿主、不依赖 React / DOM。
3
+ // 约定:POSIX `/` 分隔;空串 `''` 表示根。
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.joinPath = joinPath;
6
+ exports.parentOf = parentOf;
7
+ exports.extOf = extOf;
8
+ exports.crumbsOf = crumbsOf;
9
+ /** 拼接子路径,去掉 dir 尾斜杠与 name 首斜杠,避免多余斜杠。 */
10
+ function joinPath(dir, name) {
11
+ const base = dir.replace(/\/+$/, '');
12
+ const leaf = name.replace(/^\/+/, '');
13
+ if (base === '')
14
+ return leaf;
15
+ return leaf === '' ? base : `${base}/${leaf}`;
16
+ }
17
+ /** 父目录(无父 = 空串,表示根);先剔尾斜杠,否则 `a/b/` 会返回 `a/b`。 */
18
+ function parentOf(path) {
19
+ const trimmed = path.replace(/\/+$/, '');
20
+ const cut = trimmed.lastIndexOf('/');
21
+ return cut < 0 ? '' : trimmed.slice(0, cut);
22
+ }
23
+ /** 扩展名(小写、不含点);无扩展名返回 `''`;忽略 `?` / `#` 之后部分。 */
24
+ function extOf(path) {
25
+ const clean = path.split(/[?#]/)[0];
26
+ const name = clean.slice(clean.lastIndexOf('/') + 1);
27
+ const dot = name.lastIndexOf('.');
28
+ return dot <= 0 ? '' : name.slice(dot + 1).toLowerCase();
29
+ }
30
+ /** 路径分段(面包屑用):`a/b/c` ⇒ `['a','b','c']`。 */
31
+ function crumbsOf(path) {
32
+ return path.split('/').filter((segment) => segment !== '');
33
+ }
@@ -0,0 +1,8 @@
1
+ /** 拼接子路径,去掉 dir 尾斜杠与 name 首斜杠,避免多余斜杠。 */
2
+ export declare function joinPath(dir: string, name: string): string;
3
+ /** 父目录(无父 = 空串,表示根);先剔尾斜杠,否则 `a/b/` 会返回 `a/b`。 */
4
+ export declare function parentOf(path: string): string;
5
+ /** 扩展名(小写、不含点);无扩展名返回 `''`;忽略 `?` / `#` 之后部分。 */
6
+ export declare function extOf(path: string): string;
7
+ /** 路径分段(面包屑用):`a/b/c` ⇒ `['a','b','c']`。 */
8
+ export declare function crumbsOf(path: string): string[];
@@ -0,0 +1,27 @@
1
+ // 纯路径方法:只做字符串切分 / 拼接,不碰宿主、不依赖 React / DOM。
2
+ // 约定:POSIX `/` 分隔;空串 `''` 表示根。
3
+ /** 拼接子路径,去掉 dir 尾斜杠与 name 首斜杠,避免多余斜杠。 */
4
+ export function joinPath(dir, name) {
5
+ const base = dir.replace(/\/+$/, '');
6
+ const leaf = name.replace(/^\/+/, '');
7
+ if (base === '')
8
+ return leaf;
9
+ return leaf === '' ? base : `${base}/${leaf}`;
10
+ }
11
+ /** 父目录(无父 = 空串,表示根);先剔尾斜杠,否则 `a/b/` 会返回 `a/b`。 */
12
+ export function parentOf(path) {
13
+ const trimmed = path.replace(/\/+$/, '');
14
+ const cut = trimmed.lastIndexOf('/');
15
+ return cut < 0 ? '' : trimmed.slice(0, cut);
16
+ }
17
+ /** 扩展名(小写、不含点);无扩展名返回 `''`;忽略 `?` / `#` 之后部分。 */
18
+ export function extOf(path) {
19
+ const clean = path.split(/[?#]/)[0];
20
+ const name = clean.slice(clean.lastIndexOf('/') + 1);
21
+ const dot = name.lastIndexOf('.');
22
+ return dot <= 0 ? '' : name.slice(dot + 1).toLowerCase();
23
+ }
24
+ /** 路径分段(面包屑用):`a/b/c` ⇒ `['a','b','c']`。 */
25
+ export function crumbsOf(path) {
26
+ return path.split('/').filter((segment) => segment !== '');
27
+ }