@doubao-dev/template 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -182,9 +182,51 @@ import { Price } from '@doubao-dev/template/primitives';
182
182
  - `loading` 展示最大宽度为 60% 的扫光占位。
183
183
  - `className` 和 `style` 可用于样式定制。
184
184
 
185
+ ## MapCard
186
+
187
+ 地图卡模板,由固定高度地图、可选信息区和操作区组成,适合路线预估、叫车状态、位置详情等场景。
188
+
189
+ ```tsx
190
+ import { MapCard } from '@doubao-dev/template';
191
+
192
+ <MapCard
193
+ mapProps={{
194
+ center: { latitude: 39.9087, longitude: 116.3975 },
195
+ scale: 14,
196
+ polyline: [
197
+ {
198
+ id: 'route',
199
+ points: [
200
+ { latitude: 39.9151, longitude: 116.4039 },
201
+ { latitude: 39.9042, longitude: 116.3925 }
202
+ ],
203
+ width: 5
204
+ }
205
+ ]
206
+ }}
207
+ title="预估 29 元"
208
+ metaItems={[
209
+ { text: '最高优惠 6 元', tone: 'highlight' },
210
+ { text: '已选 4 种车型' }
211
+ ]}
212
+ inlineActions={[{ text: '确认叫车', onClick: () => console.log('confirm') }]}
213
+ />
214
+ ```
215
+
216
+ 说明:
217
+
218
+ - `mapProps` 透传地图能力,但卡片统一管理地图的 `className`、`style` 和 168px 高度;可通过 `mapProps.children` 传入 `MapMarker` 等地图覆盖物。
219
+ - `ref` 会直接绑定到内部 Map,可通过 `MapRef` 调用 `getCenter`、`setCenter` 等实例方法。
220
+ - MapCard 不渲染地图左上角来源标题,小程序标题由客户端的 `titleType` 控制。
221
+ - `title` 使用单行 `Title` primitive,`showArrow` 默认是 `true`。
222
+ - `metaItems` 最多展示前 2 项,`tone="highlight"` 使用强调色;多项之间由模板补充分隔点。
223
+ - `inlineActions` 复用 `TemplateCardFooterActionButton`;单按钮按主按钮渲染,双按钮依次按次按钮、主按钮渲染。
224
+ - `footer` 使用通用底部操作区。信息区和 footer 可单独使用,也可组合使用。
225
+ - MapCard 不支持 `children`,地图配置、信息和操作均使用对应的结构化字段。
226
+
185
227
  ## ContentCard
186
228
 
187
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/content-card.png" alt="ContentCard 示例" width="400" />
229
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/content-card.png" alt="ContentCard 示例" width="400" />
188
230
 
189
231
  通用列表卡,由标题栏、列表内容和底部操作区组成,适合商品、服务、内容入口等可重复条目。
190
232
 
@@ -226,7 +268,7 @@ import { ContentCard } from '@doubao-dev/template';
226
268
 
227
269
  ## PriceActionCard
228
270
 
229
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/price-action-card.png" alt="PriceActionCard 示例" width="400" />
271
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/price-action-card.png" alt="PriceActionCard 示例" width="400" />
230
272
 
231
273
  价格操作卡,由多条"价格 + 信息 + 右侧按钮"组成,适合报价、权益、服务方案等结果列表。
232
274
 
@@ -259,7 +301,7 @@ import { PriceActionCard } from '@doubao-dev/template';
259
301
 
260
302
  ## CheckoutCard
261
303
 
262
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/checkout-card.png" alt="CheckoutCard 示例" width="400" />
304
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/checkout-card.png" alt="CheckoutCard 示例" width="400" />
263
305
 
264
306
  通用提单卡,由商品摘要、提单信息、费用汇总和底部操作区组成,适合下单确认、支付确认等场景。
265
307
 
@@ -310,7 +352,7 @@ import { CheckoutCard } from '@doubao-dev/template';
310
352
 
