Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 10 additions & 0 deletions .changeset/rapid-input-number-icons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@varo-ui/h5": patch
"@varo-ui/weapp": patch
"@varo/weapp-web": patch
"@varo-ui/headless": patch
"@varo-ui/cli": patch
"@varo/registry": patch
---

Replace input-number ASCII steppers with named VIcon plus/minus controls and restore its compact inline geometry, pin textarea word-limit to the bottom-right, use a circular cancel-x on Input/Select without stretching Select on focus, avoid the native Input `focus` prop/handler collision, add dual-target multi-column Picker, DateField, PullRefresh, Signature, and Watermark Registry components while keeping Calendar independent, add shared motion tokens and Spectrum-inspired Button, Switch, Radio, Toast card, and VToastRegion interactions without changing the Varo palette, teach weapp-web native controls to preserve hover and ARIA semantics without Glass-Easel property warnings, pad docs API tables, preview compiled mini-program artifacts through weapp-web, and add a root `docs:dev` command with in-page H5 and Weapp primitive previews.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ pnpm --filter @varo/playground-weapp dev:ai

`dev:ai` prepares the WeChat DevTools project, starts the MCP HTTP service, and forwards DevTools console output and uncaught errors to the active terminal.

## Documentation development

```bash
pnpm run docs:dev
```

This starts VitePress at `http://localhost:5173` with in-page H5 and Weapp component previews.

## Verification

```bash
Expand Down
8 changes: 8 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ pnpm --filter @varo/playground-weapp dev:ai

`dev:ai` 会准备微信开发者工具项目、启动 MCP HTTP 服务,并将 DevTools console 与未捕获异常转发到当前终端。

## 文档开发

```bash
pnpm run docs:dev
```

该命令会在 `http://localhost:5173` 启动 VitePress,并在文档页内提供 H5 与 Weapp 组件预览。

## 验证

```bash
Expand Down
84 changes: 84 additions & 0 deletions apps/docs/.vitepress/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { resolve } from 'node:path'
import { createMarkdownRenderer, disposeMdItInstance } from 'vitepress'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { renderSearchMarkdown } from './config'

const docsRoot = process.cwd()
const searchDocumentPath = resolve(docsRoot, 'search-test.md')

let markdown: Awaited<ReturnType<typeof createMarkdownRenderer>>

beforeAll(async () => {
markdown = await createMarkdownRenderer(docsRoot, {
languages: ['ts', 'vue'],
})
})

afterAll(() => disposeMdItInstance())

async function renderSearch(source: string) {
return renderSearchMarkdown(source, {
cleanUrls: true,
path: searchDocumentPath,
relativePath: 'search-test.md',
}, markdown)
}

describe('VitePress search rendering', () => {
it('removes fenced code nested in blockquotes and ordered lists', async () => {
const html = await renderSearch([
'# Visible heading',
'> Visible quote',
'> ```ts',
'> hiddenBlockquote()',
'> ```',
'1. Visible item',
' ~~~vue',
' <template>hiddenList</template>',
' ~~~',
'Visible ending.',
].join('\n'))

expect(html).toContain('Visible heading')
expect(html).toContain('Visible quote')
expect(html).toContain('Visible item')
expect(html).toContain('Visible ending.')
expect(html).not.toContain('hiddenBlockquote')
expect(html).not.toContain('hiddenList')
})

it('expands included prose while omitting code from included Markdown', async () => {
const html = await renderSearch('<!-- @include: ../../README.md -->')
expect(html).toContain('Published packages')
expect(html).toContain('The CLI does not overwrite existing files by default.')
expect(html).not.toContain('pnpm dlx @varo-ui/cli')
})

it('leaves the normal page code renderer intact', async () => {
const html = await markdown.renderAsync('```ts\nconst visibleNormalCode = true\n```', {
cleanUrls: true,
path: searchDocumentPath,
relativePath: 'search-test.md',
})
expect(html).toContain('visibleNormalCode')
})

