@omit-design/preset-mobile 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -15
- package/README.zh-CN.md +123 -0
- package/components/OmDialog.tsx +2 -2
- package/components/OmNumpad.tsx +2 -2
- package/components/OmOrderFooter.tsx +2 -2
- package/components/OmProductCard.tsx +2 -2
- package/components/OmSearchBar.tsx +1 -1
- package/components/OmSheet.tsx +1 -1
- package/package.json +1 -1
- package/templates/dashboard.tmpl.tsx +6 -6
- package/templates/detail-view.tmpl.tsx +8 -8
- package/templates/dialog-view.tmpl.tsx +6 -6
- package/templates/form-view.tmpl.tsx +6 -6
- package/templates/list-view.tmpl.tsx +6 -6
- package/templates/sheet-action.tmpl.tsx +5 -5
- package/templates/tab-view.tmpl.tsx +8 -8
- package/templates/welcome-view.tmpl.tsx +4 -4
package/README.md
CHANGED
|
@@ -1,29 +1,122 @@
|
|
|
1
1
|
# @omit-design/preset-mobile
|
|
2
2
|
|
|
3
|
-
omit-design
|
|
3
|
+
> Default mobile preset for [omit-design](https://github.com/leefanv/omit-design): `Om*` whitelist components, `--om-*` token system, Ionic 8 runtime, and 8 ready-to-use patterns with copy-paste templates.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@omit-design/preset-mobile)
|
|
6
|
+
[](../../LICENSE)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
2. **组件白名单**:业务页面(`design/**`)只能 import `@omit-design/preset-mobile`,**禁止**直接 import `@ionic/react`(例外:`IonList` / `IonBackButton` / `IonIcon`,仅做排版/图标宿主)
|
|
9
|
-
3. **模式标注**:每个业务页面文件头第一行必须是 `// @pattern: <name>`,name 必须存在于 [PATTERNS.md](./PATTERNS.md)
|
|
8
|
+
[简体中文](./README.zh-CN.md)
|
|
10
9
|
|
|
11
|
-
##
|
|
10
|
+
## What it is
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
`preset-mobile` is the canonical preset most omit-design projects use. It provides:
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
- **21 `Om*` components** — the import whitelist for `design/**/*.tsx`
|
|
15
|
+
- **`--om-*` token system** mapped to Ionic 8 runtime (`--ion-*`)
|
|
16
|
+
- **8 patterns** with copy-paste `.tmpl.tsx` skeletons (consumed by `omit-design new-page`)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## Three hard rules (enforced by [@omit-design/eslint-plugin](../eslint-plugin/))
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
1. **Tokens only.** All colors / spacing / font sizes / radii / shadows must go through tokens. Raw literals (`#FF6B00`, `12px`, `16px`, etc.) are forbidden in business code.
|
|
21
|
+
2. **Whitelist imports.** Business pages (under `design/**`) can only import from `@omit-design/preset-mobile`. Direct `@ionic/react` imports are forbidden — exceptions: `IonList`, `IonBackButton`, `IonIcon` (layout / icon hosts only).
|
|
22
|
+
3. **Pattern header.** Every business page must start with `// @pattern: <name>`, where `<name>` is registered in [PATTERNS.md](./PATTERNS.md).
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
## Components (21)
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
All exported from `@omit-design/preset-mobile`:
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
| Layout | Inputs | Display | Overlays |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `OmPage` | `OmInput` | `OmCard` | `OmDialog` |
|
|
31
|
+
| `OmHeader` | `OmSelect` | `OmListRow` | `OmSheet` |
|
|
32
|
+
| `OmAppBar` | `OmSearchBar` | `OmStatCard` | |
|
|
33
|
+
| `OmTabBar` | `OmNumpad` | `OmMenuCard` | |
|
|
34
|
+
| | `OmButton` | `OmProductCard` | |
|
|
35
|
+
| | | `OmCouponCard` | |
|
|
36
|
+
| | | `OmSettingRow` | |
|
|
37
|
+
| | | `OmEmptyState` | |
|
|
38
|
+
| | | `OmTag` | |
|
|
39
|
+
| | | `OmOrderFooter` | |
|
|
26
40
|
|
|
27
|
-
|
|
41
|
+
Full source list: [components/index.ts](./components/index.ts).
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
## Patterns (8)
|
|
44
|
+
|
|
45
|
+
Each pattern ships:
|
|
46
|
+
- A documented section in [PATTERNS.md](./PATTERNS.md)
|
|
47
|
+
- A copy-paste `.tmpl.tsx` template
|
|
48
|
+
|
|
49
|
+
| Pattern | Use for |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `dashboard` | Stat cards + entry tiles (cafe POS home, admin overview) |
|
|
52
|
+
| `list-view` | Vertical list with filter / search |
|
|
53
|
+
| `detail-view` | Single record with sections (order, product, member) |
|
|
54
|
+
| `form-view` | Input-heavy edit / create forms |
|
|
55
|
+
| `dialog-view` | Modal with title + body + actions |
|
|
56
|
+
| `sheet-action` | Bottom sheet for quick actions |
|
|
57
|
+
| `tab-view` | Top-tab segmented content |
|
|
58
|
+
| `welcome-view` | First-launch / onboarding |
|
|
59
|
+
|
|
60
|
+
Generate a new page from a pattern:
|
|
61
|
+
```bash
|
|
62
|
+
npx omit-design new-page list-view design/orders/list
|
|
63
|
+
# → design/orders/list.tsx with the list-view skeleton
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Token naming
|
|
67
|
+
|
|
68
|
+
| Family | Examples |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `--om-color-*` | `--om-color-primary`, `--om-color-text`, `--om-color-text-muted` |
|
|
71
|
+
| `--om-spacing-*` | `--om-spacing-xs` (4) … `--om-spacing-xxl` (32) |
|
|
72
|
+
| `--om-radius-*` | `--om-radius-sm`, `--om-radius-md`, `--om-radius-lg` |
|
|
73
|
+
| `--om-font-size-*` | `--om-font-size-sm`, `--om-font-size-md`, `--om-font-size-lg` |
|
|
74
|
+
| `--om-shadow-*` | `--om-shadow-sm`, `--om-shadow-md` |
|
|
75
|
+
|
|
76
|
+
Defaults defined in [theme/variables.css](./theme/variables.css). Override in your project's CSS:
|
|
77
|
+
|
|
78
|
+
```css
|
|
79
|
+
:root {
|
|
80
|
+
--om-color-primary: #ff6b00;
|
|
81
|
+
--om-radius-md: 8px;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or use the in-browser theme editor at `/workspace/:projectId/theme-editor` (writes back to your `preset/theme.css`).
|
|
86
|
+
|
|
87
|
+
## Install
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install @omit-design/preset-mobile @omit-design/engine @ionic/react ionicons
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Required peers: `@omit-design/engine ^0.2.0`, `@ionic/react ^8`, `ionicons ^7 || ^8`, `react ^19`, `react-router-dom ^6`.
|
|
94
|
+
|
|
95
|
+
## Usage
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// design/main/welcome.tsx
|
|
99
|
+
// @pattern: welcome-view
|
|
100
|
+
export const meta = {
|
|
101
|
+
name: "Welcome",
|
|
102
|
+
pattern: "welcome-view",
|
|
103
|
+
description: "First-launch screen",
|
|
104
|
+
} as const;
|
|
105
|
+
|
|
106
|
+
import { OmButton, OmPage } from "@omit-design/preset-mobile";
|
|
107
|
+
|
|
108
|
+
export default function Welcome() {
|
|
109
|
+
return (
|
|
110
|
+
<OmPage padding="none">
|
|
111
|
+
<div style={{ padding: "var(--om-spacing-xl)" }}>
|
|
112
|
+
<h1>Hello</h1>
|
|
113
|
+
<OmButton expand="block">Continue</OmButton>
|
|
114
|
+
</div>
|
|
115
|
+
</OmPage>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
[MIT](../../LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @omit-design/preset-mobile
|
|
2
|
+
|
|
3
|
+
> [omit-design](https://github.com/leefanv/omit-design) 的默认移动端 preset:`Om*` 组件白名单 + `--om-*` token 体系 + Ionic 8 运行时 + 8 个开箱即用 pattern 与对应模板。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@omit-design/preset-mobile)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
|
|
8
|
+
[English](./README.md)
|
|
9
|
+
|
|
10
|
+
## 这是什么
|
|
11
|
+
|
|
12
|
+
`preset-mobile` 是 omit-design 项目默认用的 preset,提供:
|
|
13
|
+
|
|
14
|
+
- **21 个 `Om*` 组件** — `design/**/*.tsx` 的 import 白名单
|
|
15
|
+
- **`--om-*` token 体系**,映射到 Ionic 8 运行时(`--ion-*`)
|
|
16
|
+
- **8 个 pattern** + 对应的 `.tmpl.tsx` 模板(`omit-design new-page` 消费)
|
|
17
|
+
|
|
18
|
+
## 三条硬规则(由 [@omit-design/eslint-plugin](../eslint-plugin/) 强制)
|
|
19
|
+
|
|
20
|
+
1. **Token 优先**:所有颜色、间距、字号、圆角、阴影必须走 token,**禁止字面量**(`#FF6B00`、`12px`、`16px` 等都不允许出现在业务代码里)。
|
|
21
|
+
2. **组件白名单**:业务页面(`design/**`)只能 import `@omit-design/preset-mobile`,**禁止**直接 import `@ionic/react`(例外:`IonList` / `IonBackButton` / `IonIcon`,仅做排版/图标宿主)。
|
|
22
|
+
3. **模式标注**:每个业务页面文件头第一行必须是 `// @pattern: <name>`,`<name>` 必须在 [PATTERNS.md](./PATTERNS.md) 里登记。
|
|
23
|
+
|
|
24
|
+
## 组件清单(21 个)
|
|
25
|
+
|
|
26
|
+
全部从 `@omit-design/preset-mobile` 导出:
|
|
27
|
+
|
|
28
|
+
| 布局 | 输入 | 展示 | 浮层 |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `OmPage` | `OmInput` | `OmCard` | `OmDialog` |
|
|
31
|
+
| `OmHeader` | `OmSelect` | `OmListRow` | `OmSheet` |
|
|
32
|
+
| `OmAppBar` | `OmSearchBar` | `OmStatCard` | |
|
|
33
|
+
| `OmTabBar` | `OmNumpad` | `OmMenuCard` | |
|
|
34
|
+
| | `OmButton` | `OmProductCard` | |
|
|
35
|
+
| | | `OmCouponCard` | |
|
|
36
|
+
| | | `OmSettingRow` | |
|
|
37
|
+
| | | `OmEmptyState` | |
|
|
38
|
+
| | | `OmTag` | |
|
|
39
|
+
| | | `OmOrderFooter` | |
|
|
40
|
+
|
|
41
|
+
完整列表:[components/index.ts](./components/index.ts)。
|
|
42
|
+
|
|
43
|
+
## Patterns(8 个)
|
|
44
|
+
|
|
45
|
+
每个 pattern 自带:
|
|
46
|
+
- [PATTERNS.md](./PATTERNS.md) 里一段文档
|
|
47
|
+
- 一份可复制的 `.tmpl.tsx` 模板
|
|
48
|
+
|
|
49
|
+
| Pattern | 适用场景 |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `dashboard` | 统计卡 + 入口磁贴(咖啡店 POS 首页、admin 总览) |
|
|
52
|
+
| `list-view` | 带筛选 / 搜索的纵向列表 |
|
|
53
|
+
| `detail-view` | 单条记录详情(订单、商品、会员) |
|
|
54
|
+
| `form-view` | 输入密集的编辑 / 创建表单 |
|
|
55
|
+
| `dialog-view` | 标题 + 内容 + 操作按钮的模态 |
|
|
56
|
+
| `sheet-action` | 底部弹起的快捷操作 |
|
|
57
|
+
| `tab-view` | 顶部分段切换 |
|
|
58
|
+
| `welcome-view` | 首启 / 引导页 |
|
|
59
|
+
|
|
60
|
+
从 pattern 生成新页面:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx omit-design new-page list-view design/orders/list
|
|
64
|
+
# → design/orders/list.tsx 已含 list-view 骨架
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Token 命名
|
|
68
|
+
|
|
69
|
+
| 类别 | 例子 |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `--om-color-*` | `--om-color-primary` / `--om-color-text` / `--om-color-text-muted` |
|
|
72
|
+
| `--om-spacing-*` | `--om-spacing-xs` (4) … `--om-spacing-xxl` (32) |
|
|
73
|
+
| `--om-radius-*` | `--om-radius-sm` / `--om-radius-md` / `--om-radius-lg` |
|
|
74
|
+
| `--om-font-size-*` | `--om-font-size-sm` / `--om-font-size-md` / `--om-font-size-lg` |
|
|
75
|
+
| `--om-shadow-*` | `--om-shadow-sm` / `--om-shadow-md` |
|
|
76
|
+
|
|
77
|
+
默认值在 [theme/variables.css](./theme/variables.css)。在项目 CSS 里覆盖:
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
:root {
|
|
81
|
+
--om-color-primary: #ff6b00;
|
|
82
|
+
--om-radius-md: 8px;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
或用浏览器内的主题编辑器(`/workspace/:projectId/theme-editor`),编辑后写回项目的 `preset/theme.css`。
|
|
87
|
+
|
|
88
|
+
## 安装
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install @omit-design/preset-mobile @omit-design/engine @ionic/react ionicons
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
peer 依赖:`@omit-design/engine ^0.2.0`、`@ionic/react ^8`、`ionicons ^7 || ^8`、`react ^19`、`react-router-dom ^6`。
|
|
95
|
+
|
|
96
|
+
## 用例
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
// design/main/welcome.tsx
|
|
100
|
+
// @pattern: welcome-view
|
|
101
|
+
export const meta = {
|
|
102
|
+
name: "欢迎",
|
|
103
|
+
pattern: "welcome-view",
|
|
104
|
+
description: "首启页",
|
|
105
|
+
} as const;
|
|
106
|
+
|
|
107
|
+
import { OmButton, OmPage } from "@omit-design/preset-mobile";
|
|
108
|
+
|
|
109
|
+
export default function Welcome() {
|
|
110
|
+
return (
|
|
111
|
+
<OmPage padding="none">
|
|
112
|
+
<div style={{ padding: "var(--om-spacing-xl)" }}>
|
|
113
|
+
<h1>你好</h1>
|
|
114
|
+
<OmButton expand="block">开始</OmButton>
|
|
115
|
+
</div>
|
|
116
|
+
</OmPage>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 许可
|
|
122
|
+
|
|
123
|
+
[MIT](../../LICENSE)
|
package/components/OmDialog.tsx
CHANGED
|
@@ -39,7 +39,7 @@ export function OmDialog({
|
|
|
39
39
|
iconColor = "primary",
|
|
40
40
|
title,
|
|
41
41
|
subtitle,
|
|
42
|
-
confirmText = "
|
|
42
|
+
confirmText = "OK",
|
|
43
43
|
confirmColor = "primary",
|
|
44
44
|
confirmHref,
|
|
45
45
|
onConfirm,
|
|
@@ -81,7 +81,7 @@ export function OmDialog({
|
|
|
81
81
|
<>
|
|
82
82
|
{hasCancel && (
|
|
83
83
|
<OmButton variant="outline" color="medium" onClick={handleCancel}>
|
|
84
|
-
{cancelText ?? "
|
|
84
|
+
{cancelText ?? "Cancel"}
|
|
85
85
|
</OmButton>
|
|
86
86
|
)}
|
|
87
87
|
<OmButton color={confirmColor} onClick={handleConfirm}>
|
package/components/OmNumpad.tsx
CHANGED
|
@@ -63,14 +63,14 @@ export function OmNumpad({
|
|
|
63
63
|
{/* 右下角 */}
|
|
64
64
|
{clearMode ? (
|
|
65
65
|
<button className="om-numpad__key pos-numpad__key--clear" type="button" onClick={() => onClear?.()}>
|
|
66
|
-
|
|
66
|
+
Clear
|
|
67
67
|
</button>
|
|
68
68
|
) : showBackspace ? (
|
|
69
69
|
<button
|
|
70
70
|
className="om-numpad__key pos-numpad__key--ghost"
|
|
71
71
|
type="button"
|
|
72
72
|
onClick={() => onBackspace?.()}
|
|
73
|
-
aria-label="
|
|
73
|
+
aria-label="Backspace"
|
|
74
74
|
>
|
|
75
75
|
<IonIcon icon={backspaceOutline} />
|
|
76
76
|
</button>
|
|
@@ -43,7 +43,7 @@ export function OmOrderFooter({
|
|
|
43
43
|
className="om-order-footer__cart"
|
|
44
44
|
type="button"
|
|
45
45
|
onClick={onCartClick}
|
|
46
|
-
aria-label="
|
|
46
|
+
aria-label="Cart"
|
|
47
47
|
>
|
|
48
48
|
<IonIcon icon={cartOutline} />
|
|
49
49
|
{typeof cartCount === "number" && cartCount > 0 && (
|
|
@@ -55,7 +55,7 @@ export function OmOrderFooter({
|
|
|
55
55
|
<button className="om-order-footer__discount" type="button" onClick={onDiscountClick}>
|
|
56
56
|
<span className="om-order-footer__discount-amount">{discountLabel}</span>
|
|
57
57
|
<span className="om-order-footer__discount-label">
|
|
58
|
-
|
|
58
|
+
Discount details
|
|
59
59
|
<IonIcon icon={chevronForward} aria-hidden />
|
|
60
60
|
</span>
|
|
61
61
|
</button>
|
|
@@ -55,12 +55,12 @@ export function OmProductCard({
|
|
|
55
55
|
<span className="om-product__price-value">{price.toFixed(2)}</span>
|
|
56
56
|
</span>
|
|
57
57
|
<span className="om-product__unit">/{unit}</span>
|
|
58
|
-
<span className="om-product__stock"
|
|
58
|
+
<span className="om-product__stock">Stock {stock}</span>
|
|
59
59
|
</div>
|
|
60
60
|
<button
|
|
61
61
|
className="om-product__add"
|
|
62
62
|
type="button"
|
|
63
|
-
aria-label={
|
|
63
|
+
aria-label={`Add ${name}`}
|
|
64
64
|
onClick={(e) => {
|
|
65
65
|
e.stopPropagation();
|
|
66
66
|
onAdd?.();
|
package/components/OmSheet.tsx
CHANGED
|
@@ -37,7 +37,7 @@ export function OmSheet({ title, children, onDismiss, dismissHref, size = "auto"
|
|
|
37
37
|
{title && (
|
|
38
38
|
<div className="om-sheet__head">
|
|
39
39
|
<span className="om-sheet__title">{title}</span>
|
|
40
|
-
<button className="om-sheet__close" type="button" onClick={dismiss} aria-label="
|
|
40
|
+
<button className="om-sheet__close" type="button" onClick={dismiss} aria-label="Close">
|
|
41
41
|
<IonIcon icon={closeOutline} />
|
|
42
42
|
</button>
|
|
43
43
|
</div>
|
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// 3. 给 TILES 加合适 ionicons + href
|
|
6
6
|
|
|
7
7
|
export const meta = {
|
|
8
|
-
name: "TODO
|
|
8
|
+
name: "TODO Dashboard",
|
|
9
9
|
pattern: "dashboard",
|
|
10
|
-
description: "TODO
|
|
10
|
+
description: "TODO one-line description",
|
|
11
11
|
source: "prd",
|
|
12
12
|
} as const;
|
|
13
13
|
|
|
@@ -41,13 +41,13 @@ interface Tile {
|
|
|
41
41
|
|
|
42
42
|
// TODO: 替换为真实 mock import
|
|
43
43
|
const STATS: Stat[] = [
|
|
44
|
-
{ label: "
|
|
45
|
-
{ label: "
|
|
44
|
+
{ label: "Today's revenue", value: "$0.00", caption: "Includes settled amount" },
|
|
45
|
+
{ label: "Order count", value: "0", caption: "orders" },
|
|
46
46
|
];
|
|
47
47
|
|
|
48
48
|
const TILES: Tile[] = [
|
|
49
49
|
{ id: "pos", icon: cashOutline, label: "POS", href: "/designs/TODO" },
|
|
50
|
-
{ id: "orders", icon: receiptOutline, label: "
|
|
50
|
+
{ id: "orders", icon: receiptOutline, label: "Orders", href: "/designs/TODO" },
|
|
51
51
|
];
|
|
52
52
|
|
|
53
53
|
export function TodoDashboardPage() {
|
|
@@ -56,7 +56,7 @@ export function TodoDashboardPage() {
|
|
|
56
56
|
padding="lg"
|
|
57
57
|
header={
|
|
58
58
|
<OmHeader
|
|
59
|
-
title="TODO
|
|
59
|
+
title="TODO Dashboard"
|
|
60
60
|
start={<IonBackButton defaultHref="/designs/TODO-from" />}
|
|
61
61
|
/>
|
|
62
62
|
}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// 4. 主操作改成业务跳转
|
|
7
7
|
|
|
8
8
|
export const meta = {
|
|
9
|
-
name: "TODO
|
|
9
|
+
name: "TODO Detail page",
|
|
10
10
|
pattern: "detail-view",
|
|
11
|
-
description: "TODO
|
|
11
|
+
description: "TODO one-line description",
|
|
12
12
|
source: "prd",
|
|
13
13
|
} as const;
|
|
14
14
|
|
|
@@ -30,9 +30,9 @@ interface Record {
|
|
|
30
30
|
// TODO: 替换为真实 mock import
|
|
31
31
|
const RECORD: Record = {
|
|
32
32
|
id: "TODO",
|
|
33
|
-
title: "
|
|
33
|
+
title: "Sample title",
|
|
34
34
|
amount: 0,
|
|
35
|
-
status: "TODO
|
|
35
|
+
status: "TODO status",
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
export function TodoDetailPage() {
|
|
@@ -41,19 +41,19 @@ export function TodoDetailPage() {
|
|
|
41
41
|
padding="lg"
|
|
42
42
|
header={
|
|
43
43
|
<OmHeader
|
|
44
|
-
title="TODO
|
|
44
|
+
title="TODO Detail"
|
|
45
45
|
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
46
46
|
/>
|
|
47
47
|
}
|
|
48
48
|
>
|
|
49
49
|
<OmCard title={RECORD.title} subtitle={`#${RECORD.id}`}>
|
|
50
|
-
<p
|
|
51
|
-
<p
|
|
50
|
+
<p>Amount: ${RECORD.amount.toFixed(2)}</p>
|
|
51
|
+
<p>Status: {RECORD.status}</p>
|
|
52
52
|
</OmCard>
|
|
53
53
|
|
|
54
54
|
{/* TODO: 关联信息分块 —— 增加更多 OmCard */}
|
|
55
55
|
|
|
56
|
-
<OmButton expand="block"
|
|
56
|
+
<OmButton expand="block">Primary action</OmButton>
|
|
57
57
|
</OmPage>
|
|
58
58
|
);
|
|
59
59
|
}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// 4. iconColor / confirmColor 按场景设(danger / warning / success / primary)
|
|
7
7
|
|
|
8
8
|
export const meta = {
|
|
9
|
-
name: "TODO
|
|
9
|
+
name: "TODO Dialog",
|
|
10
10
|
pattern: "dialog-view",
|
|
11
|
-
description: "TODO
|
|
11
|
+
description: "TODO one-line description",
|
|
12
12
|
source: "prd",
|
|
13
13
|
} as const;
|
|
14
14
|
|
|
@@ -21,11 +21,11 @@ export function TodoDialogPage() {
|
|
|
21
21
|
<OmDialog
|
|
22
22
|
icon={informationCircleOutline}
|
|
23
23
|
iconColor="primary"
|
|
24
|
-
title="TODO
|
|
25
|
-
subtitle="TODO
|
|
26
|
-
cancelText="
|
|
24
|
+
title="TODO Title"
|
|
25
|
+
subtitle="TODO subtitle description."
|
|
26
|
+
cancelText="Cancel"
|
|
27
27
|
cancelHref="/designs/TODO-from"
|
|
28
|
-
confirmText="
|
|
28
|
+
confirmText="Confirm"
|
|
29
29
|
confirmHref="/designs/TODO-next"
|
|
30
30
|
/>
|
|
31
31
|
</OmPage>
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// 4. IonBackButton defaultHref 改成上一级
|
|
7
7
|
|
|
8
8
|
export const meta = {
|
|
9
|
-
name: "TODO
|
|
9
|
+
name: "TODO Form page",
|
|
10
10
|
pattern: "form-view",
|
|
11
|
-
description: "TODO
|
|
11
|
+
description: "TODO one-line description",
|
|
12
12
|
source: "prd",
|
|
13
13
|
} as const;
|
|
14
14
|
|
|
@@ -32,19 +32,19 @@ export function TodoFormPage() {
|
|
|
32
32
|
padding="lg"
|
|
33
33
|
header={
|
|
34
34
|
<OmHeader
|
|
35
|
-
title="TODO
|
|
35
|
+
title="TODO Form"
|
|
36
36
|
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
37
37
|
/>
|
|
38
38
|
}
|
|
39
39
|
>
|
|
40
|
-
<OmInput label="
|
|
41
|
-
<OmInput label="
|
|
40
|
+
<OmInput label="Field one" value={field1} onChange={setField1} />
|
|
41
|
+
<OmInput label="Field two" value={field2} onChange={setField2} />
|
|
42
42
|
|
|
43
43
|
<OmButton
|
|
44
44
|
expand="block"
|
|
45
45
|
onClick={() => navigate("/designs/TODO-next")}
|
|
46
46
|
>
|
|
47
|
-
|
|
47
|
+
Submit
|
|
48
48
|
</OmButton>
|
|
49
49
|
</OmPage>
|
|
50
50
|
);
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// 4. 调整空态文案
|
|
7
7
|
|
|
8
8
|
export const meta = {
|
|
9
|
-
name: "TODO
|
|
9
|
+
name: "TODO List page",
|
|
10
10
|
pattern: "list-view",
|
|
11
|
-
description: "TODO
|
|
11
|
+
description: "TODO one-line description",
|
|
12
12
|
source: "prd",
|
|
13
13
|
} as const;
|
|
14
14
|
|
|
@@ -28,8 +28,8 @@ interface Item {
|
|
|
28
28
|
|
|
29
29
|
// TODO: 替换为 import { items } from ""./mock/<group>" 相对路径";
|
|
30
30
|
const ITEMS: Item[] = [
|
|
31
|
-
{ id: "1", title: "
|
|
32
|
-
{ id: "2", title: "
|
|
31
|
+
{ id: "1", title: "Sample item 1", detail: "Subinfo" },
|
|
32
|
+
{ id: "2", title: "Sample item 2" },
|
|
33
33
|
];
|
|
34
34
|
|
|
35
35
|
export function TodoListPage() {
|
|
@@ -38,13 +38,13 @@ export function TodoListPage() {
|
|
|
38
38
|
padding="none"
|
|
39
39
|
header={
|
|
40
40
|
<OmHeader
|
|
41
|
-
title="TODO
|
|
41
|
+
title="TODO Title"
|
|
42
42
|
start={<IonBackButton defaultHref="/designs/TODO" />}
|
|
43
43
|
/>
|
|
44
44
|
}
|
|
45
45
|
>
|
|
46
46
|
{ITEMS.length === 0 ? (
|
|
47
|
-
<OmEmptyState title="
|
|
47
|
+
<OmEmptyState title="No data" description="TODO empty-state description" />
|
|
48
48
|
) : (
|
|
49
49
|
<IonList lines="none">
|
|
50
50
|
{ITEMS.map((it) => (
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// 3. dismissHref 改成来源页路径
|
|
6
6
|
|
|
7
7
|
export const meta = {
|
|
8
|
-
name: "TODO
|
|
8
|
+
name: "TODO Action menu",
|
|
9
9
|
pattern: "sheet-action",
|
|
10
|
-
description: "TODO
|
|
10
|
+
description: "TODO one-line description",
|
|
11
11
|
source: "prd",
|
|
12
12
|
} as const;
|
|
13
13
|
|
|
@@ -24,15 +24,15 @@ interface MenuItem {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const ITEMS: MenuItem[] = [
|
|
27
|
-
{ label: "TODO
|
|
28
|
-
{ label: "TODO
|
|
27
|
+
{ label: "TODO Item one", icon: ellipsisHorizontalOutline, href: "/designs/TODO" },
|
|
28
|
+
{ label: "TODO Item two", icon: ellipsisHorizontalOutline, href: "/designs/TODO" },
|
|
29
29
|
];
|
|
30
30
|
|
|
31
31
|
export function TodoSheetActionPage() {
|
|
32
32
|
const navigate = useNavigate();
|
|
33
33
|
return (
|
|
34
34
|
<OmPage padding="none">
|
|
35
|
-
<OmSheet title="TODO
|
|
35
|
+
<OmSheet title="TODO Title" dismissHref="/designs/TODO-from">
|
|
36
36
|
<div>
|
|
37
37
|
{ITEMS.map((it) => (
|
|
38
38
|
<button
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
// 本 template 展示扁平结构,首批落地后可重构为 shell。
|
|
9
9
|
|
|
10
10
|
export const meta = {
|
|
11
|
-
name: "TODO Tab
|
|
11
|
+
name: "TODO Tab page",
|
|
12
12
|
pattern: "tab-view",
|
|
13
|
-
description: "TODO
|
|
13
|
+
description: "TODO one-line description",
|
|
14
14
|
source: "prd",
|
|
15
15
|
} as const;
|
|
16
16
|
|
|
@@ -28,21 +28,21 @@ import {
|
|
|
28
28
|
} from "@omit-design/preset-mobile";
|
|
29
29
|
|
|
30
30
|
const TABS: OmTabItem[] = [
|
|
31
|
-
{ tab: "stored", href: "/designs/TODO-stored", label: "
|
|
32
|
-
{ tab: "orders", href: "/designs/TODO-orders", label: "
|
|
33
|
-
{ tab: "member", href: "/designs/TODO-member", label: "
|
|
34
|
-
{ tab: "settings", href: "/designs/TODO-settings", label: "
|
|
31
|
+
{ tab: "stored", href: "/designs/TODO-stored", label: "Stored", icon: cubeOutline },
|
|
32
|
+
{ tab: "orders", href: "/designs/TODO-orders", label: "Orders", icon: receiptOutline },
|
|
33
|
+
{ tab: "member", href: "/designs/TODO-member", label: "Members", icon: peopleOutline },
|
|
34
|
+
{ tab: "settings", href: "/designs/TODO-settings", label: "Settings", icon: settingsOutline },
|
|
35
35
|
];
|
|
36
36
|
|
|
37
37
|
export function TodoTabPage() {
|
|
38
38
|
return (
|
|
39
39
|
<OmPage
|
|
40
40
|
padding="lg"
|
|
41
|
-
header={<OmAppBar variant="brand" brandTitle="TODO
|
|
41
|
+
header={<OmAppBar variant="brand" brandTitle="TODO Brand" />}
|
|
42
42
|
>
|
|
43
43
|
<div>
|
|
44
44
|
{/* TODO: 主体内容 —— 表单 / 列表 / 空态 */}
|
|
45
|
-
<h1>TODO Tab
|
|
45
|
+
<h1>TODO Tab page body</h1>
|
|
46
46
|
</div>
|
|
47
47
|
<OmTabBar items={TABS} />
|
|
48
48
|
</OmPage>
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// 4. tagline / version 走 mock 或常量
|
|
7
7
|
|
|
8
8
|
export const meta = {
|
|
9
|
-
name: "TODO
|
|
9
|
+
name: "TODO Welcome page",
|
|
10
10
|
pattern: "welcome-view",
|
|
11
|
-
description: "TODO
|
|
11
|
+
description: "TODO one-line description",
|
|
12
12
|
source: "prd",
|
|
13
13
|
} as const;
|
|
14
14
|
|
|
@@ -23,14 +23,14 @@ export function TodoWelcomePage() {
|
|
|
23
23
|
{/* TODO: 替换为品牌 logo 组件 */}
|
|
24
24
|
<div>
|
|
25
25
|
<h1>Welcome</h1>
|
|
26
|
-
<p>TODO
|
|
26
|
+
<p>TODO welcome message</p>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
29
|
<OmButton
|
|
30
30
|
expand="block"
|
|
31
31
|
onClick={() => navigate("/designs/TODO-next")}
|
|
32
32
|
>
|
|
33
|
-
|
|
33
|
+
Get started
|
|
34
34
|
</OmButton>
|
|
35
35
|
</OmPage>
|
|
36
36
|
);
|