311
353
  ## TicketOrderCard
312
354
 
313
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/ticket-checkout-card.png" alt="TicketOrderCard 示例" width="400" />
355
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/ticket-checkout-card.png" alt="TicketOrderCard 示例" width="400" />
314
356
 
315
357
  > **已废弃:** 请使用 `CheckoutCard`。`TicketOrderCard` 仅为兼容现有代码保留。
316
358
 
@@ -357,7 +399,7 @@ import { TicketOrderCard } from '@doubao-dev/template';
357
399
 
358
400
  ## TransitCard
359
401
 
360
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/transit-card.png" alt="TransitCard 示例" width="400" />
402
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/transit-card.png" alt="TransitCard 示例" width="400" />
361
403
 
362
404
  交通票务列表卡,由多条出发、中转、到达和价格信息组成,适合展示机票、火车票、大巴等推荐列表。
363
405
 
@@ -405,7 +447,7 @@ import { TransitCard } from '@doubao-dev/template';
405
447
 
406
448
  ## AskHumanCard
407
449
 
408
- <img src="https://unpkg.com/@doubao-dev/template@0.1.0/assets/ask-human-card.png" alt="AskHumanCard 示例" width="400" />
450
+ <img src="https://unpkg.com/@doubao-dev/template@0.2.0/assets/ask-human-card.png" alt="AskHumanCard 示例" width="400" />
409
451
 
410
452
  人工确认选项卡,由一组选项组成,适合让用户在多个候选项中确认选择。
411
453
 
@@ -421,6 +463,14 @@ import { AskHumanCard } from '@doubao-dev/template';
421
463
  text: '都不是',
422
464
  showArrow: 'right',
423
465
  onClick: () => console.log('skip')
466
+ },
467
+ {
468
+ text: '打开外部应用',
469
+ showArrow: 'right',
470
+ openType: 'launchApp',
471
+ launchAppUrl: 'your-app://path',
472
+ onLaunchApp: (result) => console.log('launch app success', result),
473
+ onLaunchAppError: (error) => console.error('launch app failed', error)
424
474
  }
425
475
  ]}
426
476
  />
@@ -430,3 +480,4 @@ import { AskHumanCard } from '@doubao-dev/template';
430
480
 
431
481
  - `items` 配置选项列表,选项文案通过 `text` 设置。
432
482
  - `items[].showArrow` 支持 `'left'`、`'right'`、`'none'`,默认不展示;跳过、固定跳转等入口也通过 `items` 表达。
483
+ - 设置 `items[].openType` 为 `'launchApp'` 并传入 `launchAppUrl`,可以通过 deeplink 跳转外部应用;跳转结果分别通过 `onLaunchApp` 和 `onLaunchAppError` 回调。
@@ -1,3 +1,4 @@
1
+ import { type LaunchAppResult } from '@byted-doubao-apps/components';
1
2
  import type { CSSProperties, TouchEvent } from '@lynx-js/types';
2
3
  import { type ReactElement } from 'react';
3
4
  import type { TemplateKey, TemplateText } from '../types.js';
