Clutch 工具包
为Next.js应用程序提供反应组件、公用事业和州管理解决方案的综合工具包.
安装
npm install @clutch-creator/toolkit
# or
yarn add @clutch-creator/toolkit
# or
bun add @clutch-creator/toolkit
概览
Clutch工具包旨在为开发者提供一套可再用组件和公用设施,与Next.js应用程序无缝地融合. 它包括国家管理,SIO优化,图像处理,以及各种公用功能.
API 参考
国家管理钩
useRegisterState(name, value)
在离合器中注册一个全球可约束的状态.
类型签名 :
useRegisterState<T>(name: string, value: T): (newValue: T) => void
示例
import { useRegisterState } from '@clutch-creator/toolkit';
import { useState } from 'react';
function Counter() {
const [counter, setCounter] = useState(0);
// Register the state so it can be accessed globally in Clutch
useRegisterState<number>('count', counter);
const increment = () => setCounter(prev => prev + 1);
const reset = () => setCounter(0);
return (
<div>
<button onClick={increment}>Increment</button>
<button onClick={reset}>Reset</button>
</div>
);
}
useRegisterAction(options)
注册事件可触发的组件的行动.
类型签名 :
useRegisterAction<T extends (...args: unknown[]) => unknown>(
options: TRegisterActionOptions<T>
): void
interface TRegisterActionOptions<T> {
name: string;
action: T;
props?: Record<string, unknown>;
wrapper?: React.FunctionComponent<{
children: React.ReactNode;
[key: string]: unknown;
}>;
styleSelectors?: TStyleSelector[];
}
interface TStyleSelector {
name: string;
value: string;
}
示例
import { useRegisterAction } from '@clutch-creator/toolkit';
import { useState } from 'react';
type TSetToggled = (toggled: boolean) => void;
function TodoItem({ id, text, completed }) {
const [toggled, setToggled] = useState(false);
useRegisterAction<TSetToggled>({
name: 'setToggled',
action: (newValue) => {
setToggled((value) => newValue);
},
props: {
'data-toggled': toggled
},
styleSelectors: [
{ name: 'Toggled', value: '&:[data-toggled=true]' }
]
});
return <div className={completed ? 'completed' : ''}>{text}</div>;
}
useRegisterSelect(setVisibility, activeTrail)
在离合器中选择元素时,注册一个要调用的处理器.
类型签名 :
useRegisterSelect(
setVisibility: (shouldBeVisible: boolean) => void,
activeTrail?: boolean
): null
示例
import { useRegisterSelect } from '@clutch-creator/toolkit';
import { useState } from 'react';
function ConditionalContent({ children }) {
const [isVisible, setIsVisible] = useState(true);
useRegisterSelect(
(shouldBeVisible) => setIsVisible(shouldBeVisible),
true // activeTrail - whether it should be called when a child is selected
);
if (!isVisible) return null;
return <div className="conditional-content">{children}</div>;
}
公用事业
updateUrlSearchParams(newParams, router)
更新 URL 搜索参数,同时保留已有的参数。 用于通过 URL 过滤、 pagination 和状态管理 .
类型签名 :
updateUrlSearchParams(
newParams: Record<string, unknown>,
router: NextRouter
): Record<string, unknown>
示例
import { updateUrlSearchParams } from '@clutch-creator/toolkit';
import { useRouter } from 'next/router';
function ProductFilters() {
const router = useRouter();
const handleCategoryFilter = (category: string) => {
updateUrlSearchParams({ category, page: 1 }, router);
// URL: /products?category=electronics&page=1
};
const handlePriceRange = (min: number, max: number) => {
updateUrlSearchParams({
priceMin: min.toString(),
priceMax: max.toString()
}, router);
// URL: /products?category=electronics&page=1&priceMin=100&priceMax=500
};
const clearFilters = () => {
updateUrlSearchParams({
category: null,
priceMin: null,
priceMax: null
}, router);
// URL: /products
};
return (
<div>
<button onClick={() => handleCategoryFilter('electronics')}>
Electronics
</button>
<button onClick={() => handlePriceRange(100, 500)}>
$100-$500
</button>
<button onClick={clearFilters}>Clear Filters</button>
</div>
);
}
clutchElementConfig(element, config)
用于可选配置的 Clutch 视觉编辑器的 React 组件 .
类型签名 :
clutchElementConfig(
element: React.FunctionComponent,
config: {
icon?: string;
styleSelectors?: { name?: string; value: string }[];
}
): void
示例
import { clutchElementConfig } from '@clutch-creator/toolkit';
const Button = ({ children, variant = 'primary', ...props }) => (
<button className={`btn btn-${variant}`} {...props}>
{children}
</button>
);
const Card = ({ title, children, ...props }) => (
<div className="card" {...props}>
<h3 className="card-title">{title}</h3>
<div className="card-content">{children}</div>
</div>
);
// Register components with Clutch editor
clutchElementConfig(Button, {
icon: '🔘',
styleSelectors: [
{ name: 'Hover', value: '&:hover' },
{ name: 'Disabled', value: '&:disabled' },
]
});
clutchElementConfig(Card, {
icon: '🃏',
styleSelectors: [
{ name: 'Card Hover', value: '&:hover' },
]
});
logger
有条件的日志功能,具有不同的开发与调试方法.
类型签名 :
logger: {
log(...args: unknown[]): void; // Only in development
debug(...args: unknown[]): void; // Only when window.CLUTCH_DEBUG = true
warn(...args: unknown[]): void; // In development or server
error(...args: unknown[]): void; // In development or server
}
示例
import { logger } from '@clutch-creator/toolkit';
function DataProcessor({ data }) {
// Always logs in development
logger.log('Processing data:', data);
// Only logs when window.CLUTCH_DEBUG = true
logger.debug('Debug info:', data);
try {
const processed = processData(data);
logger.log('Data processed successfully:', processed);
return processed;
} catch (error) {
logger.error('Error processing data:', error);
logger.warn('Falling back to default data');
return getDefaultData();
}
}
// In browser console to enable debug logging:
// window.CLUTCH_DEBUG = true;
cloneChildren(children, props)
克隆反应儿童,并将给定道具应用于每个儿童元素. 过滤出与调试相关的道具,并同时处理独生子和数组子.
类型签名 :
cloneChildren(
children: React.ReactNode,
props: Record<string, unknown>
): React.ReactNode
示例
import { cloneChildren } from '@clutch-creator/toolkit';
function WrapperComponent({ children, className, onClick }) {
// Clone children and add common props
const clonedChildren = cloneChildren(children, {
className: `child-element ${className}`,
onClick: onClick,
'data-wrapper': true
});
return <div className="wrapper">{clonedChildren}</div>;
}
// Usage
function App() {
return (
<WrapperComponent className="highlighted" onClick={() => console.log('clicked')}>
<button>Button 1</button>
<button>Button 2</button>
</WrapperComponent>
);
}
// Both buttons will receive className="child-element highlighted" and onClick handler
错误分类
MissingEnvVariableError
缺少所需环境变量时抛出 .
类型签名 :
class MissingEnvVariableError extends Error {
constructor(envName: string);
}
示例
import { MissingEnvVariableError } from '@clutch-creator/toolkit';
function initializeApp() {
const apiKey = process.env.NEXT_PUBLIC_API_KEY;
const dbUrl = process.env.DATABASE_URL;
if (!apiKey) {
throw new MissingEnvVariableError('NEXT_PUBLIC_API_KEY');
}
if (!dbUrl) {
throw new MissingEnvVariableError('DATABASE_URL');
}
// Initialize app with environment variables
return { apiKey, dbUrl };
}
// Usage with error handling
try {
const config = initializeApp();
} catch (error) {
if (error instanceof MissingEnvVariableError) {
console.error('Configuration error:', error.message);
// Handle missing environment variable
}
}
InvalidEnvVariableError
当环境变量有无效值时抛出 .
类型签名 :
class InvalidEnvVariableError extends Error {
constructor(envName: string);
}
示例
import { InvalidEnvVariableError } from '@clutch-creator/toolkit';
function validateConfig() {
const port = process.env.PORT;
const nodeEnv = process.env.NODE_ENV;
if (port && isNaN(parseInt(port))) {
throw new InvalidEnvVariableError('PORT');
}
if (nodeEnv && !['development', 'production', 'test'].includes(nodeEnv)) {
throw new InvalidEnvVariableError('NODE_ENV');
}
return {
port: port ? parseInt(port) : 3000,
nodeEnv: nodeEnv || 'development',
};
}
// Usage
try {
const config = validateConfig();
} catch (error) {
if (error instanceof InvalidEnvVariableError) {
console.error('Invalid configuration:', error.message);
process.exit(1);
}
}
控制类型
工具包用于 Clutch 编辑器中所使用的各种控制类型,导出全面的 TypeScript 类型 :
import type { Controls } from '@clutch-creator/toolkit';
// Available control types:
// Array, Checkbox, Code, Color, Combobox, Component, File, Input,
// Json, Media, Number, Object, RichText, Select, Styles, Svg,
// TextArea, Url, Action
示例
import type { Controls } from '@clutch-creator/toolkit';
type TSomeComponentProps = {
// props.image will use a media control
image: Controls["Media"],
/**
* You can also annotate a prop to set a control
* @control CustomControl
*/
anotherProp: string
}
export function SomeComponent = (props: TSomeComponentProps) {
// ...
}
软件包导出
该工具包分为模块出口,用于特定用途:
构成部分
// Individual component imports
import { Image } from '@clutch-creator/toolkit/components/Image';
import { ClientImage } from '@clutch-creator/toolkit/components/ClientImage';
import { Link } from '@clutch-creator/toolkit/components/Link';
import { Seo } from '@clutch-creator/toolkit/components/Seo';
import { RichText } from '@clutch-creator/toolkit/components/RichText';
import { Svg } from '@clutch-creator/toolkit/components/Svg';
import { ApplyHooks } from '@clutch-creator/toolkit/components/ApplyHooks';
import { NotFoundRedirect } from '@clutch-creator/toolkit/components/NotFoundRedirect';
import { Slot } from '@clutch-creator/toolkit/components/Slot';
Imageưμ㼯A 有自动占位符生成和优化的图像包ClientImage: 用于动态图像加载的客户端图像组件Link: 增强的下一个.js 链接组件,支持复杂的 URL 参数管理Seo: 支持OpenGraph、Twitter卡和结构化数据的SEO综合组件RichText: 支持字符串和JSX内容的灵活丰富的文本渲染器Svg: SVG 组件包装器,用于动态 SVG 渲染ApplyHooks: 对儿童适用多钩组件的组件NotFoundRedirect: 处理404再定向的组件Slot: 向儿童传递道具的功能部分(使用)cloneChildren内部)
发展 工作流量
- 叉子存储器
- 创建特性分支 :
git checkout -b feature/amazing-feature - 做你的改变
- 运行测试 :
bun run test - 运行林入 :
bun run lint - 创建更改列表数字 :
bun run changeset(如果您的更改会触发释放) - 提交更改 :
git commit -m 'feat: add amazing feature' - 推到你的树枝:
git push origin feature/amazing-feature - 创建拉动请求
在离合器项目中本地运行工具包,创建工具包的连锁:
bun link
然后在项目目录上:
bun link @clutch-creator/toolkit
您还需要在下一个配置中添加一些配置, 确保根路径足够返回到它嵌入工具包位置的地方 :
const nextConfig: NextConfig = withClutch({
transpilePackages: ['@clutch-creator/toolkit'],
turbo: {
root: path.join(__dirname, '../../../../..'),
},
outputFileTracingRoot: path.join(__dirname, '../../../../..'),
});
部署
这个项目使用 更改 用于自动版本和出版:
- 创建更改列表 :
bun run changeset - 将更改推到
main分支 - GitHub 动作将自动 :
- 创建带有版本更新的“ 释放 PR ”
- 合并后,发布国家防范机制软件包并创建 GitHub 版本
许可证
麻省理工学院
捐款
这个工具包由克勒克团队维护. 关于问题和专题报道,请访问 GitHub 仓库。 。 。 .
++ 辅助
由美国制造 Clutch 团队
Clutch是下一代视觉构建者,赋予创作专业人士完全设计自由,高级功能,并具有顶级性能的能力. 学习更多 离合器 io。 。 。 .