@omit-design/preset-mobile 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 (57) hide show
  1. package/PATTERNS.md +134 -0
  2. package/README.md +29 -0
  3. package/catalog.tsx +365 -0
  4. package/components/OmAppBar.tsx +63 -0
  5. package/components/OmButton.tsx +41 -0
  6. package/components/OmCard.tsx +28 -0
  7. package/components/OmCouponCard.tsx +71 -0
  8. package/components/OmDialog.tsx +96 -0
  9. package/components/OmEmptyState.tsx +32 -0
  10. package/components/OmHeader.tsx +21 -0
  11. package/components/OmInput.tsx +38 -0
  12. package/components/OmListRow.tsx +30 -0
  13. package/components/OmMenuCard.tsx +47 -0
  14. package/components/OmNumpad.tsx +82 -0
  15. package/components/OmOrderFooter.tsx +78 -0
  16. package/components/OmPage.tsx +30 -0
  17. package/components/OmProductCard.tsx +75 -0
  18. package/components/OmSearchBar.tsx +51 -0
  19. package/components/OmSelect.tsx +47 -0
  20. package/components/OmSettingRow.tsx +95 -0
  21. package/components/OmSheet.tsx +49 -0
  22. package/components/OmStatCard.tsx +30 -0
  23. package/components/OmTabBar.tsx +26 -0
  24. package/components/OmTag.tsx +28 -0
  25. package/components/index.ts +30 -0
  26. package/components/inspect-attrs.ts +34 -0
  27. package/components/om-app-bar.css +83 -0
  28. package/components/om-coupon-card.css +107 -0
  29. package/components/om-dialog.css +81 -0
  30. package/components/om-empty-state.css +55 -0
  31. package/components/om-input.css +43 -0
  32. package/components/om-menu-card.css +68 -0
  33. package/components/om-numpad.css +49 -0
  34. package/components/om-order-footer.css +121 -0
  35. package/components/om-page.css +43 -0
  36. package/components/om-product-card.css +124 -0
  37. package/components/om-search-bar.css +39 -0
  38. package/components/om-select.css +28 -0
  39. package/components/om-setting-row.css +82 -0
  40. package/components/om-sheet.css +73 -0
  41. package/components/om-stat-card.css +40 -0
  42. package/components/om-tag.css +51 -0
  43. package/index.ts +14 -0
  44. package/package.json +48 -0
  45. package/preset.manifest.ts +62 -0
  46. package/templates/dashboard.tmpl.tsx +90 -0
  47. package/templates/detail-view.tmpl.tsx +60 -0
  48. package/templates/dialog-view.tmpl.tsx +34 -0
  49. package/templates/form-view.tmpl.tsx +52 -0
  50. package/templates/list-view.tmpl.tsx +58 -0
  51. package/templates/sheet-action.tmpl.tsx +52 -0
  52. package/templates/tab-view.tmpl.tsx +51 -0
  53. package/templates/welcome-view.tmpl.tsx +38 -0
  54. package/theme/baseline.ts +32 -0
  55. package/theme/presets/light.ts +8 -0
  56. package/theme/variables.css +183 -0
  57. package/tokens/index.ts +51 -0
