@doany-ai/目录
一个企业在它的网站上卖什么: 通过目录读取的钩子
给定 SDK 客户端 @doany-ai/app-core是因为 <DoanyProvider>默认值
一个站点可以通过主题重新样式,通过道具调整,或者
在保持钩子的同时替换.
网站只读目录. 出版的,可购买的,以及 价格是平台决定的;组件显示API的答案. 访问者只看到已公布的物品;网站列出自己的物品和那些 企业的每个地点都卖. 物品的添加和出售 代理商的业务工具, 从来没有从网站的代码.
需求 @doany-ai/app-core (单位:千美元)DoanyProvider)和一个客户端
@doany-ai/sdk 0.3.0-alpha.0 或更晚时. 它没有CSS: 地点的Tailwind
构建扫描(参见 @doany-ai/app-core) (中文(简体) ).
import { CatalogGrid, CatalogItemDetail } from "@doany-ai/catalog";
import { BuyButton } from "@doany-ai/commerce";
<CatalogGrid
params={{ purchasable: true }}
hrefFor={(item) => `/services/${item.id}`}
renderLink={({ href, className, children }) => <Link to={href} className={className}>{children}</Link>}
/>
<CatalogItemDetail
itemId={id}
actions={(variant, item) => variant && item.purchasable && <BuyButton items={[{ catalog_item_variant_id: variant.id }]}>Order now</BuyButton>}
/>
记录
CatalogItem数字 :id, (中文(简体) ),kind(单位:千美元)service编号 :physical编号 :digital编号 :plan编号 :bundle, (中文(简体) ),status(单位:千美元)draft编号 :active编号 :paused编号 :archived, (中文(简体) ),name, (中文(简体) ),description, (中文(简体) ),category, (中文(简体) ),image_url, (中文(简体) ),service_mode(单位:千美元)booking编号 :order编号 :inquiry,或null当他未分类的时候, 选项payment_requirement(单位:千美元)none编号 :full_online编号 :null, (中文(简体) ),direct_purchase_enabled, (中文(简体) ),purchasable(API决定网站资格),sort_order, (中文(简体) ),variants(按显示顺序排列). 这是在目录上标注之前 建造的工地的产物legacy_id(那个网站的id知道它)和attributes(字段为 网站在名称和价格之外保留,例如slug或者说color和它一样 留着吧 两者都只读,和{}编号 :null关于在《京都议定书》 目录.CatalogVariant数字 :id, (中文(简体) ),name, (中文(简体) ),price_amount(整数,最小货币) 单位;null=没有价格,0=免费,可选compare_at_amount(仅以同一种货币表示的参考价格),currency, (中文(简体) ),duration_minutes, (中文(简体) ),is_default(预选),status, (中文(简体) ),sku, (中文(简体) ),sort_order。 。 。 .
预订使用日历;调查需要确认引用. 他们的直接购买是
固定关闭。 订购服务有固定的直接购买,但收费网站
目前需要 full_online· ; none 可供商业订单使用.
零是免费的 null 谓无价相. 跟着API purchasable 结果.
过滤清晰的顺序服务 params={{ service_mode: "order", purchasable: true }}
或者说 useCatalogItems({ service_mode: "order" })服务查询表本身
没有命令或预约.
构成部分
每个组件都 locale (金钱;默认:浏览器的), labels 联合国
部分内容 CatalogLabels,见下文)和 className。 。 。 .
CatalogGrid
网格中的卡片,并有加载,空出和出错的状态和"更多".
| Prop | 类型 | |
|---|---|---|
params | { purchasable?, category?, kind?, type?, service_mode?, q?, sort?, limit? } | 哪些项目. sort数字 : sort_order (违约), name, (中文(简体) ), created_at, (中文(简体) ), updated_at, (中文(简体) ), - 在前面为下降. limit 1 - 200, 默认50 |
hrefFor | (item) => string | 每张卡片的链接 |
renderLink | ({ href, className, children }) => ReactNode | 链接如何显示; 平面 <a> 默认。 传路由器 Link 在网站上导航 |
onSelect | (item) => void | 将每张牌变成按钮 |
renderItem | (item) => ReactNode | 替换默认的牌 |
layout | "cards" | "list" | 默认 cards:盖上,以自动柱为中心瓦片. list: 一栏全宽,包括加载占位符;无384px平板盖或小计数盖 |
footer | ReactNode | (item) => ReactNode | 每张卡的价格 |
showDescription | boolean | |
appearance | "default" | "editorial" | "discovery" | "course" | 默认:紧凑牌. 编辑:景观媒体和标题。 发现:大方形被子,无边形布局,完整标题/结果和突出的导航 CTA; 课程:16:9被子,以标题和描述为中心,紧凑以CTA为中心,默认没有价格或类别;软件包拥有所有布局 |
showPrice | boolean | 默认 true; 在不更改 API 资格或选定变体的情况下隐藏显示的金额 |
media | ReactNode | (item) => ReactNode | 用配置的网站媒体替换每张卡片的图像 |
mediaOverlay | ReactNode | (item) => ReactNode | 对封面的独立预览控制, 在导航链接/按钮之外 |
formatLabel | ReactNode | (item) => ReactNode | 提供Online 课程或 1:1 辅导等格式,与主题分开; 在已专门用于一种格式的列表中省略 |
accessLabel | ReactNode | (item) => ReactNode | 提供访问/成员说明;保持可见 showPrice={false}仅列报,从未计算应享权利 |
eyebrow | ReactNode | (item) => ReactNode | 替换类别行 |
actionLabel | string | 每个链接/可选择的卡片内的导航提示; 发现时将其作为 CTA 文本( 默认为 labels.viewItem) (中文(简体) ). 这不是购买行动 |
empty | ReactNode | 显示为无所售出。 默认: empty 标签 |
对于服务价格行或全宽特性,请选择 layout="list"。 。 。 .
renderItem 单是刻意保持现有的卡片布局. 做一个
自定义行自己的列响应其可用的宽度,而不是屏幕 :
<CatalogGrid layout="list" renderItem={(item) => (
<article className="grid grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] gap-6 [&>*]:min-w-0">
<div><h3>{item.name}</h3><p>{item.description}</p></div>
<div><Price item={item} /><Button wrap asChild><Link to={`/services/${item.id}`}>Explore this service</Link></Button></div>
</article>
)} />
Price 从 @doany-ai/catalog, (中文(简体) ), Button 从
@doany-ai/app-core/ui/button,以及 Link 从网站的路由器。 用同样的
价格表头和行的响应列定义; 在窄处
容器堆放单元格并显示其标签。 不要隐藏溢出到
隐藏被剪切的文本或动作.
CatalogItemCard
图像、名称、类别、价格From … 当变量不同时)和持续时间.
| Prop | 类型 | |
|---|---|---|
item | CatalogItem | 所需经费 |
href | string | 让整张卡成为链接; 在发现时,只有明确的CTA是链接 |
onSelect | (item) => void | 使整张卡成为按钮; 在发现时, 只有明确的 CTA 是按钮 |
renderLink, (中文(简体) ), footer, (中文(简体) ), showDescription | 作为 CatalogGrid | |
appearance, (中文(简体) ), showPrice, (中文(简体) ), media, (中文(简体) ), mediaOverlay, (中文(简体) ), formatLabel, (中文(简体) ), accessLabel, (中文(简体) ), eyebrow, (中文(简体) ), actionLabel | 作为 CatalogGrid |
media, (中文(简体) ), eyebrow, (中文(简体) ), formatLabel 财务报告和审定财务报表 accessLabel 请坐 内部 全卡链接或
按钮。 保持它们不互动( 图像或哑音)
预览视频无控件). 单独的预览控件属于 mediaOverlay· ;
额外的播放/购买控制可以使用 footer。两个槽仍然处于导航之外.
默认和编辑上线与软件包的4:3和16:10媒体领域一致;自定义
媒体应保持这些比例。 发现使用一个平面覆盖和一个单独的CTA,
因此预览按钮永远无法激活课程链接. 其CTA包括项目名称
用于辅助技术。 一个交互式插槽需要自己的无障碍标签.
媒体配置和页面副本来自网站;可重复使用的卡片布局将保留
在这里。 这些档次不改变产品分类,准入或购买规则.
<CatalogGrid
appearance="editorial"
showPrice={false}
hrefFor={(item) => `/collections/${item.id}`}
actionLabel="Explore collection"
media={(item) => <img src={posters[item.id]} alt={item.name} />}
footer={(item) => <button onClick={() => openPreview(item.id)}>Watch preview</button>}
/>
对于课程的发现,使用 appearance="course":一个16:9的封面,以课程标题和描述为中心,以及一个紧凑的CTA. 显示一个
与细节页有明确的链接。 在此收藏中明确隐藏价格; 细节
报价保留其价格。 使用 eyebrow="" 以略去冗余的话题行,以及
formatLabel 只有在环境需要的时候 既不是这种外表,也不是隐藏
价格改变通用目录默认值,或决定某一物品是否可以购买.
<CatalogGrid
appearance="course"
showPrice={false}
eyebrow=""
actionLabel="View course"
hrefFor={(item) => `/courses/${item.id}`}
media={(item) => <img src={posters[item.id]} alt="" />}
mediaOverlay={(item) => <button onClick={() => openPreview(item.id)}>Preview<span className="sr-only"> {item.name}</span></button>}
accessLabel={(item) => accessNotes[item.id]}
/>
出入说明书由场地从其核准的预测中提供 并不从产品类型、价格或浏览器本地状态推断成员.
CatalogItemDetail
某物品的页面:图像,名称,描述,变种采取者和价格 选择的变体.
| Prop | 类型 | |
|---|---|---|
itemId | string | 由id读取.. |
item | CatalogItem | ...或显示为给定 |
actions | (variant | null, item) => ReactNode | 备选案文:如何处理所选变式,例如a BuyButton |
variantId, (中文(简体) ), onVariantChange | string | null, (中文(简体) ), (variantId) => void | 共享英雄/侧边栏/移动购买位置的可选控制选择;省略以保留本地选择。 缺少或不活跃的ID通过软件包的默认变量规则返回 |
notFound | ReactNode | 项目不存在或未公布。 默认: notAvailable 标签 |
appearance | "default" | "editorial" | 社论使用地貌媒体和显著标题,有相同的查询/选择/行动 |
media | ReactNode | 替换项目图像; 由站点配置 |
showMedia | boolean | 默认 true· ; false 删除整个媒体栏(包括自定义) media 和装入占位符),用于压缩摘要 |
headingLevel | 1 | 2 | 3 | 默认 1; 当项目摘要位于现有页面标题下方时, 匹配页面的标题等级 |
eyebrow | ReactNode | 替换类别行 |
showPrice | boolean | 默认 true; 当错误时, 隐藏所选价格和取取出的数量; 选项和行动参数保持不变 |
在现场的英雄之下买东西 <h1>,使用时
<CatalogItemDetail itemId={id} headingLevel={2} showMedia={false} actions={...} />。 。 。 .
项目查询、价格变化选择和行动投入保持不变;
没有空图像列。 这个 detail 下面的道具示例运行此程序
由二级标题组成.
VariantPicker
以收音机组为单位定价的活性变体;一件物品没有单向销售.
| Prop | 类型 | |
|---|---|---|
variants | CatalogVariant[] | 所需经费 |
value | string | null | 所选变体的 id |
onChange | (variantId) => void | 所需经费 |
includeUnpriced | boolean | 也提供无价变体(不能订购)。 默认 false |
label | string | 屏幕阅读器; 胜过 options |
showPrice | boolean | 默认 true; 仅演示文稿, 不允许非价格选择 |
Price
variant (一价)或 item (一种价格,或 From … 当它的变体
差异); fallback 当无价(默认:无)时.
钩子
| 钩子 | 回返 |
|---|---|
useCatalogItems(params) | 网站的项目,一个网页一次, sort_order 第一条: items (所有页阅读至今), isLoading, (中文(简体) ), isError, (中文(简体) ), hasNextPage, (中文(简体) ), fetchNextPage()。 。 。 . params 作为 CatalogGrid |
useCatalogItem(itemId) | 查询; data 是其活动变量的项目 |
useVariantSelection(item, { value?, onChange? }) | { variant, select(variantId) }:从项目的默认变体开始,跟随新项目;非项目的代号倒回默认. 可选可控输入在多个选项中共享一个选项 |
显示所使用的组件的帮助 : itemPriceLabel(item, locale?, words?), (中文(简体) ),
variantPriceLabel(variant, locale?, words?) (文本,或 null 当没有
价格, formatDuration(minutes) (单位:千美元)1 h 30 min, (中文(简体) ), pricedVariants(item), (中文(简体) ),
defaultVariant(item)。 。 。 . catalogKeys 是反应查询键,用于
无效 .
标签
组件显示的每个字 CatalogLabels组成部分参与
以物配主,以物配主,并传达给里面的人
它(一个网格取出它的牌,一个项页取出它的取出者). defaultCatalogLabels
持有默认值; catalogLabels(partial) 合并.
| 密钥 | 默认 |
|---|---|
free | 免费 |
fromPrice | (price) => "From " + price |
duration | (minutes) => "45 min", (中文(简体) ), "1 h 30 min" |
options | 选项( 屏幕读取器) |
empty | 这里还没有. |
loadError | 无法装入目录 。 (除非设定,否则平台本身的信息会显示) |
tryAgain | 再试一次 |
loadMore | 装入更多 |
loadingMore | 正在装入.. |
notAvailable | 本项目不详. |
viewItem | 查看细节( 发现 CTA; 明确 actionLabel 赢) |
自定义
停止第一级,即满足需要:
-
支助科: 主题变量
:root(见@doany-ai/app-core) (中文(简体) ). -
道具:上面的插槽和道具,以及
labels每个字:<CatalogGrid labels={{ loadMore: "Show more", free: "Complimentary", duration: (m) => `${m} minutes` }} /> -
钩子: 将列表或项目页面建入
useCatalogItems, (中文(简体) ),useCatalogItem财务报告和审定财务报表useVariantSelection,与itemPriceLabel编号 :variantPriceLabel价格问题.
从不编辑此软件包 node_modules 或将其来源复制到网站.
4个可循环用途
官方实例 @doany-ai/catalog/examples每个更改
构成部分有四种用法: grid, (中文(简体) ), card, (中文(简体) ), detail,以及 picker。 。 。 .
import { CatalogExamples } from "@doany-ai/catalog/examples";
<CatalogExamples component="grid" mode="default" />
<CatalogExamples component="grid" mode="css" />
<CatalogExamples component="grid" mode="props" />
<CatalogExamples component="grid" mode="hook" />
default: 实际软件包组件及其查询/选择行为.css: 相同的组件道具,并有一套被范围化的主题变量. 这些 示例中没有门户;一个真实的网站的全球主题属于:root。 。 。 .props:包自有的编辑外观,标签/相机和价格能见度.hook: 使用明确的自定义标记useCatalogItems, (中文(简体) ),useCatalogItem财务报告和审定财务报表useVariantSelection;格式化仍然使用软件包的价格帮助.
同样的4个卡/网格用法可以显示发现的演示:
<CatalogExamples component="card" appearance="course" mode="default" />
<CatalogExamples component="card" appearance="course" mode="css" />
<CatalogExamples component="card" appearance="course" mode="props" />
<CatalogExamples component="card" appearance="course" mode="hook" />
默认和CSS只拥有相同的组件道具和记录. 支持添加一个 明确格式/访问注释和自定义 CTA; 仅用钩子构建接口 真正的目录查询。 每个发现实例都有单独的预览和视图 进程动作: 预览报告选定的本地样本, 不进行导航或 声称要演拖车 打电话者提供实际的媒体和玩家行为.
onSelect(item) 可以观察选择。 每个例子都有自己的地方
DoanyProvider 并查询缓存。 导出 catalogExampleItems 财务报告和审定财务报表
createCatalogExampleClient(items?, pageSize = 2) 并让预览作曲
一个提供者中的软件包组件。 客户端回复本地目录列表/ get,
支持显示的过滤器、名称排序和页码,并拒绝
账户/上载/移动能力 EXAMPLE_ONLY它从不叫
腾讯网. 这些说明性的数字记录没有建立Course API,
授权、订阅、下载交付或离职合同。 生产
页面使用网站真正的SDK客户端,而不是这个示例适配器.
开发
npm run typecheck 包含 tests/sdk-contract.types.ts真实的
@doany-ai/sdk 客户端( 来自 ../doany-sdk)必须满足客户类型
软件包的呼叫,所以一个变更的SDK合同在这里失败,而不是在一个站点.
CatalogItemDetail appearance="summary" 使用紧凑的标题并默认隐藏长描述用于购买侧边栏和关闭动作. showDescription 可推翻演示文稿;选项选择、实际价格,以及 actions(variant, item) 保持同样的行为。 官方道具的例子表明了这种外观.
可选原价
Price 财务报告和审定财务报表 CatalogItemDetail 显示击穿 compare_at_amount 提供
按当前旁的目录 price_amount. 缺失/参考价格
只有当前价格。 项目价格范围没有参考价格,除非每个
定价的变种既分享金额又分享货币。 选择另一个变体更新
这两笔金额. showCompareAt={false} 隐藏引用; labels.currentPrice 财务报告和审定财务报表
labels.originalPrice 自定义屏幕阅读器措辞 。 命令和退房总是
使用情况 price_amount;参考金额从来不是收费或客户折扣.
所有四种用途都可用 <CatalogExamples component="price" mode={mode} />数字 :
default,仅限主题 css,措辞 props,以及 hook 使用 useCatalogItem, (中文(简体) ),
useVariantSelection, (中文(简体) ), variantPriceLabel 财务报告和审定财务报表 compareAtPriceLabel 与定制标记.