@uniweb /工具
Uniweb基础的标准组件库。用于构建基础组件的可摇树实用程序、组件和挂钩。
安装
npm install @uniweb/kit
Tree-Shaking好处
Kit被设计成捆绑在你的基础(而不是外部化像 @uniweb/core). 这意味着:
- 只有你使用的是捆绑的 —导入3个组件?只有这3个最终成为你的基金
- 没有运行时开销 -在构建时消除未使用的代码
- 可定制的 -覆盖或扩展任何组件而不携带死代码
- 小的基础 -最小的粉底使用
Link和useWebsite保持小
// vite.config.js - Kit is bundled, core is external
export default {
build: {
rollupOptions: {
external: ['react', 'react-dom', 'react-router-dom', '@uniweb/core']
// Note: @uniweb/kit is NOT in external — it gets tree-shaken
}
}
}
快速入门
import { Link, Image, useWebsite } from '@uniweb/kit'
function Hero({ content }) {
const { localize } = useWebsite()
return (
<div>
<Image src={content.images[0]?.url} alt="Hero" />
<h1>{localize({ en: 'Welcome', es: 'Bienvenido' })}</h1>
<Link to="/about">Learn More</Link>
</div>
)
}
组件
链接
具有路由和下载功能的智能链接组件。一个离开网站、下载文件、写电子邮件或打电话的链接会得到一个提示;内部链接没有。
import { Link } from '@uniweb/kit'
<Link to="/about">About</Link>
<Link href="https://github.com">GitHub</Link>
<Link href="/files/report.pdf">Download Report</Link>
<Link href="mailto:[email protected]">Contact</Link>
| 道具 | 类型 | 描述 |
|---|---|---|
to / href | string | 目标URL |
title | string | 工具提示。如果省略,则只有当链接离开网站、下载、写电子邮件或拨打电话时才会生成一个链接 |
target | string | 链接的目标 |
download | boolean | 强制下载行为 |
图像
具有过滤器和大小预设的通用图像组件。
import { Image } from '@uniweb/kit'
<Image src="/photo.jpg" alt="Photo" />
<Image src="/photo.jpg" filter={{ grayscale: 100 }} />
<Image src="/team/ada.jpg" alt="Ada" size="lg" rounded />
| 道具 | 类型 | 描述 |
|---|---|---|
src / url | string | 图像URL |
alt | string | Alt文本 |
size | string | 预设:xs, sm, md, lg, xl, 2xl, full |
rounded | boolean|string | 边界半径 |
filter | object | CSS滤镜:模糊、亮度、对比度、灰度、饱和度、棕褐色 |
SafeHtml
安全渲染HTML,解析 page: 链接和基本路径。
import { SafeHtml } from '@uniweb/kit'
<SafeHtml value="<p>Hello <strong>World</strong></p>" />
<SafeHtml value='<a href="page:about">About</a>' />
图标
带有内置图标和URL加载的SVG图标组件。
import { Icon } from '@uniweb/kit'
<Icon name="check" size="24" color="green" />
<Icon url="/icons/custom.svg" />
<Icon svg="<svg>...</svg>" />
内置:检查,警报,用户,心,设置,星号,关闭,菜单,雪佛兰下,雪佛兰右,外部链接,下载,播放
SocialIcon
自动检测社交媒体平台图标。
import { SocialIcon, getSocialPlatform, filterSocialLinks } from '@uniweb/kit'
<SocialIcon platform="twitter" size={24} />
<SocialIcon url="https://twitter.com/example" />
// Utilities
getSocialPlatform('https://linkedin.com/in/user') // 'linkedin'
filterSocialLinks(links) // Filter to only social links
支持:facebook, twitter, x, linkedin, instagram, youtube, github, medium, pinterest,抖音,discord,乳齿象,蓝天,电子邮件,电话,orcid, researchgate, google学者
排版
用于呈现语义解析器输出的智能排版组件。
import { Text, H1, H2, P, PlainText } from '@uniweb/kit'
<H1 text="Main Title" />
<H2 text={["Multi-line", "Subtitle"]} />
<P text="A paragraph of content" />
<P text={["First paragraph", "Second paragraph"]} />
// Plain text (HTML shown as text)
<PlainText text="Show <strong>tags</strong> as text" />
| 道具 | 类型 | 描述 |
|---|---|---|
text | string|string[] | 要呈现的内容 |
as | string | 标签:'h1'-'h6', 'p', 'div', ‘span’ |
html | boolean | 渲染为HTML(默认值:true) |
lineAs | string | 数组项的标签 |
别名: H1, H2, H3, H4, H5, H6, P, Span, Div, PlainText
媒体
视频播放器的YouTube, Vimeo,和本地视频。
import { Media } from '@uniweb/kit'
<Media src="https://youtube.com/watch?v=abc123" />
<Media src="/videos/intro.mp4" controls />
<Media src="https://youtube.com/..." thumbnail="/poster.jpg" facade />
FileLogo
基于文件名的文件类型图标。
import { FileLogo } from '@uniweb/kit'
<FileLogo filename="report.pdf" size="32" />
MediaIcon
平台图标(YouTube, Vimeo等)。
import { MediaIcon } from '@uniweb/kit'
<MediaIcon type="youtube" size="24" />
资产
文件预览与下载功能。
import { Asset } from '@uniweb/kit'
<Asset value="/files/document.pdf" />
钩子
useWebsite
访问网站实例和实用程序。
import { useWebsite } from '@uniweb/kit'
function MyComponent() {
const {
website, // Website instance
localize, // Localize multilingual values
makeHref, // Resolve page: references to routes
getLanguage, // Current language code
getLanguages // Available languages
} = useWebsite()
return <div>{localize({ en: 'Hello', fr: 'Bonjour' })}</div>
}
useActiveRoute
检测活动导航状态。
import { useActiveRoute } from '@uniweb/kit'
function NavLink({ page }) {
const { isActive, isActiveOrAncestor } = useActiveRoute()
return (
<Link
to={page.route}
className={isActiveOrAncestor(page) ? 'font-bold' : ''}
>
{page.title}
</Link>
)
}
useScrolled
检测粘贴头的滚动位置。
import { useScrolled } from '@uniweb/kit'
function Header() {
const scrolled = useScrolled(50) // Threshold in pixels
return (
<header className={scrolled ? 'shadow-md' : ''}>
...
</header>
)
}
useMobileMenu
移动菜单状态管理。
import { useMobileMenu } from '@uniweb/kit'
function Navbar() {
const { isOpen, toggle, close } = useMobileMenu()
return (
<>
<button onClick={toggle}>Menu</button>
{isOpen && <MobileMenu onClose={close} />}
</>
)
}
useAccordion
Accordion/FAQ状态管理。
import { useAccordion } from '@uniweb/kit'
function FAQ({ items }) {
const { isOpen, toggle } = useAccordion()
return items.map((item, i) => (
<div key={i}>
<button onClick={() => toggle(i)}>{item.question}</button>
{isOpen(i) && <p>{item.answer}</p>}
</div>
))
}
useInView
延迟加载和动画的视口交叉检测。
import { useInView, useIsInView } from '@uniweb/kit'
function AnimatedSection() {
const { ref, inView } = useInView({ threshold: 0.2, once: true })
return (
<div ref={ref} className={inView ? 'animate-fade-in' : 'opacity-0'}>
Content appears when scrolled into view
</div>
)
}
// Simple boolean version
function LazyImage({ src }) {
const [ref, isInView] = useIsInView()
return <div ref={ref}>{isInView && <img src={src} />}</div>
}
useGridLayout
响应式电网公用事业。
import { useGridLayout, getGridClasses } from '@uniweb/kit'
function Gallery({ items }) {
const { columns } = useGridLayout(items.length, { maxColumns: 4 })
return (
<div className={getGridClasses(columns)}>
{items.map(item => <Card key={item.id} {...item} />)}
</div>
)
}
主题挂钩
在运行时访问站点主题化数据。
import {
useThemeData,
useThemeColor,
useThemeColorVar,
useColorContext,
useAppearance
} from '@uniweb/kit'
function ThemedComponent({ block }) {
// Full theme access
const theme = useThemeData()
const palettes = theme?.getPaletteNames() // ['primary', 'secondary', ...]
// Get specific color
const primaryColor = useThemeColor('primary', 500) // '#3b82f6'
const primaryVar = useThemeColorVar('primary', 600) // 'var(--primary-600)'
// Context-aware (light/medium/dark sections)
const context = useColorContext(block) // 'light' | 'medium' | 'dark'
// Dark mode
const { scheme, toggle, canToggle } = useAppearance()
return (
<div style={{ color: primaryColor }}>
{canToggle && (
<button onClick={toggle}>
{scheme === 'dark' ? 'Light' : 'Dark'}
</button>
)}
</div>
)
}
搜索
全文搜索由Fuse.js提供支持。需要 fuse.js 作为你基金会的同伴依赖。
npm install fuse.js
useSearch
主要的搜索挂钩与脱绑定和状态管理。
import { useSearch, useWebsite } from '@uniweb/kit'
function SearchComponent() {
const { website } = useWebsite()
const { query, results, isLoading, isEnabled, preload } = useSearch(website)
if (!isEnabled) return null
return (
<div>
<input onChange={e => query(e.target.value)} placeholder="Search..." />
{isLoading && <span>Searching...</span>}
{results.map(r => (
<a key={r.id} href={r.href}>{r.title}</a>
))}
</div>
)
}
useSearchPrefetch
预取搜索索引悬停,焦点或触摸,而不是在页面加载。
import { useSearchPrefetch, useSearchShortcut } from '@uniweb/kit'
function SearchButton({ onClick }) {
const { website } = useWebsite()
const { triggerPreload, prefetchProps } = useSearchPrefetch(website)
// Cmd/Ctrl+K shortcut with preload
useSearchShortcut({
onOpen: onClick,
onPreload: triggerPreload,
})
return (
<button onClick={onClick} {...prefetchProps}>
Search
</button>
)
}
从不搜索的访问者永远不会下载索引。它取一次。
useSearchShortcut
打开搜索的键盘快捷方式。
import { useSearchShortcut } from '@uniweb/kit'
// Simple
useSearchShortcut(() => setSearchOpen(true))
// With preload on shortcut
useSearchShortcut({
onOpen: () => setSearchOpen(true),
onPreload: () => searchClient.preload()
})
createSearchClient
低级搜索客户端供高级使用。
import { createSearchClient } from '@uniweb/kit'
const client = createSearchClient(website, {
fuseOptions: { threshold: 0.3 },
defaultLimit: 10
})
// Query — returns SearchResult[]
const results = await client.query('authentication', { limit: 5 })
// Same query, plus how many matched before `limit` — the 47 in "showing 10 of 47".
// `total` is null when the active provider cannot say (a deployment fact, not an
// error): the local index always knows it; an endpoint knows it only if it
// reports one. Render the count conditionally, the results unconditionally.
const { results: page, total } = await client.queryWithTotal('authentication', { limit: 5 })
// Preload index
await client.preload()
// Check status
client.isEnabled()
client.getIndexUrl()
风格的组件
使用顺风CSS预样式组件。
import { Section, SidebarLayout, Disclaimer } from '@uniweb/kit'
<Section width="lg" padding="md" className="bg-gray-50">
<h1>Welcome</h1>
</Section>
<SidebarLayout sidebar={<Nav />} sidebarPosition="left">
<main>Content</main>
</SidebarLayout>
<Disclaimer
title="Terms of Service"
content="<p>Please read our terms...</p>"
triggerText="View Terms"
/>
公用事业公司
import { cn, stripTags, isExternalUrl, isFileUrl, detectMediaType } from '@uniweb/kit'
// Merge Tailwind classes (uses tailwind-merge)
cn('px-4 py-2', 'bg-blue-500', condition && 'opacity-50')
// Strip HTML tags
stripTags('<p>Hello</p>') // "Hello"
// URL utilities
isExternalUrl('https://google.com') // true
isFileUrl('/files/doc.pdf') // true
detectMediaType('https://youtube.com/...') // 'youtube'
体系结构
┌─────────────────────────────────────────────────────────────┐
│ Foundation (your code) │
│ ├── imports @uniweb/kit (bundled, tree-shaken) │
│ └── @uniweb/core marked as external │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ @uniweb/runtime (browser) │
│ ├── Loads foundation dynamically │
│ ├── Provides @uniweb/core singleton │
│ └── Orchestrates React rendering │
└─────────────────────────────────────────────────────────────┘
为什么捆绑套件而外部化核心?
-
工具包:不同的基础可能使用不同的套件子集。摇树确保每个基础只包含它使用的东西。
-
核心包含Website, Page和Block类,这些类必须是单例的。运行时提供这些基础,通过外部导入引用它们。
许可证
apache - 2.0