@askdialog / dialog-vue
用于Dialog ai产品辅助的Vue 3组件库。
目录表
安装
npm install @askdialog/dialog-vue @askdialog/dialog-sdk
# or
pnpm add @askdialog/dialog-vue @askdialog/dialog-sdk
# or
yarn add @askdialog/dialog-vue @askdialog/dialog-sdk
使用
<script setup lang="ts">
import { Dialog } from '@askdialog/dialog-sdk';
import { DialogProductBlock } from '@askdialog/dialog-vue';
import '@askdialog/dialog-vue/style.css';
const client = new Dialog({
apiKey: 'your-api-key',
locale: 'en', currency: 'EUR',
callbacks: {
addToCart: () => Promise.resolve(),
getProduct: () => Promise.resolve({
// Product data
}),
},
});
</script>
<template>
<DialogProductBlock
:client="client"
product-id="product-123"
product-title="Product Name"
/>
</template>
可用的组件
DialogProductBlock
产品块,最多有2个产品问题和一个“问别的”按钮,打开助手,最多有5个关于产品的产品问题。按钮标签根据客户端的语言环境使用英语、法语或西班牙语(否则使用英语)。
道具:
client(Dialog) - Dialog SDK客户端实例(必需)productId(字符串)-产品编号(必需)productTitle(字符串)-产品名称(必需)selectedVariantId(字符串,可选)-选定的变体IDenableInput(boolean,可选)-已弃用。显示输入字段,而不是“Ask something else”按钮(默认值:false)
例子:
<DialogProductBlock
:client="client"
product-id="9403924119882"
product-title="Blizzard King All-Mountain Snowboard"
selected-variant-id="variant-123"
/>
DialogInput
用于提问的独立输入组件。它显示了固定的“问AI一个问题”文本和AI披露行,根据客户端区域使用英语,法语或西班牙语(否则为英语)。
道具:
client(Dialog) - Dialog SDK客户端实例(必需)productId(字符串)-产品编号(必需)productTitle(字符串)-产品名称(必需)placeholder(字符串,可选)-已弃用,忽略selectedVariantId(字符串,可选)-选定的变体ID
例子:
<DialogInput
:client="client"
product-id="9403924119882"
product-title="Product Name"
/>
店面搜索
useDialogSearch 绑定SDK搜索控制器(createSearchController 从 @askdialog/dialog-sdk)到组件状态。控制器管理请求、商家的配置和分析;组件读取它的连接器(connectSearchBox, connectHits, connectSections, connectPagination),只处理渲染。文本,显示规则,标题突出显示,价格和主题来自SDK。
<script setup lang="ts">
import { Dialog } from '@askdialog/dialog-sdk';
import {
DialogSearchBar,
DialogSearchResults,
useDialogSearch,
} from '@askdialog/dialog-vue';
import '@askdialog/dialog-vue/style.css';
const client = new Dialog({ apiKey: 'your-api-key', locale: 'en-US', currency: 'USD' });
const { controller, state, theme } = useDialogSearch({ client, language: 'en', country: 'US' });
</script>
<template>
<DialogSearchBar :controller="controller" placeholder="Search products..." />
<DialogSearchResults :controller="controller" :state="state" :theme="theme" />
</template>
useDialogSearch
为每个可组合实例创建一个搜索控制器,并在卸载时对其进行处理。控制器在第一个焦点或搜索中加载带有客户端API密钥的商家业务排名,用于空查询产品的标题。
选项:
client(Dialog) - Dialog SDK客户端实例(必需)language(字符串,必需)-小写的ISO 639-1语言代码,例如:frcountry(字符串,必选)-购物者的ISO 3166-1 alpha-2国家,例如。BE;价格随市场而定surface(SearchSurface,可选)-显示结果的地方,用于分析(默认:'search_page')navigate((url, hit: SearchProductHit) => void, optional) -选择属性后调用的路由器适配器(例如:(url) => router.push(url)). 省略它,让卡片更清晰<a href>链接本地导航。storefrontRoot(字符串,可选)-命中的相对路径_display.url解决以下问题,例如:/或者/fr-fr/(Shopifywindow.Shopify.routes.root); 默认的/buildProductUrl(已弃用,忽略)-每个命中的链接都是它的_display.urldebounceMs(数字,可选)-击键计数(默认:100)hitsPerPage(数目,可选)-每页结果(默认:12)sections(SearchSection[],可选)-与产品一起搜索的额外索引;collections的集合列DialogSearchResults. 只请求目录公开的索引:缺少索引将使整个搜索失败。
搜索语言和国家是明确而独立的 client.locale,它可以是区域区域设置,例如 fr-FR.
在设置过程中读取一次选项-以后的更改不会重新绑定活动控制器。
返回: { controller, state, theme } -将它们传递给下面的组件; theme 客户的主题是什么 DialogSearchResults. controller 是SDK的 SearchController,也可以将其传递给的连接器 @askdialog/dialog-sdk 用于自定义UI。 state 是一个 ShallowRef 控制器快照的: state.value.searchState (顾客的要求), state.value.results (status 是 idle / loading / success / empty / error, products, sections, error), state.value.context (语言、国家、企业排名、文本)。
对于公开集合索引的目录,使用collections列:
const { controller, state, theme } = useDialogSearch({
client,
language: 'en',
country: 'US',
sections: [{ index: 'collections', hitsPerPage: 5 }],
});
DialogSearchBar
搜索输入 connectSearchBox:输入将运行一个未绑定的搜索,立即提交(Enter)搜索。聚焦输入打开搜索,它发出 TRACK_OPENED_SEARCH 如果还没有查询,则显示空查询产品。
道具:
controller(SearchController) - FromuseDialogSearch(必需)placeholder(字符串,可选)-输入占位符文本(默认:'Search products...')autoFocus(boolean,可选)-将输入集中在mount上(默认:false)submitAriaLabel(字符串,可选)-提交按钮的可访问标签(默认:'Search')
DialogSearchResults
浮动结果面板覆盖页面内容:传送到 document.body 在 position: fixed,位于条的中心(最大1440px宽,填充视口),并锚定在组件渲染的位置(将其放置在条的后面),因此没有祖先堆叠上下文或 overflow: hidden 可以隐藏它。它显示了与Shopify搜索覆盖相同的布局:在左边有一个集合列 sections 请求它们,将右边的产品作为列表或3列网格,查询匹配在每个标题中强调,并且,当 seeAllHref 设置后,有“查看所有结果”按钮;没有它,面板只显示点击的第一页,不分页。在768px以下,面板堆叠,集合在产品上方的水平轨道上。颜色,半径和字体遵循SDK主题(深色调色板时 backgroundColor 是暗角、直角还是圆角呢 ctaBorderType). 每张产品卡上都写着Algolia在Shopify上的记录:its _display.image (点击需要 _display,服务器从DAT-2016开始计算;当 _display.image 是缺席,没有缩略图;它的 shape 用主题的角来绘制 theme,直角 square,圆角 rounded 作为一个圆圈 round),其 _display.title,它的 _display.price (由服务器以购物者的市场货币进行格式化),在它旁边敲开 _display.compare_at_price 当存在时,和它 _display.url (相对的,在 storefrontRoot); 没有价格的成功说明没有价值。每张卡片都链接到产品页面,并自动记录搜索属性(视图印象,点击和中键选择)。点击面板外(和栏外)关闭它;再次输入或重新聚焦工具条将重新打开,并保留结果。
道具:
controller(SearchController) - FromuseDialogSearch(必需)state(SearchSnapshot) - FromuseDialogSearch(必需)locale(字符串,可选)-计数和标签的BCP 47语言环境。省略时,它们遵循控制器的language. 价格由服务器格式化。theme(主题,可选)-客户端的主题,由useDialogSearch;样式面板(调色板,半径,字体)layout('list' | 'grid',可选)-产品布局(默认:'list')seeAllHref((query) => string, optional) -“查看所有结果”页脚按钮的链接;省略后,面板只显示第一页的点击,没有分页
DialogSearchPagination
“上一页/下一页”控件带有页面指示符,为on connectPagination;在加载、类型化查询挂起或只有一个页面时隐藏。不是由 DialogSearchResults,它不会分页:在您自己的结果页面上使用它。
道具:
controller(SearchController) - FromuseDialogSearch(必需)state(SearchSnapshot) - FromuseDialogSearch(必需)locale(string,可选)-按钮标签的区域设置;省略,控制器的language
DialogSearchProductCard
结果的一个产品,带有图像,突出显示的标题,价格和链接,以及它的搜索属性(视口印象,点击和中键选择)。呈现的 DialogSearchResults -仅为自定义布局导出。
道具:
controller(SearchController) - FromuseDialogSearch(必需)hit(SearchProductHit) -产品命中(必选)index(数)-它在。中的位置state.results.products.hits,注明出处(必填)display(ProductHitDisplay,可选)- hit的显示来自connectHits;省略时从命中构建
主题
组件使用CSS变量进行主题化。您可以通过Dialog SDK客户端自定义主题:
const client = new Dialog({
apiKey: 'your-api-key',
theme: {
backgroundColor: 'pink',
primaryColor: 'pink',
ctaTextColor: 'white',
ctaBorderType: 'rounded',
capitalizeCtas: true,
fontFamily: 'Arial',
highlightProductName: true,
title: {
fontSize: '22px',
color: 'purple',
},
description: {
color: 'blue',
fontSize: '18px',
},
content: {
color: 'green',
fontSize: '10px',
},
},
});
开发
本节是为库本身工作的贡献者编写的。
先决条件
- Node.js >= 22
- PNPM >= 10
设置
# From monorepo root
pnpm install
开发工作流程
日常开发
对组件进行即时反馈;
# From monorepo root
pnpm dev:vue-example
# Opens vue-example app at http://localhost:5173
发生了什么:
- 示例应用程序在Vite开发服务器上运行
- 组件从 源文件 (
packages/vue/src/)通过别名 - 对组件的更改立即反映出来(启用HMR)
- 无需重建
测试构建库
测试这个库,就像消费者从npm接收它一样:
# Step 1: Build the library
pnpm build:vue
# Step 2: Run example app against built dist/
cd packages/vue-example
pnpm dev:test-dist
# Or from root: TEST_DIST=true pnpm dev:vue-example
何时使用:
- 在创建拉取请求之前
- 修改构建配置后
- 验证构建工作是否正确
- 在发布新版本之前
构建命令
# Build the library only
pnpm build:vue
# Build all packages in the monorepo
pnpm build
# Clean dist folder
pnpm --filter @askdialog/dialog-vue clean
# Run the specs (builds the SDK first)
pnpm nx test @askdialog/dialog-vue
# Lint code
pnpm --filter @askdialog/dialog-vue lint
# Fix linting issues
pnpm --filter @askdialog/dialog-vue lint:fix
项目结构
packages/vue/
├── src/
│ ├── main.ts # Library entry point
│ ├── components/ # Exported components
│ │ ├── index.ts # Component barrel export
│ │ ├── DialogProductBlock/
│ │ │ ├── DialogProductBlock.vue
│ │ │ ├── DialogInput.vue
│ │ │ ├── ThemeProvider.vue
│ │ │ └── ...
│ │ └── DialogSearch/
│ │ ├── DialogSearchBar.vue
│ │ ├── DialogSearchResults.vue
│ │ ├── useDialogSearch.ts
│ │ └── ...
│ └── icons/ # Icon components
├── dist/ # Build output (gitignored)
├── package.json
├── vite.config.ts # Library build configuration
└── project.json # Nx configuration
出版
# From monorepo root
pnpm publish:vue
Pre-publish清单:
- 所有测试都通过
- 版本更新于
package.json - 使用内置库进行测试(
pnpm dev:test-dist) - Tarball检查
pnpm pack - 更新日志更新
打印稿
这个包包含TypeScript类型定义。这些类型在安装包时自动可用。
Vue版本
此包需要v3或更高版本作为对等依赖项。