@@ -29,6 +30,10 @@ export interface AskHumanCardItem {
29
30
  text?: TemplateText;
30
31
  /** 是否显示加载状态;为 true 时选项内展示 loading 动画并禁用点击。 */
31
32
  loading?: boolean;
33
+ /** 开放能力类型;`'launchApp'` 用于跳转外部应用。 */
34
+ openType?: 'launchApp';
35
+ /** 跳转外部应用的 deeplink URL,只在 `openType="launchApp"` 时有效。 */
36
+ launchAppUrl?: string;
32
37
  /** 箭头展示位置;默认 `'none'` 不展示。 */
33
38
  showArrow?: AskHumanCardArrowPosition;
34
39
  /** 选项根节点自定义类名。 */
@@ -37,6 +42,10 @@ export interface AskHumanCardItem {
37
42
  style?: CSSProperties;
38
43
  /** 点击选项时触发。 */
39
44
  onClick?: (event?: TouchEvent) => void;
45
+ /** 跳转外部应用成功时触发,只在 `openType="launchApp"` 时有效。 */
46
+ onLaunchApp?: (result: LaunchAppResult) => void;
47
+ /** 跳转外部应用失败时触发,只在 `openType="launchApp"` 时有效。 */
48
+ onLaunchAppError?: (error: unknown) => void;
40
49
  }
41
50
  export declare function AskHumanCard(props: AskHumanCardProps): ReactElement;
42
51
  //# sourceMappingURL=index.d.ts.map
@@ -23,7 +23,7 @@ function renderAskHumanCardItem({ item, index, optionBg, arrowColor }) {
23
23
  }, item.className)} style={{
24
24
  backgroundColor: optionBg,
25
25
  ...item.style
26
- }} type="default" loading={isLoading} onClick={(event)=>{
26
+ }} type="default" loading={isLoading} openType={item.openType} launchAppUrl={item.launchAppUrl} onLaunchApp={item.onLaunchApp} onLaunchAppError={item.onLaunchAppError} onClick={(event)=>{
27
27
  reportAskHumanCardClick();
28
28
  item.onClick?.(event);
29
29
  }}>
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export type { TemplateExtraAction, TemplateExtraActionButton, TemplateExtraActio
5
5
  export { AskHumanCard, type AskHumanCardArrowPosition, type AskHumanCardItem, type AskHumanCardProps } from './ask-human-card/index.js';
6
6
  export { CheckoutCard, type CheckoutCardFeeItem, type CheckoutCardInfoItem, type CheckoutCardProductItem, type CheckoutCardProps } from './checkout-card/index.js';
7
7
  export { PriceActionCard, type PriceActionCardInfoRow, type PriceActionCardItem, type PriceActionCardProps } from './price-action-card/index.js';
8
+ export { MapCard, type MapCardMapProps, type MapCardMetaItem, type MapCardMetaTone, type MapCardProps } from './map-card/index.js';
8
9
  export { TransitCard, type TransitCardItem, type TransitCardPrice, type TransitCardProps, type TransitCardTag } from './transit-card/index.js';
9
10
  export type { TemplateKey, TemplateTagTone, TemplateText } from './types.js';
10
11
  export { TicketOrderCard, type TicketOrderCardFeeItem, type TicketOrderCardInfoItem, type TicketOrderCardProps, type TicketOrderCardRouteItem } from './ticket-order-card/index.js';
package/dist/index.js CHANGED
@@ -2,5 +2,6 @@ export { ContentCard } from "./content-card/index.js";
2
2
  export { AskHumanCard } from "./ask-human-card/index.js";
3
3
  export { CheckoutCard } from "./checkout-card/index.js";
4
4
  export { PriceActionCard } from "./price-action-card/index.js";
5
+ export { MapCard } from "./map-card/index.js";
5
6
  export { TransitCard } from "./transit-card/index.js";
6
7
  export { TicketOrderCard } from "./ticket-order-card/index.js";
@@ -0,0 +1,37 @@
1
+ import { type MapProps, type MapRef } from '@byted-doubao-apps/components';
2
+ import type { CSSProperties, TouchEvent } from '@lynx-js/types';
3
+ import { type TemplateCardFooterActionButton, type TemplateCardFooterProps } from '../components/footer/index.js';
4
+ import type { TemplateKey, TemplateText } from '../types.js';
5
+ import './styles.scss';
6
+ export type MapCardMapProps = Omit<MapProps, 'className' | 'style'>;
7
+ export type MapCardMetaTone = 'default' | 'highlight';
8
+ export interface MapCardMetaItem {
9
+ /** 唯一标识;不传时使用数组下标。 */
10
+ key?: TemplateKey;
11
+ /** 辅助信息文案。 */
12
+ text: TemplateText;
13
+ /** 文案色调。@defaultValue default */
14
+ tone?: MapCardMetaTone;
15
+ }
16
+ export interface MapCardProps {
17
+ /** 地图配置。卡片统一管理地图的宽高和类名。 */
18
+ mapProps: MapCardMapProps;
19
+ /** 信息区标题。 */
20
+ title?: TemplateText;
21
+ /** 是否展示标题右侧箭头。@defaultValue true */
22
+ showArrow?: boolean;
23
+ /** 标题下方的辅助信息,最多展示前两项。 */
24
+ metaItems?: MapCardMetaItem[];
25
+ /** 信息区右侧操作,最多展示前两个;双按钮时依次按次按钮、主按钮渲染。 */
26
+ inlineActions?: TemplateCardFooterActionButton[];
27
+ /** 底部操作区配置。 */
28
+ footer?: TemplateCardFooterProps;
29
+ /** 卡片根节点自定义类名。 */
30
+ className?: string;
31
+ /** 卡片根节点自定义样式。 */
32
+ style?: CSSProperties;
33
+ /** 点击卡片根节点时触发。 */
34
+ onClick?: (event: TouchEvent) => void;
35
+ }
36
+ export declare const MapCard: (props: MapCardProps & import("react").RefAttributes<MapRef>) => React.ReactElement | null;
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { Button, Map, useThemeClassName } from "@byted-doubao-apps/components";
2
+ import { clsx } from "clsx";
3
+ import { forwardRef } from "react";
4
+ import { TemplateCardFooter } from "../components/footer/index.js";
5
+ import { Title } from "../primitives/title/index.js";
6
+ import "./styles.css";
7
+ function hasTemplateText(value) {
8
+ return void 0 !== value && '' !== value;
9
+ }
10
+ function MapCardImpl(props, ref) {
11
+ const { mapProps, title, showArrow = true, metaItems = [], inlineActions = [], footer, className, style, onClick } = props;
12
+ const visibleMetaItems = metaItems.filter((item)=>hasTemplateText(item.text)).slice(0, 2);
13
+ const visibleInlineActions = inlineActions.filter((action)=>null != action.text && action.text.length > 0).slice(0, 2);
14
+ const hasTitle = hasTemplateText(title);
15
+ const hasContent = hasTitle || visibleMetaItems.length > 0 || visibleInlineActions.length > 0;
16
+ return <view className={useThemeClassName(clsx('doubao-map-card', className))} style={style} bindtap={onClick} clip-radius="true">
17
+ <view className="doubao-map-card__viewport">
18
+ <Map {...mapProps} ref={ref} className="doubao-map-card__map"/>
19
+ </view>
20
+
21
+ {hasContent ? <view className="doubao-map-card__content">
22
+ <view className="doubao-map-card__text-content">
23
+ {hasTitle ? <Title text={title} showArrow={showArrow}/> : null}
24
+ {visibleMetaItems.length > 0 ? <view className="doubao-map-card__meta">
25
+ {visibleMetaItems.map((item, index)=><view className="doubao-map-card__meta-entry" key={item.key ?? index}>
26
+ {index > 0 ? <text className="doubao-map-card__meta-separator">·</text> : null}
27
+ <text className={clsx('doubao-map-card__meta-text', 'highlight' === item.tone && 'doubao-map-card__meta-text--highlight')} text-maxline="1">
28
+ {item.text}
29
+ </text>
30
+ </view>)}
31
+ </view> : null}
32
+ </view>
33
+
34
+ {visibleInlineActions.length > 0 ? <view className="doubao-map-card__inline-actions">
35
+ {visibleInlineActions.map((action, index)=><Button className="doubao-map-card__inline-action" key={index} size="mini" type={visibleInlineActions.length > 1 && 0 === index ? 'default' : 'primary'} text={action.text ?? ''} disabled={action.disabled} loading={action.loading} throttle={action.throttle} onClick={action.onClick}/>)}
36
+ </view> : null}
37
+ </view> : null}
38
+
39
+ <TemplateCardFooter primaryActionButton={footer?.primaryActionButton} secondaryActionButton={footer?.secondaryActionButton}/>
40
+ </view>;
41
+ }
42
+ const MapCard = forwardRef(MapCardImpl);
43
+ export { MapCard };
@@ -0,0 +1,110 @@
1
+ .doubao-map-card {
2
+ box-sizing: border-box;
3
+ background-color: var(--bg-base-1);
4
+ border: 1px solid var(--bg-base-2-overlay);
5
+ border-radius: 8px;
6
+ flex-direction: column;
7
+ align-items: stretch;
8
+ width: 100%;
9
+ display: flex;
10
+ overflow: hidden;
11
+ }
12
+
13
+ .doubao-map-card__viewport {
14
+ box-sizing: border-box;
15
+ border: 1px solid var(--bg-base-2-overlay);
16
+ flex-shrink: 0;
17
+ width: 100%;
18
+ height: 168px;
19
+ position: relative;
20
+ overflow: hidden;
21
+ }
22
+
23
+ .doubao-map-card__map {
24
+ width: 100%;
25
+ height: 100%;
26
+ }
27
+
28
+ .doubao-map-card__content {
29
+ box-sizing: border-box;
30
+ background-color: var(--bg-base-1);
31
+ border-radius: 8px;
32
+ flex-direction: row;
33
+ align-items: center;
34
+ gap: 12px;
35
+ width: 100%;
36
+ padding: 12px;
37
+ display: flex;
38
+ }
39
+
40
+ .doubao-map-card__text-content {
41
+ flex-direction: column;
42
+ flex: 1 1 0;
43
+ align-items: flex-start;
44
+ gap: 2px;
45
+ min-width: 0;
46
+ display: flex;
47
+ overflow: hidden;
48
+ }
49
+
50
+ .doubao-map-card__meta {
51
+ flex-direction: row;
52
+ flex-shrink: 0;
53
+ align-items: center;
54
+ width: 100%;
55
+ min-width: 0;
56
+ height: 22px;
57
+ display: flex;
58
+ overflow: hidden;
59
+ }
60
+
61
+ .doubao-map-card__meta-entry {
62
+ flex-direction: row;
63
+ flex: 0 auto;
64
+ align-items: center;
65
+ min-width: 0;
66
+ display: flex;
67
+ overflow: hidden;
68
+ }
69
+
70
+ .doubao-map-card__meta-separator {
71
+ color: var(--neutral-70);
72
+ flex-shrink: 0;
73
+ margin: 0 4px;
74
+ font-family: PingFang SC, sans-serif;
75
+ font-size: 13px;
76
+ font-weight: 400;
77
+ line-height: 1.5;
78
+ }
79
+
80
+ .doubao-map-card__meta-text {
81
+ min-width: 0;
82
+ color: var(--neutral-70);
83
+ text-overflow: ellipsis;
84
+ white-space: nowrap;
85
+ font-family: PingFang SC, sans-serif;
86
+ font-size: 13px;
87
+ font-style: normal;
88
+ font-weight: 400;
89
+ line-height: 1.5;
90
+ overflow: hidden;
91
+ }
92
+
93
+ .doubao-map-card__meta-text--highlight {
94
+ color: #ff375f;
95
+ }
96
+
97
+ .doubao-map-card__inline-actions {
98
+ flex-direction: row;
99
+ flex-shrink: 0;
100
+ align-items: center;
101
+ gap: 8px;
102
+ display: flex;
103
+ }
104
+
105
+ .doubao-map-card__inline-action {
106
+ width: auto;
107
+ min-width: 60px;
108
+ max-width: 100px;
109
+ }
110
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doubao-dev/template",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {