@doubao-dev/template 0.0.39 → 0.0.41

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
@@ -105,6 +105,8 @@ import { Price } from '@doubao-dev/template/primitives';
105
105
 
106
106
  <Price value="1636.92" prefix="均" suffix="券后价" description="销量100+" />
107
107
 
108
+ <Price value="1636.92" prefix="券后" prefixTone="muted" tone="highlight" />
109
+
108
110
  <Price value={1636.92} tone="highlight" originalPrice={2000} />
109
111
  ```
110
112
 
@@ -113,12 +115,13 @@ import { Price } from '@doubao-dev/template/primitives';
113
115
  - `value` 支持 `string | number`;需要保留前导零或末尾小数位时传字符串。
114
116
  - `currency` 默认是 `¥`,传空字符串可隐藏币种符号。
115
117
  - `tone="highlight"` 使用营销强调色;默认色跟随当前主题。
118
+ - `prefixTone` 支持 `default | highlight | muted`,分别对应主文字色、营销红和 `--neutral-70`;不传时前缀与价格值颜色一致。
116
119
  - `loading` 展示最大宽度为 60% 的扫光占位。
117
120
  - `className` 和 `style` 可用于样式定制。
118
121
 
119
122
  ## ContentCard
120
123
 
121
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/content-card.png" alt="ContentCard 示例" width="400" />
124
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/content-card.png" alt="ContentCard 示例" width="400" />
122
125
 
123
126
  通用列表卡,由标题栏、列表内容和底部操作区组成,适合商品、服务、内容入口等可重复条目。
124
127
 
@@ -160,7 +163,7 @@ import { ContentCard } from '@doubao-dev/template';
160
163
 
161
164
  ## PriceActionCard
162
165
 
163
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/price-action-card.png" alt="PriceActionCard 示例" width="400" />
166
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/price-action-card.png" alt="PriceActionCard 示例" width="400" />
164
167
 
165
168
  价格操作卡,由多条"价格 + 信息 + 右侧按钮"组成,适合报价、权益、服务方案等结果列表。
166
169
 
@@ -193,7 +196,7 @@ import { PriceActionCard } from '@doubao-dev/template';
193
196
 
194
197
  ## CheckoutCard
195
198
 
196
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/checkout-card.png" alt="CheckoutCard 示例" width="400" />
199
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/checkout-card.png" alt="CheckoutCard 示例" width="400" />
197
200
 
198
201
  通用提单卡,由商品摘要、提单信息、费用汇总和底部操作区组成,适合下单确认、支付确认等场景。
199
202
 
@@ -244,7 +247,7 @@ import { CheckoutCard } from '@doubao-dev/template';
244
247
 
245
248
  ## TicketOrderCard
246
249
 
247
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/ticket-checkout-card.png" alt="TicketOrderCard 示例" width="400" />
250
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/ticket-checkout-card.png" alt="TicketOrderCard 示例" width="400" />
248
251
 
249
252
  > **已废弃:** 请使用 `CheckoutCard`。`TicketOrderCard` 仅为兼容现有代码保留。
250
253
 
@@ -291,7 +294,7 @@ import { TicketOrderCard } from '@doubao-dev/template';
291
294
 
292
295
  ## TransitCard
293
296
 
294
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/transit-card.png" alt="TransitCard 示例" width="400" />
297
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/transit-card.png" alt="TransitCard 示例" width="400" />
295
298
 
296
299
  交通票务列表卡,由多条出发、中转、到达和价格信息组成,适合展示机票、火车票、大巴等推荐列表。
297
300
 
@@ -308,7 +311,16 @@ import { TransitCard } from '@doubao-dev/template';
308
311
  arrivalMain: '12:32',
309
312
  arrivalDayOffset: '+1',
310
313
  arrivalSub: '上海虹桥',
311
- price: '¥553'
314
+ price: {
315
+ value: '553',
316
+ currency: '¥',
317
+ prefix: '前缀',
318
+ tone: 'highlight'
319
+ },
320
+ tag: {
321
+ text: '可优惠约¥5',
322
+ tone: 'marketing'
323
+ }
312
324
  }
313
325
  ]}
314
326
  footer={{
@@ -322,12 +334,15 @@ import { TransitCard } from '@doubao-dev/template';
322
334
  说明:
323
335
 
324
336
  - `items` 会全量展示,模板不做"最多 4 条"的截断。
325
- - `title`、`transfer`、`price` 接收 `ReactNode`,适合需要自定义整块区域的场景。
337
+ - `price` 推荐传 `{ value, currency?, prefix?, prefixTone?, tone? }`,由模板使用 `Price` Primitive 渲染;`currency` 默认是 `¥`,不传 `prefixTone` 时前缀与价格值颜色一致。
338
+ - `price` 传数字时直接作为 `Price.value`,使用默认币种;传字符串时按首个币种符号拆为 `prefix + currency + value`,没有币种符号时整串作为 `value` 并隐藏币种。两种写法均使用 Price 的默认 `tone`。
339
+ - `tag` 传 `{ text, tone? }`,`tone` 仅支持红色 `marketing` 和灰色 `neutral`,默认 `marketing`;不传 `tag` 时保持原来的单价格布局。
340
+ - `title`、`transfer` 接收 `ReactNode`,适合需要自定义整块区域的场景。
326
341
  - `departureMain`、`departureSub`、`transferTop`、`transferBottom`、`arrivalMain`、`arrivalDayOffset`、`arrivalSub` 接收字符串或数字。
327
342
 
328
343
  ## AskHumanCard
329
344
 
330
- <img src="https://unpkg.com/@doubao-dev/template@0.0.39/assets/ask-human-card.png" alt="AskHumanCard 示例" width="400" />
345
+ <img src="https://unpkg.com/@doubao-dev/template@0.0.41/assets/ask-human-card.png" alt="AskHumanCard 示例" width="400" />
331
346
 
332
347
  人工确认选项卡,由一组选项组成,适合让用户在多个候选项中确认选择。
333
348
 
@@ -24,6 +24,8 @@ export interface TemplateTransportSummaryProps {
24
24
  arrivalSub?: TemplateText;
25
25
  /** 价格块内容。 */
26
26
  price?: ReactNode;
27
+ /** 价格下方的标签内容。 */
28
+ tag?: ReactNode;
27
29
  /** 根节点自定义类名。 */
28
30
  className?: string;
29
31
  }
@@ -33,6 +33,15 @@ function renderTemplateTransportSummaryTextField(content, wrapperClassName, text
33
33
  </text>
34
34
  </view>;
35
35
  }
36
+ function renderTemplateTransportSummaryPrice(price, tag) {
37
+ const hasPrice = !isTemplateTransportSummaryNodeEmpty(price);
38
+ const hasTag = !isTemplateTransportSummaryNodeEmpty(tag);
39
+ if (!hasPrice && !hasTag) return null;
40
+ return <view className={clsx('doubao-template-transport-summary__price', hasTag && 'doubao-template-transport-summary__price--with-tag')}>
41
+ {hasPrice && price}
42
+ {hasTag && tag}
43
+ </view>;
44
+ }
36
45
  function TemplateTransportSummaryArrowIcon({ showDot }) {
37
46
  const theme = useTheme();
38
47
  return <svg className="doubao-template-transport-summary__transfer-arrow-icon" content={getTransportSummaryArrowSvgContent(Boolean(showDot), 'dark' === theme)}/>;
@@ -70,7 +79,7 @@ function renderTemplateTransportSummaryTransfer({ content, topText, showDot, bot
70
79
  </view>;
71
80
  }
72
81
  function TemplateTransportSummary(props) {
73
- const { title, departureMain, departureSub, transfer, transferTop, showTransferDot, transferBottom, arrivalMain, arrivalDayOffset, arrivalSub, price, className } = props;
82
+ const { title, departureMain, departureSub, transfer, transferTop, showTransferDot, transferBottom, arrivalMain, arrivalDayOffset, arrivalSub, price, tag, className } = props;
74
83
  const departureNode = renderTemplateTransportSummaryPoint({
75
84
  mainText: departureMain,
76
85
  subText: departureSub
@@ -89,7 +98,7 @@ function TemplateTransportSummary(props) {
89
98
  const arrivalDayOffsetNode = null == arrivalPointNode ? null : renderTemplateTransportSummaryArrivalDayOffset(arrivalDayOffset);
90
99
  const arrivalNode = null == arrivalPointNode ? null : <view className="doubao-template-transport-summary__arrival">{arrivalPointNode}</view>;
91
100
  const titleNode = renderTemplateTransportSummaryNodeField(title, 'doubao-template-transport-summary__title', 'doubao-template-transport-summary__title-text');
92
- const priceNode = renderTemplateTransportSummaryNodeField(price, 'doubao-template-transport-summary__price', 'doubao-template-transport-summary__price-text');
101
+ const priceNode = renderTemplateTransportSummaryPrice(price, tag);
93
102
  const hasRoute = Boolean(departureNode || transferNode || arrivalNode);
94
103
  const hasRouteRow = Boolean(hasRoute || priceNode);
95
104
  if (null == titleNode && !hasRouteRow) return null;
@@ -23,7 +23,7 @@
23
23
  height: 20px;
24
24
  }
25
25
 
26
- .doubao-template-transport-summary__title-text, .doubao-template-transport-summary__route-point-main-text, .doubao-template-transport-summary__arrival-day-offset-text, .doubao-template-transport-summary__route-point-sub-text, .doubao-template-transport-summary__transfer-label-text, .doubao-template-transport-summary__price-text {
26
+ .doubao-template-transport-summary__title-text, .doubao-template-transport-summary__route-point-main-text, .doubao-template-transport-summary__arrival-day-offset-text, .doubao-template-transport-summary__route-point-sub-text, .doubao-template-transport-summary__transfer-label-text {
27
27
  text-overflow: ellipsis;
28
28
  white-space: nowrap;
29
29
  font-family: PingFang SC, sans-serif;
@@ -132,9 +132,9 @@
132
132
 
133
133
  .doubao-template-transport-summary__arrival-day-offset-text {
134
134
  color: var(--neutral-100);
135
- font-size: 11px;
135
+ font-size: 10px;
136
136
  font-weight: 400;
137
- line-height: 14px;
137
+ line-height: normal;
138
138
  }
139
139
 
140
140
  .doubao-template-transport-summary__route-point-sub-text {
@@ -203,12 +203,8 @@
203
203
  padding: 0 4px;
204
204
  }
205
205
 
206
- .doubao-template-transport-summary__price-text {
207
- color: var(--pink-500);
208
- text-align: right;
209
- font-family: SF Pro, sans-serif;
210
- font-size: 17px;
211
- font-weight: 600;
212
- line-height: 22px;
206
+ .doubao-template-transport-summary__price--with-tag {
207
+ gap: 4px;
208
+ height: 46px;
213
209
  }
214
210
 
@@ -137,7 +137,9 @@
137
137
  }
138
138
 
139
139
  .doubao-content-card__item-action-button {
140
- width: 80px;
140
+ width: auto;
141
+ min-width: 60px;
142
+ max-width: 100px;
141
143
  }
142
144
 
143
145
  .doubao-content-card__item-action-switch {
package/dist/index.d.ts CHANGED
@@ -5,7 +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 { TransitCard, type TransitCardItem, type TransitCardProps } from './transit-card/index.js';
8
+ export { TransitCard, type TransitCardItem, type TransitCardPrice, type TransitCardProps, type TransitCardTag } from './transit-card/index.js';
9
9
  export type { TemplateKey, TemplateTagTone, TemplateText } from './types.js';
10
10
  export { TicketOrderCard, type TicketOrderCardFeeItem, type TicketOrderCardInfoItem, type TicketOrderCardProps, type TicketOrderCardRouteItem } from './ticket-order-card/index.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -141,7 +141,9 @@
141
141
  --doubao-button-default-bg: var(--bg-base-1-overlay);
142
142
  --doubao-button-default-text: var(--neutral-100);
143
143
  flex-shrink: 0;
144
- width: 80px;
144
+ width: auto;
145
+ min-width: 60px;
146
+ max-width: 100px;
145
147
  height: 38px;
146
148
  }
147
149
 
@@ -1,4 +1,4 @@
1
- export { Price, type PriceProps, type PriceTone, type PriceValue } from './price/index.js';
1
+ export { Price, type PricePrefixTone, type PriceProps, type PriceTone, type PriceValue } from './price/index.js';
2
2
  export { Tag, type TagProps, type TagTone, type TagValue } from './tag/index.js';
3
3
  export { Title, type TitleMaxLines, type TitleProps, type TitleValue } from './title/index.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import type { PriceProps } from './types.js';
2
2
  import './styles.scss';
3
- export type { PriceProps, PriceTone, PriceValue } from './types.js';
4
- export declare function Price({ value, currency, prefix, suffix, description, originalPrice, tone, loading, className, style }: PriceProps): any;
3
+ export type { PricePrefixTone, PriceProps, PriceTone, PriceValue } from './types.js';
4
+ export declare function Price({ value, currency, prefix, prefixTone, suffix, description, originalPrice, tone, loading, className, style }: PriceProps): any;
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -17,7 +17,7 @@ function formatOriginalPrice(value, currency) {
17
17
  const originalPrice = String(value);
18
18
  return currency && originalPrice.startsWith(currency) ? originalPrice : `${currency}${originalPrice}`;
19
19
  }
20
- function Price({ value, currency = '¥', prefix, suffix, description, originalPrice, tone = 'default', loading = false, className, style }) {
20
+ function Price({ value, currency = '¥', prefix, prefixTone, suffix, description, originalPrice, tone = 'default', loading = false, className, style }) {
21
21
  const themedClassName = useThemeClassName(className);
22
22
  const { integer, decimal } = splitPriceValue(value);
23
23
  return <view className={clsx('doubao-price', `doubao-price--tone-${tone}`, {
@@ -26,7 +26,9 @@ function Price({ value, currency = '¥', prefix, suffix, description, originalPr
26
26
  {loading ? <view className="doubao-price__placeholder"/> : <>
27
27
  <view className="doubao-price__amount">
28
28
  {prefix ? <view className="doubao-price__affix">
29
- <text className="doubao-price__prefix">{prefix}</text>
29
+ <text className={clsx('doubao-price__prefix', prefixTone && `doubao-price__prefix--tone-${prefixTone}`)}>
30
+ {prefix}
31
+ </text>
30
32
  </view> : null}
31
33
 
32
34
  <view className="doubao-price__main">
@@ -76,6 +76,18 @@
76
76
  line-height: 11px;
77
77
  }
78
78
 
79
+ .doubao-price__prefix.doubao-price__prefix--tone-default {
80
+ color: var(--neutral-100);
81
+ }
82
+
83
+ .doubao-price__prefix.doubao-price__prefix--tone-highlight {
84
+ color: #ff375f;
85
+ }
86
+
87
+ .doubao-price__prefix.doubao-price__prefix--tone-muted {
88
+ color: var(--neutral-70);
89
+ }
90
+
79
91
  .doubao-price__currency {
80
92
  font-size: 13px;
81
93
  font-weight: 500;
@@ -1,6 +1,7 @@
1
1
  import type { CSSProperties } from '@lynx-js/types';
2
2
  export type PriceValue = string | number;
3
3
  export type PriceTone = 'default' | 'highlight';
4
+ export type PricePrefixTone = 'default' | 'highlight' | 'muted';
4
5
  export interface PriceProps {
5
6
  /** 价格值。传入字符串时会保留前导零和末尾小数位。 */
6
7
  value: PriceValue;
@@ -8,6 +9,8 @@ export interface PriceProps {
8
9
  currency?: string;
9
10
  /** 价格前缀,例如“均”“起”。 */
10
11
  prefix?: string;
12
+ /** 价格前缀色调。不传时跟随价格色调。 */
13
+ prefixTone?: PricePrefixTone;
11
14
  /** 价格后缀,例如“券后价”“/10斤”。 */
12
15
  suffix?: string;
13
16
  /** 价格后的辅助说明,例如“销量100+”。 */
@@ -2,6 +2,8 @@ import type { CSSProperties, TouchEvent } from '@lynx-js/types';
2
2
  import type { ReactElement, ReactNode } from 'react';
3
3
  import { type TemplateCardFooterProps } from '../components/footer/index.js';
4
4
  import { type TemplateCardHeaderProps } from '../components/header/index.js';
5
+ import { type PricePrefixTone, type PriceTone, type PriceValue } from '../primitives/price/index.js';
6
+ import { type TagValue } from '../primitives/tag/index.js';
5
7
  import type { TemplateKey, TemplateText } from '../types.js';
6
8
  import './styles.scss';
7
9
  export interface TransitCardProps {
@@ -39,8 +41,10 @@ export interface TransitCardItem {
39
41
  arrivalDayOffset?: TemplateText;
40
42
  /** 到达点补充信息文案。 */
41
43
  arrivalSub?: TemplateText;
42
- /** 价格块内容。 */
43
- price?: ReactNode;
44
+ /** 价格配置或价格块内容。 */
45
+ price?: TransitCardPrice | ReactNode;
46
+ /** 价格下方的标签配置。 */
47
+ tag?: TransitCardTag;
44
48
  /** 列表项根节点自定义类名。 */
45
49
  className?: string;
46
50
  /** 列表项根节点自定义样式。 */
@@ -48,5 +52,23 @@ export interface TransitCardItem {
48
52
  /** 点击列表项时触发。 */
49
53
  onClick?: (event: TouchEvent) => void;
50
54
  }
55
+ export interface TransitCardPrice {
56
+ /** 价格值。 */
57
+ value: PriceValue;
58
+ /** 币种符号。 */
59
+ currency?: string;
60
+ /** 价格前缀。 */
61
+ prefix?: string;
62
+ /** 价格前缀色调。不传时跟随价格色调。 */
63
+ prefixTone?: PricePrefixTone;
64
+ /** 价格色调。 */
65
+ tone?: PriceTone;
66
+ }
67
+ export interface TransitCardTag {
68
+ /** 标签内容。 */
69
+ text: TagValue;
70
+ /** 标签色调;marketing 为红色,neutral 为灰色,默认 marketing。 */
71
+ tone?: 'marketing' | 'neutral';
72
+ }
51
73
  export declare function TransitCard(props: TransitCardProps): ReactElement;
52
74
  //# sourceMappingURL=index.d.ts.map
@@ -3,12 +3,34 @@ import { clsx } from "clsx";
3
3
  import { TemplateCardFooter } from "../components/footer/index.js";
4
4
  import { TemplateCardHeader } from "../components/header/index.js";
5
5
  import { TemplateTransportSummary } from "../components/transport-summary/index.js";
6
+ import { Price } from "../primitives/price/index.js";
7
+ import { Tag } from "../primitives/tag/index.js";
6
8
  import "./styles.css";
9
+ function isTransitCardPriceConfig(price) {
10
+ return null != price && 'object' == typeof price && !Array.isArray(price) && 'value' in price;
11
+ }
12
+ function renderTransitCardTextPrice(price) {
13
+ if ('' === price) return null;
14
+ const matched = price.match(/^(.*?)([¥¥$€£₩₽₹])(.*)$/);
15
+ if (null == matched) return <Price value={price} currency=""/>;
16
+ const [, prefix, currency, value] = matched;
17
+ return <Price value={value} currency={currency} prefix={prefix || void 0}/>;
18
+ }
19
+ function renderTransitCardPrice(price) {
20
+ if ('number' == typeof price) return <Price value={price}/>;
21
+ if ('string' == typeof price) return renderTransitCardTextPrice(price);
22
+ if (isTransitCardPriceConfig(price)) return <Price value={price.value} currency={price.currency} prefix={price.prefix} prefixTone={price.prefixTone} tone={price.tone}/>;
23
+ return price;
24
+ }
25
+ function renderTransitCardTag(tag) {
26
+ if (null == tag || '' === tag.text) return null;
27
+ return <Tag text={tag.text} tone={tag.tone ?? 'marketing'}/>;
28
+ }
7
29
  function renderTransitCardItem({ item, index, isLast }) {
8
30
  return <view className={clsx('doubao-transit-card__item', isLast && 'doubao-transit-card__item--last', item.className)} style={item.style} key={item.key ?? index} {...null != item.onClick ? {
9
31
  catchtap: item.onClick
10
32
  } : {}}>
11
- <TemplateTransportSummary className="doubao-template-transport-summary--list" title={item.title} departureMain={item.departureMain} departureSub={item.departureSub} transfer={item.transfer} transferTop={item.transferTop} transferBottom={item.transferBottom} arrivalMain={item.arrivalMain} arrivalDayOffset={item.arrivalDayOffset} arrivalSub={item.arrivalSub} price={item.price}/>
33
+ <TemplateTransportSummary className="doubao-template-transport-summary--list" title={item.title} departureMain={item.departureMain} departureSub={item.departureSub} transfer={item.transfer} transferTop={item.transferTop} transferBottom={item.transferBottom} arrivalMain={item.arrivalMain} arrivalDayOffset={item.arrivalDayOffset} arrivalSub={item.arrivalSub} price={renderTransitCardPrice(item.price)} tag={renderTransitCardTag(item.tag)}/>
12
34
  {!isLast && <view className="doubao-transit-card__item--spread"/>}
13
35
  </view>;
14
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doubao-dev/template",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {