@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,43 @@
1
+ /* OmInput — 与 Figma M3 "outlined text field" 对齐。
2
+ 标签在外、描边框、圆角 md。错误态整条红框 + 底部红色 Note。 */
3
+
4
+ .om-input {
5
+ --input-border-color: var(--ion-color-medium-tint);
6
+ }
7
+
8
+ .om-input--error {
9
+ --input-border-color: var(--ion-color-danger);
10
+ }
11
+
12
+ .om-input ion-item {
13
+ --background: transparent;
14
+ --border-color: transparent;
15
+ --padding-start: 0;
16
+ --inner-padding-end: 0;
17
+ --min-height: 0;
18
+ }
19
+
20
+ .om-input ion-label {
21
+ --color: var(--ion-color-dark);
22
+ font-size: var(--om-font-size-md) !important;
23
+ margin-bottom: var(--om-spacing-xs) !important;
24
+ }
25
+
26
+ .om-input ion-input {
27
+ --padding-start: var(--om-spacing-md) !important;
28
+ --padding-end: var(--om-spacing-md) !important;
29
+ --padding-top: var(--om-spacing-md) !important;
30
+ --padding-bottom: var(--om-spacing-md) !important;
31
+ border: 1px solid var(--input-border-color);
32
+ border-radius: var(--om-radius-md);
33
+ background: var(--ion-background-color);
34
+ font-size: var(--om-font-size-md);
35
+ min-height: 56px;
36
+ }
37
+
38
+ .om-input ion-note {
39
+ display: block;
40
+ margin-top: var(--om-spacing-xs);
41
+ padding-left: var(--om-spacing-lg);
42
+ font-size: var(--om-font-size-xs);
43
+ }
@@ -0,0 +1,68 @@
1
+ /* OmMenuCard —— 工作台宫格卡 */
2
+
3
+ .om-menu {
4
+ appearance: none;
5
+ text-decoration: none;
6
+ border: none;
7
+ background: var(--ion-background-color);
8
+ border-radius: var(--om-radius-lg);
9
+ padding: var(--om-spacing-lg);
10
+ display: flex;
11
+ flex-direction: column;
12
+ align-items: flex-start;
13
+ gap: var(--om-spacing-md);
14
+ box-shadow: var(--om-shadow-sm);
15
+ min-height: calc(var(--om-control-height-xl) * 2);
16
+ cursor: pointer;
17
+ color: var(--ion-color-dark);
18
+ position: relative;
19
+ text-align: left;
20
+ }
21
+
22
+ .om-menu:active {
23
+ background: var(--om-surface-primary-softest);
24
+ }
25
+
26
+ .om-menu--disabled {
27
+ opacity: 0.4;
28
+ cursor: not-allowed;
29
+ }
30
+
31
+ .om-menu__icon {
32
+ width: var(--om-control-height-md);
33
+ height: var(--om-control-height-md);
34
+ border-radius: var(--om-radius-md);
35
+ background: var(--om-surface-primary-soft);
36
+ color: var(--ion-color-primary);
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ }
41
+
42
+ .om-menu__icon ion-icon {
43
+ font-size: var(--om-icon-size-lg);
44
+ }
45
+
46
+ .om-menu__label {
47
+ font-size: var(--om-font-size-md);
48
+ color: var(--ion-color-dark);
49
+ font-weight: 500;
50
+ }
51
+
52
+ .om-menu__badge {
53
+ position: absolute;
54
+ top: var(--om-spacing-sm);
55
+ right: var(--om-spacing-sm);
56
+ min-width: var(--om-spacing-lg);
57
+ height: var(--om-spacing-lg);
58
+ padding: 0 var(--om-spacing-xs);
59
+ border-radius: var(--om-radius-full);
60
+ background: var(--ion-color-danger);
61
+ color: var(--ion-color-danger-contrast);
62
+ font-size: var(--om-font-size-xs);
63
+ font-weight: 500;
64
+ display: inline-flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ box-sizing: border-box;
68
+ }
@@ -0,0 +1,49 @@
1
+ /* OmNumpad —— 3×4 数字键盘。 */
2
+
3
+ .om-numpad {
4
+ display: grid;
5
+ grid-template-columns: repeat(3, 1fr);
6
+ gap: var(--om-spacing-sm);
7
+ width: 100%;
8
+ }
9
+
10
+ .om-numpad__key {
11
+ appearance: none;
12
+ border: none;
13
+ background: var(--ion-background-color);
14
+ border-radius: var(--om-radius-md);
15
+ height: var(--om-control-height-xl);
16
+ font-size: var(--om-font-size-xl);
17
+ font-weight: 500;
18
+ color: var(--ion-color-dark);
19
+ cursor: pointer;
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ box-shadow: var(--om-shadow-sm);
24
+ min-height: var(--om-touch-comfortable);
25
+ transition: background 0.12s ease;
26
+ }
27
+
28
+ .om-numpad__key:active {
29
+ background: var(--ion-color-light);
30
+ }
31
+
32
+ .om-numpad__key--ghost {
33
+ background: transparent;
34
+ box-shadow: none;
35
+ color: var(--ion-color-medium-shade);
36
+ font-size: var(--om-font-size-md);
37
+ }
38
+
39
+ .om-numpad__key--clear {
40
+ background: var(--ion-color-light);
41
+ color: var(--ion-color-dark);
42
+ font-size: var(--om-font-size-md);
43
+ box-shadow: none;
44
+ }
45
+
46
+ .om-numpad__spacer {
47
+ display: block;
48
+ height: var(--om-control-height-xl);
49
+ }
@@ -0,0 +1,121 @@
1
+ /* OmOrderFooter —— 销售主页 / 购物车底部结算栏 */
2
+
3
+ .om-order-footer {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: var(--om-spacing-sm);
7
+ padding: var(--om-spacing-sm) var(--om-spacing-md);
8
+ background: var(--ion-background-color);
9
+ border-top: 1px solid var(--ion-color-light);
10
+ /* control-xl + 少量内边距,比标准 tab bar 略高 */
11
+ min-height: calc(var(--om-control-height-xl) + var(--om-spacing-sm));
12
+ }
13
+
14
+ .om-order-footer__cart {
15
+ position: relative;
16
+ appearance: none;
17
+ border: none;
18
+ background: transparent;
19
+ display: inline-flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ width: var(--om-control-height-sm);
23
+ height: var(--om-control-height-sm);
24
+ flex: 0 0 auto;
25
+ color: var(--ion-color-dark);
26
+ cursor: pointer;
27
+ }
28
+
29
+ .om-order-footer__cart ion-icon {
30
+ font-size: var(--om-icon-size-lg);
31
+ }
32
+
33
+ .om-order-footer__badge {
34
+ position: absolute;
35
+ top: -2px;
36
+ right: -2px;
37
+ min-width: var(--om-spacing-lg);
38
+ height: var(--om-spacing-lg);
39
+ padding: 0 var(--om-spacing-xs);
40
+ border-radius: var(--om-radius-full);
41
+ background: var(--ion-color-danger);
42
+ color: var(--ion-color-danger-contrast);
43
+ font-size: var(--om-font-size-xs);
44
+ font-weight: 500;
45
+ display: inline-flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ box-sizing: border-box;
49
+ }
50
+
51
+ .om-order-footer__discount {
52
+ appearance: none;
53
+ border: none;
54
+ background: transparent;
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: flex-start;
58
+ gap: var(--om-spacing-xs);
59
+ flex: 1 1 auto;
60
+ min-width: 0;
61
+ cursor: pointer;
62
+ text-align: left;
63
+ }
64
+
65
+ .om-order-footer__discount-amount {
66
+ font-size: var(--om-font-size-md);
67
+ color: var(--ion-color-dark);
68
+ font-weight: 600;
69
+ }
70
+
71
+ .om-order-footer__discount-label {
72
+ font-size: var(--om-font-size-xs);
73
+ color: var(--ion-color-medium);
74
+ display: inline-flex;
75
+ align-items: center;
76
+ gap: 2px;
77
+ }
78
+
79
+ .om-order-footer__discount-label ion-icon {
80
+ font-size: var(--om-font-size-sm);
81
+ }
82
+
83
+ .om-order-footer__cta {
84
+ appearance: none;
85
+ border: none;
86
+ background: var(--ion-color-primary);
87
+ color: var(--ion-color-primary-contrast);
88
+ border-radius: var(--om-radius-md);
89
+ height: var(--om-control-height-md);
90
+ padding: 0 var(--om-spacing-xl);
91
+ font-size: var(--om-font-size-lg);
92
+ font-weight: 600;
93
+ cursor: pointer;
94
+ flex: 0 0 auto;
95
+ display: inline-flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ }
99
+
100
+ .om-order-footer__cta:active {
101
+ background: var(--ion-color-primary-shade);
102
+ }
103
+
104
+ .om-order-footer__cta--compact {
105
+ padding: 0 var(--om-spacing-lg);
106
+ height: var(--om-control-height-sm);
107
+ font-size: var(--om-font-size-md);
108
+ }
109
+
110
+ .om-order-footer__split {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: var(--om-spacing-md);
114
+ margin-left: auto;
115
+ }
116
+
117
+ .om-order-footer__amount {
118
+ font-size: var(--om-font-size-lg);
119
+ font-weight: 700;
120
+ color: var(--ion-color-dark);
121
+ }
@@ -0,0 +1,43 @@
1
+ /*
2
+ * OmPage padding utility —— 通过 IonContent 的 --padding-* 变量生效。
3
+ * 属于设计系统(业务设计稿侧),使用 --om-spacing-* token。
4
+ */
5
+
6
+ /* 移动端设计稿里不需要显示滚动条(真机上看不到),Ionic 在桌面浏览器里默认会展示 */
7
+ ion-content::part(scroll) {
8
+ scrollbar-width: none;
9
+ }
10
+ ion-content::part(scroll)::-webkit-scrollbar {
11
+ display: none;
12
+ }
13
+
14
+ .om-page-pad-none {
15
+ --padding-start: 0;
16
+ --padding-end: 0;
17
+ --padding-top: 0;
18
+ --padding-bottom: 0;
19
+ }
20
+ .om-page-pad-sm {
21
+ --padding-start: var(--om-spacing-sm);
22
+ --padding-end: var(--om-spacing-sm);
23
+ --padding-top: var(--om-spacing-sm);
24
+ --padding-bottom: var(--om-spacing-sm);
25
+ }
26
+ .om-page-pad-md {
27
+ --padding-start: var(--om-spacing-md);
28
+ --padding-end: var(--om-spacing-md);
29
+ --padding-top: var(--om-spacing-md);
30
+ --padding-bottom: var(--om-spacing-md);
31
+ }
32
+ .om-page-pad-lg {
33
+ --padding-start: var(--om-spacing-lg);
34
+ --padding-end: var(--om-spacing-lg);
35
+ --padding-top: var(--om-spacing-lg);
36
+ --padding-bottom: var(--om-spacing-lg);
37
+ }
38
+ .om-page-pad-xl {
39
+ --padding-start: var(--om-spacing-xl);
40
+ --padding-end: var(--om-spacing-xl);
41
+ --padding-top: var(--om-spacing-xl);
42
+ --padding-bottom: var(--om-spacing-xl);
43
+ }
@@ -0,0 +1,124 @@
1
+ /* OmProductCard —— 商品行卡片 */
2
+
3
+ .om-product {
4
+ display: flex;
5
+ gap: var(--om-spacing-md);
6
+ background: var(--ion-background-color);
7
+ border-radius: var(--om-radius-md);
8
+ padding: var(--om-spacing-md);
9
+ box-shadow: var(--om-shadow-sm);
10
+ width: 100%;
11
+ box-sizing: border-box;
12
+ align-items: center;
13
+ }
14
+
15
+ .om-product__image {
16
+ flex: 0 0 auto;
17
+ /* 80×80 固定缩略图尺寸(Figma 规格),= control-xl + spacing-xl */
18
+ width: calc(var(--om-control-height-xl) + var(--om-spacing-xl));
19
+ height: calc(var(--om-control-height-xl) + var(--om-spacing-xl));
20
+ border-radius: var(--om-radius-md);
21
+ background: var(--ion-color-light);
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ overflow: hidden;
26
+ }
27
+
28
+ .om-product__emoji {
29
+ font-size: var(--om-icon-size-hero);
30
+ line-height: 1;
31
+ }
32
+
33
+ .om-product__body {
34
+ flex: 1 1 auto;
35
+ min-width: 0;
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: var(--om-spacing-sm);
39
+ }
40
+
41
+ .om-product__titles {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--om-spacing-xs);
45
+ }
46
+
47
+ .om-product__name {
48
+ margin: 0;
49
+ font-size: var(--om-font-size-md);
50
+ color: var(--ion-color-dark);
51
+ line-height: 1.25;
52
+ display: -webkit-box;
53
+ -webkit-line-clamp: 2;
54
+ -webkit-box-orient: vertical;
55
+ overflow: hidden;
56
+ }
57
+
58
+ .om-product__sku {
59
+ margin: 0;
60
+ font-size: var(--om-font-size-xs);
61
+ color: var(--ion-color-medium);
62
+ }
63
+
64
+ .om-product__foot {
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ gap: var(--om-spacing-sm);
69
+ }
70
+
71
+ .om-product__price-group {
72
+ display: flex;
73
+ align-items: baseline;
74
+ gap: var(--om-spacing-xs);
75
+ flex-wrap: wrap;
76
+ }
77
+
78
+ .om-product__price {
79
+ color: var(--ion-color-dark);
80
+ font-weight: 700;
81
+ }
82
+
83
+ .om-product__price-sign {
84
+ font-size: var(--om-font-size-sm);
85
+ }
86
+
87
+ .om-product__price-value {
88
+ font-size: var(--om-font-size-md);
89
+ }
90
+
91
+ .om-product__unit {
92
+ font-size: var(--om-font-size-xs);
93
+ color: var(--ion-color-medium);
94
+ }
95
+
96
+ .om-product__stock {
97
+ font-size: var(--om-font-size-xs);
98
+ color: var(--ion-color-medium);
99
+ opacity: 0.7;
100
+ }
101
+
102
+ .om-product__add {
103
+ appearance: none;
104
+ border: none;
105
+ background: var(--om-surface-primary-soft);
106
+ color: var(--ion-color-primary);
107
+ border-radius: var(--om-radius-md);
108
+ /* 36×36 的加购按钮(比 control-sm=40 小一号,刚好容在卡片右下角) */
109
+ width: calc(var(--om-control-height-sm) - var(--om-spacing-xs));
110
+ height: calc(var(--om-control-height-sm) - var(--om-spacing-xs));
111
+ display: inline-flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ cursor: pointer;
115
+ flex: 0 0 auto;
116
+ }
117
+
118
+ .om-product__add:active {
119
+ background: rgba(var(--ion-color-primary-rgb), 0.24);
120
+ }
121
+
122
+ .om-product__add ion-icon {
123
+ font-size: var(--om-icon-size-md);
124
+ }
@@ -0,0 +1,39 @@
1
+ /* OmSearchBar —— 圆角胶囊搜索输入 */
2
+
3
+ .om-search-bar {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: var(--om-spacing-sm);
7
+ background: var(--ion-background-color);
8
+ border: 1px solid var(--ion-color-light);
9
+ border-radius: var(--om-radius-full);
10
+ padding: 0 var(--om-spacing-md);
11
+ height: var(--om-control-height-sm);
12
+ width: 100%;
13
+ }
14
+
15
+ .om-search-bar__icon {
16
+ font-size: var(--om-font-size-md);
17
+ color: var(--ion-color-medium);
18
+ flex: 0 0 auto;
19
+ }
20
+
21
+ .om-search-bar__input {
22
+ flex: 1 1 auto;
23
+ min-width: 0;
24
+ border: none;
25
+ outline: none;
26
+ background: transparent;
27
+ font-size: var(--om-font-size-sm);
28
+ color: var(--ion-color-dark);
29
+ }
30
+
31
+ .om-search-bar__input::placeholder {
32
+ color: var(--ion-color-medium);
33
+ }
34
+
35
+ .om-search-bar__trailing {
36
+ flex: 0 0 auto;
37
+ display: flex;
38
+ align-items: center;
39
+ }
@@ -0,0 +1,28 @@
1
+ /* OmSelect — 与 OmInput 视觉保持一致的下拉选择。 */
2
+
3
+ .om-select ion-item {
4
+ --background: transparent;
5
+ --border-color: transparent;
6
+ --padding-start: 0;
7
+ --inner-padding-end: 0;
8
+ --min-height: 0;
9
+ }
10
+
11
+ .om-select ion-label {
12
+ --color: var(--ion-color-dark);
13
+ font-size: var(--om-font-size-md) !important;
14
+ margin-bottom: var(--om-spacing-xs) !important;
15
+ }
16
+
17
+ .om-select ion-select {
18
+ --padding-start: var(--om-spacing-md);
19
+ --padding-end: var(--om-spacing-md);
20
+ --padding-top: var(--om-spacing-md);
21
+ --padding-bottom: var(--om-spacing-md);
22
+ border: 1px solid var(--ion-color-medium-tint);
23
+ border-radius: var(--om-radius-md);
24
+ background: var(--ion-background-color);
25
+ font-size: var(--om-font-size-md);
26
+ min-height: 56px;
27
+ color: var(--ion-color-dark);
28
+ }
@@ -0,0 +1,82 @@
1
+ /* OmSettingRow —— 设置行,toggle/navigate/value 三种形态共享布局 */
2
+
3
+ .om-setting-row {
4
+ appearance: none;
5
+ text-decoration: none;
6
+ border: none;
7
+ background: var(--ion-background-color);
8
+ display: flex;
9
+ align-items: center;
10
+ gap: var(--om-spacing-md);
11
+ padding: var(--om-spacing-lg);
12
+ width: 100%;
13
+ text-align: left;
14
+ color: inherit;
15
+ min-height: var(--om-control-height-xl);
16
+ border-bottom: 1px solid var(--ion-color-light);
17
+ }
18
+
19
+ .om-setting-row:last-child {
20
+ border-bottom: none;
21
+ }
22
+
23
+ .om-setting-row--interactive {
24
+ cursor: pointer;
25
+ }
26
+
27
+ .om-setting-row--interactive:active {
28
+ background: var(--om-surface-primary-softest);
29
+ }
30
+
31
+ .om-setting-row__icon {
32
+ width: var(--om-control-height-sm);
33
+ height: var(--om-control-height-sm);
34
+ border-radius: var(--om-radius-md);
35
+ background: var(--om-surface-primary-soft);
36
+ color: var(--ion-color-primary);
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ flex: 0 0 auto;
41
+ }
42
+
43
+ .om-setting-row__icon ion-icon {
44
+ font-size: var(--om-icon-size-md);
45
+ }
46
+
47
+ .om-setting-row__body {
48
+ flex: 1 1 auto;
49
+ min-width: 0;
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: var(--om-spacing-xs);
53
+ }
54
+
55
+ .om-setting-row__label {
56
+ font-size: var(--om-font-size-md);
57
+ color: var(--ion-color-dark);
58
+ }
59
+
60
+ .om-setting-row__desc {
61
+ font-size: var(--om-font-size-xs);
62
+ color: var(--ion-color-medium);
63
+ line-height: 1.4;
64
+ }
65
+
66
+ .om-setting-row__right {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: var(--om-spacing-sm);
70
+ flex: 0 0 auto;
71
+ color: var(--ion-color-medium-shade);
72
+ }
73
+
74
+ .om-setting-row__value {
75
+ font-size: var(--om-font-size-sm);
76
+ color: var(--ion-color-medium-shade);
77
+ }
78
+
79
+ .om-setting-row__chevron {
80
+ font-size: var(--om-icon-size-sm);
81
+ color: var(--ion-color-medium);
82
+ }
@@ -0,0 +1,73 @@
1
+ /* OmSheet —— 底部抽屉 */
2
+
3
+ .om-sheet {
4
+ position: absolute;
5
+ inset: 0;
6
+ z-index: 12;
7
+ display: flex;
8
+ flex-direction: column;
9
+ justify-content: flex-end;
10
+ }
11
+
12
+ .om-sheet__scrim {
13
+ position: absolute;
14
+ inset: 0;
15
+ background: var(--om-overlay-scrim);
16
+ }
17
+
18
+ .om-sheet__panel {
19
+ position: relative;
20
+ background: var(--ion-background-color);
21
+ border-top-left-radius: var(--om-radius-xl);
22
+ border-top-right-radius: var(--om-radius-xl);
23
+ box-shadow: var(--om-shadow-lg);
24
+ max-height: 85%;
25
+ display: flex;
26
+ flex-direction: column;
27
+ animation: pos-sheet-in 0.2s ease-out;
28
+ }
29
+
30
+ .om-sheet__panel--tall {
31
+ min-height: 70%;
32
+ }
33
+
34
+ @keyframes pos-sheet-in {
35
+ from { transform: translateY(100%); }
36
+ to { transform: translateY(0); }
37
+ }
38
+
39
+ .om-sheet__head {
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: space-between;
43
+ padding: var(--om-spacing-lg);
44
+ border-bottom: 1px solid var(--ion-color-light);
45
+ }
46
+
47
+ .om-sheet__title {
48
+ font-size: var(--om-font-size-md);
49
+ font-weight: 600;
50
+ color: var(--ion-color-dark);
51
+ }
52
+
53
+ .om-sheet__close {
54
+ appearance: none;
55
+ border: none;
56
+ background: transparent;
57
+ width: var(--om-control-height-sm);
58
+ height: var(--om-control-height-sm);
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ color: var(--ion-color-medium);
63
+ cursor: pointer;
64
+ }
65
+
66
+ .om-sheet__close ion-icon {
67
+ font-size: var(--om-icon-size-md);
68
+ }
69
+
70
+ .om-sheet__body {
71
+ overflow-y: auto;
72
+ padding: var(--om-spacing-lg);
73
+ }
@@ -0,0 +1,40 @@
1
+ /* OmStatCard —— 工作台数字指标卡 */
2
+
3
+ .om-stat {
4
+ background: var(--ion-background-color);
5
+ border-radius: var(--om-radius-lg);
6
+ padding: var(--om-spacing-lg);
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--om-spacing-xs);
10
+ box-shadow: var(--om-shadow-sm);
11
+ }
12
+
13
+ .om-stat__head {
14
+ display: flex;
15
+ align-items: baseline;
16
+ justify-content: space-between;
17
+ gap: var(--om-spacing-sm);
18
+ }
19
+
20
+ .om-stat__label {
21
+ font-size: var(--om-font-size-sm);
22
+ color: var(--ion-color-medium-shade);
23
+ }
24
+
25
+ .om-stat__meta {
26
+ font-size: var(--om-font-size-xs);
27
+ color: var(--ion-color-medium);
28
+ }
29
+
30
+ .om-stat__value {
31
+ font-size: var(--om-font-size-2xl);
32
+ font-weight: 700;
33
+ color: var(--ion-color-dark);
34
+ line-height: 1.15;
35
+ }
36
+
37
+ .om-stat__caption {
38
+ font-size: var(--om-font-size-xs);
39
+ color: var(--ion-color-medium);
40
+ }