@trustbaseai/shop-ui 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.
Files changed (75) hide show
  1. package/README.md +191 -0
  2. package/dist/base.d.ts +79 -0
  3. package/dist/base.d.ts.map +1 -0
  4. package/dist/base.js +149 -0
  5. package/dist/base.js.map +1 -0
  6. package/dist/components/account-panel.d.ts +44 -0
  7. package/dist/components/account-panel.d.ts.map +1 -0
  8. package/dist/components/account-panel.js +144 -0
  9. package/dist/components/account-panel.js.map +1 -0
  10. package/dist/components/goods-detail.d.ts +58 -0
  11. package/dist/components/goods-detail.d.ts.map +1 -0
  12. package/dist/components/goods-detail.js +232 -0
  13. package/dist/components/goods-detail.js.map +1 -0
  14. package/dist/components/goods-list.d.ts +43 -0
  15. package/dist/components/goods-list.d.ts.map +1 -0
  16. package/dist/components/goods-list.js +104 -0
  17. package/dist/components/goods-list.js.map +1 -0
  18. package/dist/components/order-form.d.ts +87 -0
  19. package/dist/components/order-form.d.ts.map +1 -0
  20. package/dist/components/order-form.js +222 -0
  21. package/dist/components/order-form.js.map +1 -0
  22. package/dist/esm/base.d.ts +79 -0
  23. package/dist/esm/base.d.ts.map +1 -0
  24. package/dist/esm/base.js +143 -0
  25. package/dist/esm/base.js.map +1 -0
  26. package/dist/esm/components/account-panel.d.ts +44 -0
  27. package/dist/esm/components/account-panel.d.ts.map +1 -0
  28. package/dist/esm/components/account-panel.js +140 -0
  29. package/dist/esm/components/account-panel.js.map +1 -0
  30. package/dist/esm/components/goods-detail.d.ts +58 -0
  31. package/dist/esm/components/goods-detail.d.ts.map +1 -0
  32. package/dist/esm/components/goods-detail.js +228 -0
  33. package/dist/esm/components/goods-detail.js.map +1 -0
  34. package/dist/esm/components/goods-list.d.ts +43 -0
  35. package/dist/esm/components/goods-list.d.ts.map +1 -0
  36. package/dist/esm/components/goods-list.js +100 -0
  37. package/dist/esm/components/goods-list.js.map +1 -0
  38. package/dist/esm/components/order-form.d.ts +87 -0
  39. package/dist/esm/components/order-form.d.ts.map +1 -0
  40. package/dist/esm/components/order-form.js +218 -0
  41. package/dist/esm/components/order-form.js.map +1 -0
  42. package/dist/esm/format.d.ts +39 -0
  43. package/dist/esm/format.d.ts.map +1 -0
  44. package/dist/esm/format.js +74 -0
  45. package/dist/esm/format.js.map +1 -0
  46. package/dist/esm/index.d.ts +44 -0
  47. package/dist/esm/index.d.ts.map +1 -0
  48. package/dist/esm/index.js +44 -0
  49. package/dist/esm/index.js.map +1 -0
  50. package/dist/esm/package.json +3 -0
  51. package/dist/esm/register.d.ts +33 -0
  52. package/dist/esm/register.d.ts.map +1 -0
  53. package/dist/esm/register.js +44 -0
  54. package/dist/esm/register.js.map +1 -0
  55. package/dist/esm/tokens.d.ts +124 -0
  56. package/dist/esm/tokens.d.ts.map +1 -0
  57. package/dist/esm/tokens.js +184 -0
  58. package/dist/esm/tokens.js.map +1 -0
  59. package/dist/format.d.ts +39 -0
  60. package/dist/format.d.ts.map +1 -0
  61. package/dist/format.js +84 -0
  62. package/dist/format.js.map +1 -0
  63. package/dist/index.d.ts +44 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +84 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/register.d.ts +33 -0
  68. package/dist/register.d.ts.map +1 -0
  69. package/dist/register.js +49 -0
  70. package/dist/register.js.map +1 -0
  71. package/dist/tokens.d.ts +124 -0
  72. package/dist/tokens.d.ts.map +1 -0
  73. package/dist/tokens.js +188 -0
  74. package/dist/tokens.js.map +1 -0
  75. package/package.json +40 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5C,eAAe,EAAE,WAAW;IAC5B,iBAAiB,EAAE,aAAa;IAChC,eAAe,EAAE,WAAW;IAC5B,kBAAkB,EAAE,cAAc;CACnC,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,QAAQ,GAAuC,UAAyD;SAC3G,cAAc,CAAC;IAClB,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO;IACnC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC3D,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACpC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAA2C,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,kBAAkB;IAChC,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAgB,CAAC;AACtD,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Design tokens —— 本包**唯一允许出现视觉字面量的地方**。
3
+ *
4
+ * ## 出处
5
+ *
6
+ * 《TrustBase-设计风格规范-2026-09-22》§1「视觉 tokens(只允许用这些值,禁止魔法值)」:
7
+ *
8
+ * | 类别 | 规范要求 | 本文件对应 |
9
+ * |---|---|---|
10
+ * | 主色 | 1 个(默认 `#1D1D1F` 文字 / `#FFFFFF` 底 / `#F5F5F7` 分区底) | `color.text/background/surface` |
11
+ * | 强调色 | 1 个,只用于主操作与选中态(如 `#C4633C`) | `color.accent` |
12
+ * | 语义色 | 成功/警告/错误各 1 个,**只用于状态**不做装饰 | `color.success/warning/danger` |
13
+ * | 灰阶 | ≤ 5 级(`1D1D1F / 6E6E73 / 8E8E93 / C7C7CC / E5E5EA`) | `gray` |
14
+ * | 字号 | ≤ 5 级:34 / 22 / 17 / 15 / 13(正文 17,次要 15,注释 13) | `fontSize` |
15
+ * | 字重 | 只用 400 / 600 | `fontWeight` |
16
+ * | 行高 | 固定 1.5(标题 1.2) | `lineHeight` |
17
+ * | 圆角 | 只用 3 种:卡片 16 / 控件 10 / 小标签 6 | `radius` |
18
+ * | 间距 | 8pt 栅格:4 / 8 / 12 / 16 / 24 / 32 / 48 | `space` |
19
+ * | 描边或阴影 | **二选一,绝不叠加**;阴影只用一层极淡 | `border.width` / `shadow.card` |
20
+ * | 动效 | ≤ 200ms,`ease-out`,只用于状态变化 | `motion` |
21
+ *
22
+ * ## 落地方式(规范 §1「tokens 必须是代码里的唯一来源」)
23
+ *
24
+ * - `TOKENS` 是**扁平的 CSS 变量表**(`--tb-*` → 值),组件样式只能写 `var(--tb-*)`。
25
+ * - 每个组件把 tokens 注入自己的 shadow root(`:host{...}`),所以组件是**自带主题**的,
26
+ * 不依赖宿主页面先引一份全局 CSS。
27
+ * - `test/tokens.test.ts` 逐条断言上表的数字;`test/styles.test.ts` 断言组件样式里
28
+ * **没有** `#hex` / `rgb()` / `13px` / `200ms` 这类字面量,且用到的变量都已定义。
29
+ *
30
+ * ⚠️ 规范里没写死的两处(本文件是唯一来源,改这里就是改全套界面):
31
+ * 1. **语义色具体色值**(规范只要求"各 1 个、只用于状态")—— v0 取值见 `color.success/warning/danger`;
32
+ * 2. **描边宽度 1px**(规范说了"描边或阴影二选一",没给宽度)。
33
+ */
34
+ /** 灰阶(**恰好 5 级**,值与规范逐一相同;多一级就会被 tokens 测试拦下) */
35
+ export declare const gray: {
36
+ readonly 900: "#1D1D1F";
37
+ readonly 700: "#6E6E73";
38
+ readonly 500: "#8E8E93";
39
+ readonly 300: "#C7C7CC";
40
+ readonly 100: "#E5E5EA";
41
+ };
42
+ /** 颜色:1 主色系 + 1 强调色 + 3 语义色 */
43
+ export declare const color: {
44
+ readonly text: "#1D1D1F";
45
+ readonly textSecondary: "#6E6E73";
46
+ readonly textTertiary: "#8E8E93";
47
+ readonly border: "#C7C7CC";
48
+ readonly divider: "#E5E5EA";
49
+ readonly background: "#FFFFFF";
50
+ readonly surface: "#F5F5F7";
51
+ readonly accent: "#C4633C";
52
+ readonly onAccent: "#FFFFFF";
53
+ readonly success: "#1D8A5B";
54
+ readonly warning: "#B26A00";
55
+ readonly danger: "#C0392B";
56
+ };
57
+ /** 字号(**恰好 5 级**:标题 34 / 段落标题 22 / 正文 17 / 次要 15 / 注释 13) */
58
+ export declare const fontSize: {
59
+ readonly title: "34px";
60
+ readonly heading: "22px";
61
+ readonly body: "17px";
62
+ readonly secondary: "15px";
63
+ readonly caption: "13px";
64
+ };
65
+ /** 字重(只用两级) */
66
+ export declare const fontWeight: {
67
+ readonly regular: "400";
68
+ readonly semibold: "600";
69
+ };
70
+ /** 行高(固定 1.5,标题 1.2) */
71
+ export declare const lineHeight: {
72
+ readonly title: "1.2";
73
+ readonly body: "1.5";
74
+ };
75
+ /** 圆角(**只用 3 种**) */
76
+ export declare const radius: {
77
+ readonly card: "16px";
78
+ readonly control: "10px";
79
+ readonly tag: "6px";
80
+ };
81
+ /** 间距(8pt 栅格 + 4 的半步) */
82
+ export declare const space: {
83
+ readonly xxs: "4px";
84
+ readonly xs: "8px";
85
+ readonly sm: "12px";
86
+ readonly md: "16px";
87
+ readonly lg: "24px";
88
+ readonly xl: "32px";
89
+ readonly xxl: "48px";
90
+ };
91
+ /** 描边(与阴影**二选一**,不叠加) */
92
+ export declare const border: {
93
+ readonly width: "1px";
94
+ };
95
+ /** 阴影(只有一层,极淡) */
96
+ export declare const shadow: {
97
+ readonly card: "0 2px 8px rgba(0,0,0,.06)";
98
+ };
99
+ /** 动效(≤200ms,ease-out,只用于状态变化) */
100
+ export declare const motion: {
101
+ readonly fast: "120ms";
102
+ readonly base: "200ms";
103
+ readonly easing: "ease-out";
104
+ };
105
+ /** 字体(规范未指定字体族;数字与金额走等宽,见规范 §2.5) */
106
+ export declare const font: {
107
+ readonly family: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif";
108
+ readonly mono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
109
+ };
110
+ /**
111
+ * 扁平 CSS 变量表(`--tb-*` → 值)。**唯一来源**:组件只允许引用这里的键。
112
+ */
113
+ export declare const TOKENS: Readonly<Record<string, string>>;
114
+ /**
115
+ * tokens → CSS 文本。默认选择器 `:root`(宿主页面全局引一次);
116
+ * 组件内用 `tokensCss(':host')` 注入自己的 shadow root(组件自带主题,互不依赖)。
117
+ */
118
+ export declare function tokensCss(selector?: string): string;
119
+ /** tokens 的 `:root` 版本(宿主页面想在自己的壳层样式里用同一套变量时引它) */
120
+ export declare const TOKENS_CSS: string;
121
+ /** 组件 shadow root 用的 tokens(`:host` + 基础排版重置) */ export declare const HOST_STYLE: string;
122
+ /** 数字与金额用等宽字体(规范 §2.5:数字与金额右对齐、等宽、永远带单位) */
123
+ export declare const AMOUNT_STYLE = "font-family:var(--tb-font-mono);font-variant-numeric:tabular-nums;";
124
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,iDAAiD;AACjD,eAAO,MAAM,IAAI;;;;;;CAMP,CAAC;AAEX,+BAA+B;AAC/B,eAAO,MAAM,KAAK;;;;;;;;;;;;;CAaR,CAAC;AAEX,6DAA6D;AAC7D,eAAO,MAAM,QAAQ;;;;;;CAMX,CAAC;AAEX,eAAe;AACf,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,wBAAwB;AACxB,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,qBAAqB;AACrB,eAAO,MAAM,MAAM;;;;CAIT,CAAC;AAEX,yBAAyB;AACzB,eAAO,MAAM,KAAK;;;;;;;;CAQR,CAAC;AAEX,yBAAyB;AACzB,eAAO,MAAM,MAAM;;CAET,CAAC;AAEX,kBAAkB;AAClB,eAAO,MAAM,MAAM;;CAET,CAAC;AAEX,kCAAkC;AAClC,eAAO,MAAM,MAAM;;;;CAIT,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,IAAI;;;CAGP,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiDlD,CAAC;AAEH;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,SAAU,GAAG,MAAM,CAKpD;AAED,mDAAmD;AACnD,eAAO,MAAM,UAAU,QAAqB,CAAC;AAE7C,iDAAiD,CAAA,eAAO,MAAM,UAAU,QAW9D,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,YAAY,uEAAuE,CAAC"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Design tokens —— 本包**唯一允许出现视觉字面量的地方**。
3
+ *
4
+ * ## 出处
5
+ *
6
+ * 《TrustBase-设计风格规范-2026-09-22》§1「视觉 tokens(只允许用这些值,禁止魔法值)」:
7
+ *
8
+ * | 类别 | 规范要求 | 本文件对应 |
9
+ * |---|---|---|
10
+ * | 主色 | 1 个(默认 `#1D1D1F` 文字 / `#FFFFFF` 底 / `#F5F5F7` 分区底) | `color.text/background/surface` |
11
+ * | 强调色 | 1 个,只用于主操作与选中态(如 `#C4633C`) | `color.accent` |
12
+ * | 语义色 | 成功/警告/错误各 1 个,**只用于状态**不做装饰 | `color.success/warning/danger` |
13
+ * | 灰阶 | ≤ 5 级(`1D1D1F / 6E6E73 / 8E8E93 / C7C7CC / E5E5EA`) | `gray` |
14
+ * | 字号 | ≤ 5 级:34 / 22 / 17 / 15 / 13(正文 17,次要 15,注释 13) | `fontSize` |
15
+ * | 字重 | 只用 400 / 600 | `fontWeight` |
16
+ * | 行高 | 固定 1.5(标题 1.2) | `lineHeight` |
17
+ * | 圆角 | 只用 3 种:卡片 16 / 控件 10 / 小标签 6 | `radius` |
18
+ * | 间距 | 8pt 栅格:4 / 8 / 12 / 16 / 24 / 32 / 48 | `space` |
19
+ * | 描边或阴影 | **二选一,绝不叠加**;阴影只用一层极淡 | `border.width` / `shadow.card` |
20
+ * | 动效 | ≤ 200ms,`ease-out`,只用于状态变化 | `motion` |
21
+ *
22
+ * ## 落地方式(规范 §1「tokens 必须是代码里的唯一来源」)
23
+ *
24
+ * - `TOKENS` 是**扁平的 CSS 变量表**(`--tb-*` → 值),组件样式只能写 `var(--tb-*)`。
25
+ * - 每个组件把 tokens 注入自己的 shadow root(`:host{...}`),所以组件是**自带主题**的,
26
+ * 不依赖宿主页面先引一份全局 CSS。
27
+ * - `test/tokens.test.ts` 逐条断言上表的数字;`test/styles.test.ts` 断言组件样式里
28
+ * **没有** `#hex` / `rgb()` / `13px` / `200ms` 这类字面量,且用到的变量都已定义。
29
+ *
30
+ * ⚠️ 规范里没写死的两处(本文件是唯一来源,改这里就是改全套界面):
31
+ * 1. **语义色具体色值**(规范只要求"各 1 个、只用于状态")—— v0 取值见 `color.success/warning/danger`;
32
+ * 2. **描边宽度 1px**(规范说了"描边或阴影二选一",没给宽度)。
33
+ */
34
+ /** 灰阶(**恰好 5 级**,值与规范逐一相同;多一级就会被 tokens 测试拦下) */
35
+ export const gray = {
36
+ 900: '#1D1D1F',
37
+ 700: '#6E6E73',
38
+ 500: '#8E8E93',
39
+ 300: '#C7C7CC',
40
+ 100: '#E5E5EA',
41
+ };
42
+ /** 颜色:1 主色系 + 1 强调色 + 3 语义色 */
43
+ export const color = {
44
+ text: gray[900],
45
+ textSecondary: gray[700],
46
+ textTertiary: gray[500],
47
+ border: gray[300],
48
+ divider: gray[100],
49
+ background: '#FFFFFF',
50
+ surface: '#F5F5F7',
51
+ accent: '#C4633C',
52
+ onAccent: '#FFFFFF',
53
+ success: '#1D8A5B',
54
+ warning: '#B26A00',
55
+ danger: '#C0392B',
56
+ };
57
+ /** 字号(**恰好 5 级**:标题 34 / 段落标题 22 / 正文 17 / 次要 15 / 注释 13) */
58
+ export const fontSize = {
59
+ title: '34px',
60
+ heading: '22px',
61
+ body: '17px',
62
+ secondary: '15px',
63
+ caption: '13px',
64
+ };
65
+ /** 字重(只用两级) */
66
+ export const fontWeight = {
67
+ regular: '400',
68
+ semibold: '600',
69
+ };
70
+ /** 行高(固定 1.5,标题 1.2) */
71
+ export const lineHeight = {
72
+ title: '1.2',
73
+ body: '1.5',
74
+ };
75
+ /** 圆角(**只用 3 种**) */
76
+ export const radius = {
77
+ card: '16px',
78
+ control: '10px',
79
+ tag: '6px',
80
+ };
81
+ /** 间距(8pt 栅格 + 4 的半步) */
82
+ export const space = {
83
+ xxs: '4px',
84
+ xs: '8px',
85
+ sm: '12px',
86
+ md: '16px',
87
+ lg: '24px',
88
+ xl: '32px',
89
+ xxl: '48px',
90
+ };
91
+ /** 描边(与阴影**二选一**,不叠加) */
92
+ export const border = {
93
+ width: '1px',
94
+ };
95
+ /** 阴影(只有一层,极淡) */
96
+ export const shadow = {
97
+ card: '0 2px 8px rgba(0,0,0,.06)',
98
+ };
99
+ /** 动效(≤200ms,ease-out,只用于状态变化) */
100
+ export const motion = {
101
+ fast: '120ms',
102
+ base: '200ms',
103
+ easing: 'ease-out',
104
+ };
105
+ /** 字体(规范未指定字体族;数字与金额走等宽,见规范 §2.5) */
106
+ export const font = {
107
+ family: '-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Noto Sans SC", sans-serif',
108
+ mono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
109
+ };
110
+ /**
111
+ * 扁平 CSS 变量表(`--tb-*` → 值)。**唯一来源**:组件只允许引用这里的键。
112
+ */
113
+ export const TOKENS = Object.freeze({
114
+ '--tb-gray-900': gray[900],
115
+ '--tb-gray-700': gray[700],
116
+ '--tb-gray-500': gray[500],
117
+ '--tb-gray-300': gray[300],
118
+ '--tb-gray-100': gray[100],
119
+ '--tb-color-text': color.text,
120
+ '--tb-color-text-secondary': color.textSecondary,
121
+ '--tb-color-text-tertiary': color.textTertiary,
122
+ '--tb-color-border': color.border,
123
+ '--tb-color-divider': color.divider,
124
+ '--tb-color-background': color.background,
125
+ '--tb-color-surface': color.surface,
126
+ '--tb-color-accent': color.accent,
127
+ '--tb-color-on-accent': color.onAccent,
128
+ '--tb-color-success': color.success,
129
+ '--tb-color-warning': color.warning,
130
+ '--tb-color-danger': color.danger,
131
+ '--tb-font-family': font.family,
132
+ '--tb-font-mono': font.mono,
133
+ '--tb-font-size-title': fontSize.title,
134
+ '--tb-font-size-heading': fontSize.heading,
135
+ '--tb-font-size-body': fontSize.body,
136
+ '--tb-font-size-secondary': fontSize.secondary,
137
+ '--tb-font-size-caption': fontSize.caption,
138
+ '--tb-font-weight-regular': fontWeight.regular,
139
+ '--tb-font-weight-semibold': fontWeight.semibold,
140
+ '--tb-line-height-title': lineHeight.title,
141
+ '--tb-line-height-body': lineHeight.body,
142
+ '--tb-radius-card': radius.card,
143
+ '--tb-radius-control': radius.control,
144
+ '--tb-radius-tag': radius.tag,
145
+ '--tb-space-xxs': space.xxs,
146
+ '--tb-space-xs': space.xs,
147
+ '--tb-space-sm': space.sm,
148
+ '--tb-space-md': space.md,
149
+ '--tb-space-lg': space.lg,
150
+ '--tb-space-xl': space.xl,
151
+ '--tb-space-xxl': space.xxl,
152
+ '--tb-border-width': border.width,
153
+ '--tb-shadow-card': shadow.card,
154
+ '--tb-motion-fast': motion.fast,
155
+ '--tb-motion-base': motion.base,
156
+ '--tb-motion-easing': motion.easing,
157
+ });
158
+ /**
159
+ * tokens → CSS 文本。默认选择器 `:root`(宿主页面全局引一次);
160
+ * 组件内用 `tokensCss(':host')` 注入自己的 shadow root(组件自带主题,互不依赖)。
161
+ */
162
+ export function tokensCss(selector = ':root') {
163
+ const declarations = Object.entries(TOKENS)
164
+ .map(([name, value]) => `${name}:${value};`)
165
+ .join('');
166
+ return `${selector}{${declarations}}`;
167
+ }
168
+ /** tokens 的 `:root` 版本(宿主页面想在自己的壳层样式里用同一套变量时引它) */
169
+ export const TOKENS_CSS = tokensCss(':root');
170
+ /** 组件 shadow root 用的 tokens(`:host` + 基础排版重置) */ export const HOST_STYLE = [
171
+ tokensCss(':host'),
172
+ ':host{display:block;color:var(--tb-color-text);background:var(--tb-color-background);',
173
+ 'font-family:var(--tb-font-family);font-size:var(--tb-font-size-body);',
174
+ 'line-height:var(--tb-line-height-body);font-weight:var(--tb-font-weight-regular);',
175
+ '-webkit-font-smoothing:antialiased;}',
176
+ '*,*::before,*::after{box-sizing:border-box;}',
177
+ 'button{font:inherit;color:inherit;cursor:pointer;}',
178
+ 'input,textarea,select{font:inherit;color:inherit;}',
179
+ 'ul{margin:0;padding:0;list-style:none;}',
180
+ 'p{margin:0;}',
181
+ ].join('');
182
+ /** 数字与金额用等宽字体(规范 §2.5:数字与金额右对齐、等宽、永远带单位) */
183
+ export const AMOUNT_STYLE = 'font-family:var(--tb-font-mono);font-variant-numeric:tabular-nums;';
184
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * 视图层最小格式化 —— **零依赖、纯函数**,口径与 `@trustbase/shop` 的模型层一致
3
+ * (`shop` 不能是本包的运行时依赖:UI 组件要零依赖;两边口径由交叉验证测试锁着,
4
+ * 见 `test/format.test.ts` 里直接 import `../../shop/src/index` 比对的断言)。
5
+ *
6
+ * 只放"界面上要显示什么",不放任何业务判断(业务判断在 `@trustbase/shop`)。
7
+ */
8
+ /** 金额的两段式(数字 + 单位分开渲染:数字走等宽、单位走次要色,见规范 §2.5) */
9
+ export interface AmountParts {
10
+ /** 例:`12.30` */
11
+ value: string;
12
+ /** 例:`TCT` */
13
+ unit: string;
14
+ }
15
+ /**
16
+ * microTCT 整数字符串 → `{ value, unit }`(最少 2 位小数、最多 6 位、去掉多余的 0)。
17
+ * `"12300000"` → `{ value: "12.30", unit: "TCT" }`。
18
+ */
19
+ export declare function formatAmountParts(microTct: string, unit?: string): AmountParts;
20
+ /** microTCT → `"12.30 TCT"`(金额永远带单位) */
21
+ export declare function formatAmount(microTct: string, unit?: string): string;
22
+ /** 单价 × 数量的合计(整数运算,无浮点;只看金额,不做任何校验) */
23
+ export declare function multiplyAmounts(pricePerUnit: string, quantity: string | number): string;
24
+ /** 多行金额合计 */
25
+ export declare function sumAmounts(amounts: readonly string[]): string;
26
+ /** 地址缩写(中间省略;完整地址由 `title` 属性承载,界面不塞一屏字符) */
27
+ export declare function shortAddress(address: string, head?: number, tail?: number): string;
28
+ /** 订单状态 → 界面文案(状态值口径见 `@trustbase/shop` 的 `ORDER_STATUS`,测试比对过) */
29
+ export declare const ORDER_STATUS_LABELS: Readonly<Record<string, string>>;
30
+ export declare function orderStatusLabel(status: string): string;
31
+ /** 状态文案(三种状态都要有,且说人话 —— 设计规范 §2.4) */
32
+ export declare const STATE_TEXT: Readonly<{
33
+ loading: "正在加载…";
34
+ error: "服务暂时不可用,请刷新重试";
35
+ empty: "这里还没有内容";
36
+ }>;
37
+ /** 商品描述行:规格数 + 库存(能用一个列表说清就不上卡片 —— 规范 §2.8) */
38
+ export declare function goodsMetaLine(skuCount: number, stock: number): string;
39
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,gBAAgB;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAQ,GAAG,WAAW,CAS7E;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAQ,GAAG,MAAM,CAGnE;AAED,uCAAuC;AACvC,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAIvF;AAED,aAAa;AACb,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI7D;AAED,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,EAAE,IAAI,SAAI,GAAG,MAAM,CAIzE;AAED,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO/D,CAAC;AAEH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,sCAAsC;AACtC,eAAO,MAAM,UAAU;;;;EAIrB,CAAC;AAEH,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrE"}
package/dist/format.js ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * 视图层最小格式化 —— **零依赖、纯函数**,口径与 `@trustbase/shop` 的模型层一致
4
+ * (`shop` 不能是本包的运行时依赖:UI 组件要零依赖;两边口径由交叉验证测试锁着,
5
+ * 见 `test/format.test.ts` 里直接 import `../../shop/src/index` 比对的断言)。
6
+ *
7
+ * 只放"界面上要显示什么",不放任何业务判断(业务判断在 `@trustbase/shop`)。
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.STATE_TEXT = exports.ORDER_STATUS_LABELS = void 0;
11
+ exports.formatAmountParts = formatAmountParts;
12
+ exports.formatAmount = formatAmount;
13
+ exports.multiplyAmounts = multiplyAmounts;
14
+ exports.sumAmounts = sumAmounts;
15
+ exports.shortAddress = shortAddress;
16
+ exports.orderStatusLabel = orderStatusLabel;
17
+ exports.goodsMetaLine = goodsMetaLine;
18
+ /** 1 TCT = 1_000_000 microTCT / utct(链上 `TCT_DECIMALS = 6`) */
19
+ const MICRO_PER_TCT = BigInt(1000000);
20
+ const DECIMAL_INTEGER_RE = /^(0|[1-9][0-9]*)$/;
21
+ /**
22
+ * microTCT 整数字符串 → `{ value, unit }`(最少 2 位小数、最多 6 位、去掉多余的 0)。
23
+ * `"12300000"` → `{ value: "12.30", unit: "TCT" }`。
24
+ */
25
+ function formatAmountParts(microTct, unit = 'TCT') {
26
+ const text = String(microTct ?? '').trim();
27
+ if (!DECIMAL_INTEGER_RE.test(text))
28
+ return { value: '—', unit };
29
+ const micro = BigInt(text);
30
+ const whole = micro / MICRO_PER_TCT;
31
+ const frac = micro % MICRO_PER_TCT;
32
+ if (frac === BigInt(0))
33
+ return { value: `${whole.toString()}.00`, unit };
34
+ const digits = frac.toString().padStart(6, '0').replace(/0+$/, '');
35
+ return { value: `${whole.toString()}.${digits.padEnd(2, '0')}`, unit };
36
+ }
37
+ /** microTCT → `"12.30 TCT"`(金额永远带单位) */
38
+ function formatAmount(microTct, unit = 'TCT') {
39
+ const parts = formatAmountParts(microTct, unit);
40
+ return `${parts.value} ${parts.unit}`;
41
+ }
42
+ /** 单价 × 数量的合计(整数运算,无浮点;只看金额,不做任何校验) */
43
+ function multiplyAmounts(pricePerUnit, quantity) {
44
+ const price = DECIMAL_INTEGER_RE.test(String(pricePerUnit)) ? BigInt(String(pricePerUnit)) : BigInt(0);
45
+ const qty = DECIMAL_INTEGER_RE.test(String(quantity)) ? BigInt(String(quantity)) : BigInt(0);
46
+ return (price * qty).toString();
47
+ }
48
+ /** 多行金额合计 */
49
+ function sumAmounts(amounts) {
50
+ return amounts
51
+ .reduce((sum, amount) => sum + (DECIMAL_INTEGER_RE.test(amount) ? BigInt(amount) : BigInt(0)), BigInt(0))
52
+ .toString();
53
+ }
54
+ /** 地址缩写(中间省略;完整地址由 `title` 属性承载,界面不塞一屏字符) */
55
+ function shortAddress(address, head = 10, tail = 6) {
56
+ const text = String(address ?? '');
57
+ if (text.length <= head + tail + 1)
58
+ return text;
59
+ return `${text.slice(0, head)}…${text.slice(-tail)}`;
60
+ }
61
+ /** 订单状态 → 界面文案(状态值口径见 `@trustbase/shop` 的 `ORDER_STATUS`,测试比对过) */
62
+ exports.ORDER_STATUS_LABELS = Object.freeze({
63
+ PENDING: '待支付',
64
+ PAID: '已支付',
65
+ SHIPPED: '已发货',
66
+ CONFIRMED: '已确认收货',
67
+ CANCELLED: '已取消',
68
+ DISPUTED: '申诉中',
69
+ });
70
+ function orderStatusLabel(status) {
71
+ return exports.ORDER_STATUS_LABELS[status] ?? String(status ?? '');
72
+ }
73
+ /** 状态文案(三种状态都要有,且说人话 —— 设计规范 §2.4) */
74
+ exports.STATE_TEXT = Object.freeze({
75
+ loading: '正在加载…',
76
+ error: '服务暂时不可用,请刷新重试',
77
+ empty: '这里还没有内容',
78
+ });
79
+ /** 商品描述行:规格数 + 库存(能用一个列表说清就不上卡片 —— 规范 §2.8) */
80
+ function goodsMetaLine(skuCount, stock) {
81
+ const specText = skuCount > 1 ? `${skuCount} 个规格` : '单一规格';
82
+ return stock > 0 ? `${specText} · 剩 ${stock} 件` : `${specText} · 已售罄`;
83
+ }
84
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * `@trustbase/shop-ui` —— TrustBase 店铺界面组件(**框架无关 Web Components**)。
3
+ *
4
+ * ## 四个组件(名字与契约都是冻结的)
5
+ *
6
+ * | 元素 | 干什么 | 关键出参事件 |
7
+ * |---|---|---|
8
+ * | `<tb-goods-list>` | 商品列表 | `tb:goods-select` |
9
+ * | `<tb-goods-detail>` | 详情 + 规格选择 | `tb:sku-change` / `tb:goods-buy` |
10
+ * | `<tb-order-form>` | 下单表单(产出**意愿 + memo**) | `tb:order-submit` / `tb:order-error` |
11
+ * | `<tb-account-panel>` | 我的账户:地址/余额/订单占位 | `tb:account-action` |
12
+ *
13
+ * ## 三条硬纪律(都有测试守着)
14
+ *
15
+ * 1. **零运行时依赖**:自己写 Custom Elements,不引任何第三方 UI 框架/库;
16
+ * 连 `@trustbase/shop` 都不 import(意愿口径由宿主**注入** `intentBuilder`,见 `tb-order-form`)。
17
+ * 2. **样式只能引用 tokens**:`src/tokens.ts` 是唯一允许出现视觉字面量的文件,
18
+ * 组件样式里出现 `#4f8ef7` / `13px` / `200ms` 这类字面量 → `test/styles.test.ts` 失败。
19
+ * 3. **不持私钥、不签名**:组件只渲染 + 抛事件;下单只产出"意愿 + memo",
20
+ * 签名由调用方交给商户守护进程(`test/isomorphic.test.ts` 扫源码禁止签名相关标识符)。
21
+ *
22
+ * ## 用法
23
+ *
24
+ * ```html
25
+ * <script type="module">
26
+ * import { registerShopUi, TOKENS_CSS } from '../dist/esm/index.js';
27
+ * registerShopUi();
28
+ * // 想在页面(light DOM)也拿到 tokens(例如自己的壳层样式):
29
+ * document.head.append(Object.assign(document.createElement('style'), { textContent: TOKENS_CSS }));
30
+ * </script>
31
+ * <tb-goods-list data-goods='[{"goods_id":"g1","title":"茶","skus":[...]}]'></tb-goods-list>
32
+ * ```
33
+ *
34
+ * 移动优先:默认 375 宽可用(`packages/shop-ui/demo/index.html` 就是按 375 设计的演示页)。
35
+ */
36
+ export { AMOUNT_STYLE, HOST_STYLE, TOKENS, TOKENS_CSS, border, color, font, fontSize, fontWeight, gray, lineHeight, motion, radius, shadow, space, tokensCss, } from './tokens.js';
37
+ export { SHOP_UI_EVENTS, STATE_STYLE, TbElement, escapeHtml, stateBlock, type JsonAttr, type UIState, } from './base.js';
38
+ export { ORDER_STATUS_LABELS, STATE_TEXT, formatAmount, formatAmountParts, goodsMetaLine, multiplyAmounts, orderStatusLabel, shortAddress, sumAmounts, type AmountParts, } from './format.js';
39
+ export { TbGoodsList, type GoodsView } from './components/goods-list.js';
40
+ export { TbGoodsDetail, type GoodsDetailView } from './components/goods-detail.js';
41
+ export { TbOrderForm, type ContactView, type IntentBuilder, type OrderLineView, type OrderSubmitDetail, } from './components/order-form.js';
42
+ export { TbAccountPanel, type AccountOrderView, type AccountView } from './components/account-panel.js';
43
+ export { SHOP_UI_ELEMENTS, registerShopUi, shopUiElementNames, type ShopUiTag } from './register.js';
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EACL,YAAY,EACZ,UAAU,EACV,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,UAAU,EACV,MAAM,EACN,MAAM,EACN,MAAM,EACN,KAAK,EACL,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,WAAW,EACX,SAAS,EACT,UAAU,EACV,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,OAAO,GACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EACL,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAExG,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * `@trustbase/shop-ui` —— TrustBase 店铺界面组件(**框架无关 Web Components**)。
4
+ *
5
+ * ## 四个组件(名字与契约都是冻结的)
6
+ *
7
+ * | 元素 | 干什么 | 关键出参事件 |
8
+ * |---|---|---|
9
+ * | `<tb-goods-list>` | 商品列表 | `tb:goods-select` |
10
+ * | `<tb-goods-detail>` | 详情 + 规格选择 | `tb:sku-change` / `tb:goods-buy` |
11
+ * | `<tb-order-form>` | 下单表单(产出**意愿 + memo**) | `tb:order-submit` / `tb:order-error` |
12
+ * | `<tb-account-panel>` | 我的账户:地址/余额/订单占位 | `tb:account-action` |
13
+ *
14
+ * ## 三条硬纪律(都有测试守着)
15
+ *
16
+ * 1. **零运行时依赖**:自己写 Custom Elements,不引任何第三方 UI 框架/库;
17
+ * 连 `@trustbase/shop` 都不 import(意愿口径由宿主**注入** `intentBuilder`,见 `tb-order-form`)。
18
+ * 2. **样式只能引用 tokens**:`src/tokens.ts` 是唯一允许出现视觉字面量的文件,
19
+ * 组件样式里出现 `#4f8ef7` / `13px` / `200ms` 这类字面量 → `test/styles.test.ts` 失败。
20
+ * 3. **不持私钥、不签名**:组件只渲染 + 抛事件;下单只产出"意愿 + memo",
21
+ * 签名由调用方交给商户守护进程(`test/isomorphic.test.ts` 扫源码禁止签名相关标识符)。
22
+ *
23
+ * ## 用法
24
+ *
25
+ * ```html
26
+ * <script type="module">
27
+ * import { registerShopUi, TOKENS_CSS } from '../dist/esm/index.js';
28
+ * registerShopUi();
29
+ * // 想在页面(light DOM)也拿到 tokens(例如自己的壳层样式):
30
+ * document.head.append(Object.assign(document.createElement('style'), { textContent: TOKENS_CSS }));
31
+ * </script>
32
+ * <tb-goods-list data-goods='[{"goods_id":"g1","title":"茶","skus":[...]}]'></tb-goods-list>
33
+ * ```
34
+ *
35
+ * 移动优先:默认 375 宽可用(`packages/shop-ui/demo/index.html` 就是按 375 设计的演示页)。
36
+ */
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.shopUiElementNames = exports.registerShopUi = exports.SHOP_UI_ELEMENTS = exports.TbAccountPanel = exports.TbOrderForm = exports.TbGoodsDetail = exports.TbGoodsList = exports.sumAmounts = exports.shortAddress = exports.orderStatusLabel = exports.multiplyAmounts = exports.goodsMetaLine = exports.formatAmountParts = exports.formatAmount = exports.STATE_TEXT = exports.ORDER_STATUS_LABELS = exports.stateBlock = exports.escapeHtml = exports.TbElement = exports.STATE_STYLE = exports.SHOP_UI_EVENTS = exports.tokensCss = exports.space = exports.shadow = exports.radius = exports.motion = exports.lineHeight = exports.gray = exports.fontWeight = exports.fontSize = exports.font = exports.color = exports.border = exports.TOKENS_CSS = exports.TOKENS = exports.HOST_STYLE = exports.AMOUNT_STYLE = void 0;
39
+ var tokens_js_1 = require("./tokens.js");
40
+ Object.defineProperty(exports, "AMOUNT_STYLE", { enumerable: true, get: function () { return tokens_js_1.AMOUNT_STYLE; } });
41
+ Object.defineProperty(exports, "HOST_STYLE", { enumerable: true, get: function () { return tokens_js_1.HOST_STYLE; } });
42
+ Object.defineProperty(exports, "TOKENS", { enumerable: true, get: function () { return tokens_js_1.TOKENS; } });
43
+ Object.defineProperty(exports, "TOKENS_CSS", { enumerable: true, get: function () { return tokens_js_1.TOKENS_CSS; } });
44
+ Object.defineProperty(exports, "border", { enumerable: true, get: function () { return tokens_js_1.border; } });
45
+ Object.defineProperty(exports, "color", { enumerable: true, get: function () { return tokens_js_1.color; } });
46
+ Object.defineProperty(exports, "font", { enumerable: true, get: function () { return tokens_js_1.font; } });
47
+ Object.defineProperty(exports, "fontSize", { enumerable: true, get: function () { return tokens_js_1.fontSize; } });
48
+ Object.defineProperty(exports, "fontWeight", { enumerable: true, get: function () { return tokens_js_1.fontWeight; } });
49
+ Object.defineProperty(exports, "gray", { enumerable: true, get: function () { return tokens_js_1.gray; } });
50
+ Object.defineProperty(exports, "lineHeight", { enumerable: true, get: function () { return tokens_js_1.lineHeight; } });
51
+ Object.defineProperty(exports, "motion", { enumerable: true, get: function () { return tokens_js_1.motion; } });
52
+ Object.defineProperty(exports, "radius", { enumerable: true, get: function () { return tokens_js_1.radius; } });
53
+ Object.defineProperty(exports, "shadow", { enumerable: true, get: function () { return tokens_js_1.shadow; } });
54
+ Object.defineProperty(exports, "space", { enumerable: true, get: function () { return tokens_js_1.space; } });
55
+ Object.defineProperty(exports, "tokensCss", { enumerable: true, get: function () { return tokens_js_1.tokensCss; } });
56
+ var base_js_1 = require("./base.js");
57
+ Object.defineProperty(exports, "SHOP_UI_EVENTS", { enumerable: true, get: function () { return base_js_1.SHOP_UI_EVENTS; } });
58
+ Object.defineProperty(exports, "STATE_STYLE", { enumerable: true, get: function () { return base_js_1.STATE_STYLE; } });
59
+ Object.defineProperty(exports, "TbElement", { enumerable: true, get: function () { return base_js_1.TbElement; } });
60
+ Object.defineProperty(exports, "escapeHtml", { enumerable: true, get: function () { return base_js_1.escapeHtml; } });
61
+ Object.defineProperty(exports, "stateBlock", { enumerable: true, get: function () { return base_js_1.stateBlock; } });
62
+ var format_js_1 = require("./format.js");
63
+ Object.defineProperty(exports, "ORDER_STATUS_LABELS", { enumerable: true, get: function () { return format_js_1.ORDER_STATUS_LABELS; } });
64
+ Object.defineProperty(exports, "STATE_TEXT", { enumerable: true, get: function () { return format_js_1.STATE_TEXT; } });
65
+ Object.defineProperty(exports, "formatAmount", { enumerable: true, get: function () { return format_js_1.formatAmount; } });
66
+ Object.defineProperty(exports, "formatAmountParts", { enumerable: true, get: function () { return format_js_1.formatAmountParts; } });
67
+ Object.defineProperty(exports, "goodsMetaLine", { enumerable: true, get: function () { return format_js_1.goodsMetaLine; } });
68
+ Object.defineProperty(exports, "multiplyAmounts", { enumerable: true, get: function () { return format_js_1.multiplyAmounts; } });
69
+ Object.defineProperty(exports, "orderStatusLabel", { enumerable: true, get: function () { return format_js_1.orderStatusLabel; } });
70
+ Object.defineProperty(exports, "shortAddress", { enumerable: true, get: function () { return format_js_1.shortAddress; } });
71
+ Object.defineProperty(exports, "sumAmounts", { enumerable: true, get: function () { return format_js_1.sumAmounts; } });
72
+ var goods_list_js_1 = require("./components/goods-list.js");
73
+ Object.defineProperty(exports, "TbGoodsList", { enumerable: true, get: function () { return goods_list_js_1.TbGoodsList; } });
74
+ var goods_detail_js_1 = require("./components/goods-detail.js");
75
+ Object.defineProperty(exports, "TbGoodsDetail", { enumerable: true, get: function () { return goods_detail_js_1.TbGoodsDetail; } });
76
+ var order_form_js_1 = require("./components/order-form.js");
77
+ Object.defineProperty(exports, "TbOrderForm", { enumerable: true, get: function () { return order_form_js_1.TbOrderForm; } });
78
+ var account_panel_js_1 = require("./components/account-panel.js");
79
+ Object.defineProperty(exports, "TbAccountPanel", { enumerable: true, get: function () { return account_panel_js_1.TbAccountPanel; } });
80
+ var register_js_1 = require("./register.js");
81
+ Object.defineProperty(exports, "SHOP_UI_ELEMENTS", { enumerable: true, get: function () { return register_js_1.SHOP_UI_ELEMENTS; } });
82
+ Object.defineProperty(exports, "registerShopUi", { enumerable: true, get: function () { return register_js_1.registerShopUi; } });
83
+ Object.defineProperty(exports, "shopUiElementNames", { enumerable: true, get: function () { return register_js_1.shopUiElementNames; } });
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;;;AAEH,yCAiBqB;AAhBnB,yGAAA,YAAY,OAAA;AACZ,uGAAA,UAAU,OAAA;AACV,mGAAA,MAAM,OAAA;AACN,uGAAA,UAAU,OAAA;AACV,mGAAA,MAAM,OAAA;AACN,kGAAA,KAAK,OAAA;AACL,iGAAA,IAAI,OAAA;AACJ,qGAAA,QAAQ,OAAA;AACR,uGAAA,UAAU,OAAA;AACV,iGAAA,IAAI,OAAA;AACJ,uGAAA,UAAU,OAAA;AACV,mGAAA,MAAM,OAAA;AACN,mGAAA,MAAM,OAAA;AACN,mGAAA,MAAM,OAAA;AACN,kGAAA,KAAK,OAAA;AACL,sGAAA,SAAS,OAAA;AAGX,qCAQmB;AAPjB,yGAAA,cAAc,OAAA;AACd,sGAAA,WAAW,OAAA;AACX,oGAAA,SAAS,OAAA;AACT,qGAAA,UAAU,OAAA;AACV,qGAAA,UAAU,OAAA;AAKZ,yCAWqB;AAVnB,gHAAA,mBAAmB,OAAA;AACnB,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;AACZ,8GAAA,iBAAiB,OAAA;AACjB,0GAAA,aAAa,OAAA;AACb,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,yGAAA,YAAY,OAAA;AACZ,uGAAA,UAAU,OAAA;AAIZ,4DAAyE;AAAhE,4GAAA,WAAW,OAAA;AACpB,gEAAmF;AAA1E,gHAAA,aAAa,OAAA;AACtB,4DAMoC;AALlC,4GAAA,WAAW,OAAA;AAMb,kEAAwG;AAA/F,kHAAA,cAAc,OAAA;AAEvB,6CAAqG;AAA5F,+GAAA,gBAAgB,OAAA;AAAE,6GAAA,cAAc,OAAA;AAAE,iHAAA,kBAAkB,OAAA"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 注册四个自定义元素。
3
+ *
4
+ * 单独一个入口(`@trustbase/shop-ui/register`)的原因:**注册是有副作用的一步**
5
+ * (`customElements.define`),而组件类本身可以安全地被 import(SSR / 测试 / 只取类型)。
6
+ * 宿主想控制注册时机(例如等 tokens 主题就绪、或只想注册用到的那几个)时,
7
+ * 引 `index` 而不调 `registerShopUi()` 即可。
8
+ *
9
+ * `registerShopUi()` 是**幂等**的:重复调用不会抛 `already defined`。
10
+ */
11
+ import { TbAccountPanel } from './components/account-panel.js';
12
+ import { TbGoodsDetail } from './components/goods-detail.js';
13
+ import { TbGoodsList } from './components/goods-list.js';
14
+ import { TbOrderForm } from './components/order-form.js';
15
+ import { TbElement } from './base.js';
16
+ /** 元素名 → 组件类(元素名是**冻结的契约**:改名字等于破坏宿主的 HTML) */
17
+ export declare const SHOP_UI_ELEMENTS: Readonly<{
18
+ 'tb-goods-list': typeof TbGoodsList;
19
+ 'tb-goods-detail': typeof TbGoodsDetail;
20
+ 'tb-order-form': typeof TbOrderForm;
21
+ 'tb-account-panel': typeof TbAccountPanel;
22
+ }>;
23
+ export type ShopUiTag = keyof typeof SHOP_UI_ELEMENTS;
24
+ /**
25
+ * 注册全部自定义元素(浏览器环境)。
26
+ * 在 Node/SSR 里调用是**安全空操作**(没有 `customElements` 就直接返回),
27
+ * 这样宿主可以无脑在最外层调一次。
28
+ */
29
+ export declare function registerShopUi(): void;
30
+ /** 已注册的元素名清单(宿主做能力探测/文档用) */
31
+ export declare function shopUiElementNames(): ShopUiTag[];
32
+ export { TbElement };
33
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,+CAA+C;AAC/C,eAAO,MAAM,gBAAgB;;;;;EAK3B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,IAAI,CASrC;AAED,6BAA6B;AAC7B,wBAAgB,kBAAkB,IAAI,SAAS,EAAE,CAEhD;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}