@@ -0,0 +1,183 @@
1
+ /*
2
+ * @omit-design/preset-mobile — Token source of truth
3
+ *
4
+ * 全局 token 的唯一权威来源。theme-editor 导出时会写回此文件。
5
+ * 业务页面与 Om* 组件**禁止**使用字面量颜色/间距,必须通过这里的 CSS 变量。
6
+ */
7
+
8
+ :root {
9
+ /* ===== 字体(与 Figma 对齐:Roboto 优先 + MiSans + 系统栈回退) ===== */
10
+ --ion-font-family: "Roboto", "MiSans", -apple-system, BlinkMacSystemFont,
11
+ "PingFang SC", "Noto Sans SC", "Microsoft YaHei", system-ui, sans-serif;
12
+
13
+ /* ===== Ionic 语义色(来自 Figma Schemes) ===== */
14
+ /* Schemes/Primary #0d8ce9 */
15
+ --ion-color-primary: #0d8ce9;
16
+ --ion-color-primary-rgb: 13, 140, 233;
17
+ --ion-color-primary-contrast: #ffffff;
18
+ --ion-color-primary-contrast-rgb: 255, 255, 255;
19
+ --ion-color-primary-shade: #0b7bcd;
20
+ --ion-color-primary-tint: #2598eb;
21
+
22
+ /* Palette/Teal/50 #00CFFF */
23
+ --ion-color-secondary: #00cfff;
24
+ --ion-color-secondary-rgb: 0, 207, 255;
25
+ --ion-color-secondary-contrast: #000000;
26
+ --ion-color-secondary-contrast-rgb: 0, 0, 0;
27
+ --ion-color-secondary-shade: #00b6e0;
28
+ --ion-color-secondary-tint: #1ad4ff;
29
+
30
+ /* Schemes/Tertiary #e56e35 */
31
+ --ion-color-tertiary: #e56e35;
32
+ --ion-color-tertiary-rgb: 229, 110, 53;
33
+ --ion-color-tertiary-contrast: #ffffff;
34
+ --ion-color-tertiary-contrast-rgb: 255, 255, 255;
35
+ --ion-color-tertiary-shade: #ca612f;
36
+ --ion-color-tertiary-tint: #e87d49;
37
+
38
+ /* Schemes/success #22c55e */
39
+ --ion-color-success: #22c55e;
40
+ --ion-color-success-rgb: 34, 197, 94;
41
+ --ion-color-success-contrast: #ffffff;
42
+ --ion-color-success-contrast-rgb: 255, 255, 255;
43
+ --ion-color-success-shade: #1eae53;
44
+ --ion-color-success-tint: #38cb6e;
45
+
46
+ /* Warning — Figma 未单列 warning,沿用 tertiary 橙作警示色(失败弹窗也走这个) */
47
+ --ion-color-warning: #e56e35;
48
+ --ion-color-warning-rgb: 229, 110, 53;
49
+ --ion-color-warning-contrast: #ffffff;
50
+ --ion-color-warning-contrast-rgb: 255, 255, 255;
51
+ --ion-color-warning-shade: #ca612f;
52
+ --ion-color-warning-tint: #e87d49;
53
+
54
+ /* Schemes/Error #da342e(用作表单内联错误) */
55
+ --ion-color-danger: #da342e;
56
+ --ion-color-danger-rgb: 218, 52, 46;
57
+ --ion-color-danger-contrast: #ffffff;
58
+ --ion-color-danger-contrast-rgb: 255, 255, 255;
59
+ --ion-color-danger-shade: #c02e29;
60
+ --ion-color-danger-tint: #dd4943;
61
+
62
+ /* Neutral/Dark/Darkest #1F2024 */
63
+ --ion-color-dark: #1f2024;
64
+ --ion-color-dark-rgb: 31, 32, 36;
65
+ --ion-color-dark-contrast: #ffffff;
66
+ --ion-color-dark-contrast-rgb: 255, 255, 255;
67
+ --ion-color-dark-shade: #1b1c1f;
68
+ --ion-color-dark-tint: #35363a;
69
+
70
+ /* Schemes/On Background #90909a */
71
+ --ion-color-medium: #90909a;
72
+ --ion-color-medium-rgb: 144, 144, 154;
73
+ --ion-color-medium-contrast: #ffffff;
74
+ --ion-color-medium-contrast-rgb: 255, 255, 255;
75
+ --ion-color-medium-shade: #7f7f88;
76
+ --ion-color-medium-tint: #9b9ba4;
77
+
78
+ /* Schemes/Outline #dbd9e0(用作最浅背景/分割线 fill) */
79
+ --ion-color-light: #dbd9e0;
80
+ --ion-color-light-rgb: 219, 217, 224;
81
+ --ion-color-light-contrast: #000000;
82
+ --ion-color-light-contrast-rgb: 0, 0, 0;
83
+ --ion-color-light-shade: #c1bfc5;
84
+ --ion-color-light-tint: #dfddc5;
85
+
86
+ /* ===== Ionic 结构色 ===== */
87
+ /* Schemes/Surface Container Lowest #ffffff */
88
+ --ion-background-color: #ffffff;
89
+ --ion-background-color-rgb: 255, 255, 255;
90
+ /* Schemes/On Surface Variant #22232b */
91
+ --ion-text-color: #22232b;
92
+ --ion-text-color-rgb: 34, 35, 43;
93
+ --ion-toolbar-background: #ffffff;
94
+ --ion-tab-bar-background: #ffffff;
95
+
96
+ /* ===== 品牌扩展色(Figma Palette) ===== */
97
+ --om-color-brand-blue-50: #0f62fe;
98
+ --om-color-brand-blue-80: #00147c;
99
+ --om-color-brand-blue-90: #020f47;
100
+ --om-color-brand-teal-50: #00cfff;
101
+ /* Schemes/Outline Variant #41424b — 次级分割线 */
102
+ --om-color-outline-variant: #41424b;
103
+
104
+ /* ===== 遮罩 ===== */
105
+ /* Figma Musk Color #000000cc */
106
+ --om-overlay-scrim: rgba(0, 0, 0, 0.8);
107
+
108
+ /* ===== 欢迎 / onboarding 渐变背景 ===== */
109
+ --om-gradient-onboarding-top: #f5f9ff;
110
+ --om-gradient-onboarding-mid: #e8f2ff;
111
+ --om-gradient-onboarding-bottom: #c8dfff;
112
+ --om-gradient-onboarding: linear-gradient(
113
+ 180deg,
114
+ var(--om-gradient-onboarding-top) 0%,
115
+ var(--om-gradient-onboarding-mid) 50%,
116
+ var(--om-gradient-onboarding-bottom) 100%
117
+ );
118
+
119
+ /* ===== POS 自定义间距 ===== */
120
+ --om-spacing-xs: 4px;
121
+ --om-spacing-sm: 8px;
122
+ --om-spacing-md: 12px;
123
+ --om-spacing-lg: 16px;
124
+ --om-spacing-xl: 24px;
125
+ --om-spacing-2xl: 32px;
126
+
127
+ /* ===== 圆角(Figma Border/Radius) ===== */
128
+ --om-radius-sm: 4px; /* Extra-small */
129
+ --om-radius-md: 8px; /* Small */
130
+ --om-radius-lg: 12px;
131
+ --om-radius-xl: 16px; /* Large */
132
+ --om-radius-2xl: 28px; /* Extra-large */
133
+ --om-radius-full: 9999px;
134
+
135
+ /* ===== 字号(Figma Type scale) ===== */
136
+ --om-font-size-xs: 12px; /* body/small */
137
+ --om-font-size-sm: 14px;
138
+ --om-font-size-md: 16px; /* body/large */
139
+ --om-font-size-lg: 18px; /* label/xlage, title/large */
140
+ --om-font-size-xl: 22px; /* title/large-prominent */
141
+ --om-font-size-2xl: 28px; /* Welcome headline */
142
+ --om-font-size-3xl: 32px;
143
+
144
+ /* ===== 行高 ===== */
145
+ --om-line-height-tight: 1.25;
146
+ --om-line-height-normal: 1.5;
147
+ --om-line-height-relaxed: 1.75;
148
+
149
+ /* ===== 阴影 ===== */
150
+ --om-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
151
+ --om-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08);
152
+ --om-shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.15);
153
+
154
+ /* ===== 触控规范(POS 设备一般 ≥48 提升精度,>= 44 是 Apple HIG 最低值) ===== */
155
+ --om-touch-min: 44px;
156
+ --om-touch-comfortable: 48px;
157
+
158
+ /* ===== Icon 尺寸(给 IonIcon / 装饰性占位图用)=====
159
+ md 与默认 body 字号对齐;sm/lg/xl 对应 chip / toolbar / hero 等上下文。 */
160
+ --om-icon-size-sm: 16px;
161
+ --om-icon-size-md: 20px;
162
+ --om-icon-size-lg: 24px;
163
+ --om-icon-size-xl: 32px;
164
+ /* 画报级占位(空态圆圈、商品缺图 emoji) */
165
+ --om-icon-size-hero: 44px;
166
+
167
+ /* ===== 交互控件高度 =====
168
+ 40/48 覆盖图标按钮 / 胶囊搜索框;52/56 是 POS 主 CTA 按钮高度(≥ 触控舒适值)。 */
169
+ --om-control-height-sm: 40px;
170
+ --om-control-height-md: 48px;
171
+ --om-control-height-lg: 52px;
172
+ --om-control-height-xl: 56px;
173
+
174
+ /* ===== 主色 / 白色之上的半透明遮罩(如蓝卡上的玻璃态徽章) ===== */
175
+ --om-overlay-on-primary-weak: rgba(255, 255, 255, 0.18);
176
+ --om-overlay-on-primary-mid: rgba(255, 255, 255, 0.2);
177
+ --om-overlay-on-primary-strong: rgba(255, 255, 255, 0.25);
178
+
179
+ /* 基于 primary-rgb 的软底(图标 chip / 加购按钮背景) */
180
+ --om-surface-primary-soft: rgba(var(--ion-color-primary-rgb), 0.12);
181
+ --om-surface-primary-softer: rgba(var(--ion-color-primary-rgb), 0.08);
182
+ --om-surface-primary-softest: rgba(var(--ion-color-primary-rgb), 0.04);
183
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * preset-mobile token 注册表 —— Inspect / 主题编辑器读这个映射。
3
+ * 实际 token 值在 [../theme/variables.css](../theme/variables.css) 里。
4
+ *
5
+ * Prefix 由 [../preset.manifest.ts](../preset.manifest.ts) 单点声明;这里不写字面量。
6
+ */
7
+
8
+ import { createTokenMap } from "@omit-design/engine/preset";
9
+ import { presetMobileManifest } from "../preset.manifest";
10
+
11
+ const PFX = presetMobileManifest.tokenPrefixes;
12
+
13
+ export const COLOR_KEYS = [
14
+ "primary",
15
+ "secondary",
16
+ "tertiary",
17
+ "success",
18
+ "warning",
19
+ "danger",
20
+ "dark",
21
+ "medium",
22
+ "light",
23
+ "background",
24
+ "text",
25
+ ] as const;
26
+
27
+ // background / text 不走 --ion-color-* 模式(Ionic 历史命名),单独 override
28
+ export const colorTokens = createTokenMap(COLOR_KEYS, PFX.color, {
29
+ background: "--ion-background-color",
30
+ text: "--ion-text-color",
31
+ });
32
+
33
+ export const SPACING_KEYS = ["xs", "sm", "md", "lg", "xl", "2xl"] as const;
34
+ export const spacingTokens = createTokenMap(SPACING_KEYS, PFX.spacing);
35
+
36
+ export const RADIUS_KEYS = ["sm", "md", "lg", "xl", "2xl", "full"] as const;
37
+ export const radiusTokens = createTokenMap(RADIUS_KEYS, PFX.radius);
38
+
39
+ export const FONT_KEYS = ["xs", "sm", "md", "lg", "xl", "2xl", "3xl"] as const;
40
+ export const fontSizeTokens = createTokenMap(FONT_KEYS, PFX.font);
41
+
42
+ export const SHADOW_KEYS = ["sm", "md", "lg"] as const;
43
+ export const shadowTokens = createTokenMap(SHADOW_KEYS, PFX.shadow ?? "--om-shadow-");
44
+
45
+ export type ColorTokenName = keyof typeof colorTokens;
46
+ export type SpacingTokenName = keyof typeof spacingTokens;
47
+ export type RadiusTokenName = keyof typeof radiusTokens;
48
+ export type FontSizeTokenName = keyof typeof fontSizeTokens;
49
+ export type ShadowTokenName = keyof typeof shadowTokens;
50
+
51
+ export const tokenVar = (cssVar: string) => `var(${cssVar})`;