it('keeps invalid backtick-info openers searchable', async () => {
const html = await renderSearch('Before\n```foo`bar\nAfter')
expect(html).toContain('Before')
expect(html).toContain('foo`bar')
expect(html).toContain('After')
})

it('removes indented code blocks from search', async () => {
const html = await renderSearch('Before\n\n hiddenIndented()\n\nAfter')
expect(html).toContain('Before')
expect(html).toContain('After')
expect(html).not.toContain('hiddenIndented')
})

it('preserves the documented search false frontmatter contract', async () => {
const html = await renderSearch('---\nsearch: false\n---\n# Hidden page')
expect(html).toBe('')
})
})
53 changes: 53 additions & 0 deletions apps/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { DefaultTheme } from 'vitepress'
import { fileURLToPath } from 'node:url'
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vitepress'
Expand All @@ -6,13 +7,58 @@ import { createComponentSidebarGroups } from '../src/component-catalog.js'
const workspacePath = (relativePath: string) => fileURLToPath(new URL(relativePath, import.meta.url))
const docsBase = process.env.DOCS_BASE || '/'
const docsAsset = (path: string) => `${docsBase}${path.replace(/^\/+/, '')}`
const docsPort = Number(process.env.DOCS_PORT || 5173)

type LocalSearchRender = NonNullable<DefaultTheme.LocalSearchOptions['_render']>
const searchRenderFlag = '__varoSearchRenderWithoutCode'
const searchFilterInstalled = '__varoSearchCodeFilterInstalled'

type SearchMarkdownEnvironment = Parameters<LocalSearchRender>[1] & {
[searchRenderFlag]?: boolean
}

type SearchMarkdownRenderer = Parameters<LocalSearchRender>[2] & {
[searchFilterInstalled]?: boolean
}

function installSearchCodeFilter(md: SearchMarkdownRenderer) {
if (md[searchFilterInstalled]) { return }

for (const ruleName of ['fence', 'code_block'] as const) {
const renderRule = md.renderer.rules[ruleName]
if (!renderRule) { continue }
md.renderer.rules[ruleName] = (tokens, index, options, env, self) => {
if ((env as SearchMarkdownEnvironment)[searchRenderFlag]) { return '' }
return renderRule(tokens, index, options, env, self)
}
}

// VitePress shares this renderer with page builds, so normal page envs must retain the original rules.
md[searchFilterInstalled] = true
}

export const renderSearchMarkdown: LocalSearchRender = async (source, env, md) => {
const searchEnvironment = env as SearchMarkdownEnvironment
installSearchCodeFilter(md)
searchEnvironment[searchRenderFlag] = true
try {
const html = await md.renderAsync(source, env)
return env.frontmatter?.search === false ? '' : html
}
finally {
delete searchEnvironment[searchRenderFlag]
}
}

export default defineConfig({
title: 'Varo',
description: '面向 Vue 3 H5 与 Wevu 小程序的 Registry-first 双端移动 UI 系统。',
base: docsBase,
cleanUrls: true,
lastUpdated: true,
markdown: {
languages: ['bash', 'css', 'json', 'ts', 'vue'],
},
head: [
['link', { rel: 'icon', type: 'image/svg+xml', href: docsAsset('/brand-assets/varo-symbol.svg') }],
['link', { rel: 'alternate icon', href: docsAsset('/favicon.ico') }],
Expand All @@ -21,17 +67,21 @@ export default defineConfig({
['meta', { name: 'theme-color', media: '(prefers-color-scheme: dark)', content: '#0b1016' }],
],
vite: {
server: { host: 'localhost', port: docsPort, strictPort: true },
plugins: [tailwindcss()],
resolve: {
alias: {
'@varo-ui/ai': workspacePath('../../../packages/agent-core/src/index.ts'),
'@varo/hooks': workspacePath('../../../packages/hooks/src/index.ts'),
'@varo/shared': workspacePath('../../../packages/shared/src/index.ts'),
'@varo/utils': workspacePath('../../../packages/utils/src/index.ts'),
'@varo-ui/theme': workspacePath('../../../packages/theme/src/index.ts'),
'@varo-ui/headless': workspacePath('../../../packages/primitives-core/src/index.ts'),
'@varo/primitives-h5': workspacePath('../../../packages/primitives-h5/src/index.ts'),
'@varo/primitives-weapp': workspacePath('../../../packages/primitives-weapp/src/index.ts'),
'@varo-ui/h5/source/style.css': workspacePath('../../../packages/ui-h5/src/style.css'),
'@varo-ui/h5': workspacePath('../../../packages/ui-h5/src/index.ts'),
'@varo-ui/weapp/primitives': workspacePath('../../../packages/ui-weapp/src/primitives.ts'),
'@varo-ui/weapp': workspacePath('../../../packages/ui-weapp/src/index.ts'),
},
},
Expand All @@ -46,6 +96,7 @@ export default defineConfig({
search: {
provider: 'local',
options: {
_render: renderSearchMarkdown,
detailedView: true,
translations: {
button: { buttonText: '搜索文档', buttonAriaLabel: '搜索文档' },
Expand Down Expand Up @@ -214,6 +265,7 @@ export default defineConfig({
{ text: 'AgentFlowchart', link: '/ai/flowchart' },
{ text: 'AgentFineTune', link: '/ai/fine-tune' },
{ text: 'AgentChat Block', link: '/ai/agent-chat' },
{ text: 'AgentWorkspace Block', link: '/ai/agent-workspace' },
],
},
],
Expand Down Expand Up @@ -427,6 +479,7 @@ export default defineConfig({
{ text: 'AgentFlowchart', link: '/en/ai/flowchart' },
{ text: 'AgentFineTune', link: '/en/ai/fine-tune' },
{ text: 'AgentChat Block', link: '/en/ai/agent-chat' },
{ text: 'AgentWorkspace Block', link: '/en/ai/agent-workspace' },
],
},
],
Expand Down
44 changes: 12 additions & 32 deletions apps/docs/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,14 @@ html:not(.dark) .VPFeature:hover {
width: 100%;
overflow: hidden;
table-layout: fixed;
border-spacing: 0;
border-collapse: separate;
}

.vp-doc > table th,
.vp-doc > table td {
padding: 12px 16px;
vertical-align: top;
}

.vp-doc > table th {
Expand Down Expand Up @@ -1637,8 +1645,7 @@ html:not(.dark) .VPFeature:hover {
.varo-color-token-card,
.varo-role-card,
.varo-color-component-system,
.varo-token-grid div,
.varo-primitive-stack section {
.varo-token-grid div {
background: var(--varo-card);
border: 1px solid var(--varo-border);
border-radius: var(--varo-radius-lg);
Expand All @@ -1655,16 +1662,14 @@ html:not(.dark) .VPFeature:hover {

.varo-color-intro h2,
.varo-color-scale h2,
.varo-color-component-system h2,
.varo-primitive-stack h2 {
.varo-color-component-system h2 {
margin: 0 0 8px;
letter-spacing: 0;
}

.varo-color-intro p,
.varo-color-scale p,
.varo-color-component-system p,
.varo-primitive-stack p {
.varo-color-component-system p {
margin: 0;
color: var(--varo-muted);
}
Expand Down Expand Up @@ -1877,39 +1882,14 @@ html:not(.dark) .VPFeature:hover {
overflow-wrap: anywhere;
}

.varo-primitive-stack {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
margin: 22px 0 30px;
}

.varo-primitive-stack section {
padding: 18px;
}

.varo-primitive-stack span {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
font-size: 12px;
font-weight: 800;
color: var(--varo-bg);
background: var(--varo-foreground);
border-radius: var(--varo-radius);
}

@media (max-width: 960px) {
.varo-package-grid,
.varo-stat-grid,
.varo-block-grid,
.varo-color-matrix,
.varo-color-roles,
.varo-color-state-strip,
.varo-token-grid,
.varo-primitive-stack {
.varo-token-grid {
grid-template-columns: 1fr;
}

Expand Down
20 changes: 14 additions & 6 deletions apps/docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
VCascader,
VCheckbox,
VCheckboxGroup,
VDateField,
VDatePicker,
VForm,
VFormItem,
Expand All @@ -28,18 +29,21 @@ import {
import DefaultTheme from 'vitepress/theme'
import AgentComponentDemo from '../../src/components/AgentComponentDemo.vue'
import AgentComponentsDemo from '../../src/components/AgentComponentsDemo.vue'
import ComponentCatalog from '../../src/components/ComponentCatalog.vue'
import DateFieldDemo from '../../src/components/DateFieldDemo.vue'
import FormComponentDemo from '../../src/components/FormComponentDemo.vue'
import InteractivePreview from '../../src/components/InteractivePreview.vue'
import ListDemo from '../../src/components/ListDemo.vue'
import MapDemo from '../../src/components/MapDemo.vue'
import MiniProgramBlocksGallery from '../../src/components/MiniProgramBlocksGallery.vue'
import PlatformTabsDemo from '../../src/components/PlatformTabsDemo.vue'
import PrimitiveCatalog from '../../src/components/PrimitiveCatalog.vue'
import PrimitiveExample from '../../src/components/PrimitiveExample.vue'
import PrimitiveInteractionDemo from '../../src/components/PrimitiveInteractionDemo.vue'
import PullRefreshDemo from '../../src/components/PullRefreshDemo.vue'
import RegistryCoverageEvidence from '../../src/components/RegistryCoverageEvidence.vue'
import RegistryInstallStrip from '../../src/components/RegistryInstallStrip.vue'
import RobotChatDemo from '../../src/components/RobotChatDemo.vue'
import SignatureDemo from '../../src/components/SignatureDemo.vue'
import ToastDemo from '../../src/components/ToastDemo.vue'
import WatermarkDemo from '../../src/components/WatermarkDemo.vue'
import DocsLayout from './DocsLayout.vue'
import '@varo-ui/h5/source/style.css'
import './tailwind.css'
Expand All @@ -52,23 +56,27 @@ const theme: Theme = {
enhanceApp({ app }) {
app.component('AgentComponentsDemo', AgentComponentsDemo)
app.component('AgentComponentDemo', AgentComponentDemo)
app.component('DateFieldDemo', DateFieldDemo)
app.component('FormComponentDemo', FormComponentDemo)
app.component('InteractivePreview', InteractivePreview)
app.component('ComponentCatalog', ComponentCatalog)
app.component('ListDemo', ListDemo)
app.component('MiniProgramBlocksGallery', MiniProgramBlocksGallery)
app.component('MapDemo', MapDemo)
app.component('RobotChatDemo', RobotChatDemo)
app.component('PlatformTabsDemo', PlatformTabsDemo)
app.component('PrimitiveCatalog', PrimitiveCatalog)
app.component('PullRefreshDemo', PullRefreshDemo)
app.component('PrimitiveExample', PrimitiveExample)
app.component('RegistryInstallStrip', RegistryInstallStrip)
app.component('SignatureDemo', SignatureDemo)
app.component('WatermarkDemo', WatermarkDemo)
app.component('ToastDemo', ToastDemo)
app.component('RegistryCoverageEvidence', RegistryCoverageEvidence)
app.component('PrimitiveInteractionDemo', PrimitiveInteractionDemo)
app.component('VCalendar', VCalendar)
app.component('VCalendarCard', VCalendarCard)
app.component('VCascader', VCascader)
app.component('VCheckbox', VCheckbox)
app.component('VCheckboxGroup', VCheckboxGroup)
app.component('VDateField', VDateField)
app.component('VDatePicker', VDatePicker)
app.component('VForm', VForm)
app.component('VFormItem', VFormItem)
Expand Down
Loading