tona-ui 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,81 +1,118 @@
1
1
  # tona-ui
2
2
 
3
- Tona UI 组件库,提供可复用的 Preact 组件。
3
+ <p align="center">
4
+ <img src="../../assets/tona.png" alt="Tona" width="100" />
5
+ </p>
4
6
 
5
- ## 安装
7
+ <p align="center">
8
+ UI component library for Tona themes, built with Preact.
9
+ </p>
6
10
 
7
- ```bash
8
- pnpm add tona-ui
9
- ```
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/tona-ui"><img src="https://img.shields.io/npm/v/tona-ui?style=flat-square" alt="npm version"></a>
13
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/tona-ui?style=flat-square" alt="license"></a>
14
+ <a href="https://preactjs.com"><img src="https://img.shields.io/badge/Preact->=10.0.0-673AB8?style=flat-square&logo=preact" alt="Preact"></a>
15
+ </p>
10
16
 
11
- ## 组件
17
+ **English** | [中文](./README.zh-CN.md)
12
18
 
13
- ### Button
19
+ ## Features
14
20
 
15
- 按钮组件,支持多种变体和尺寸。
21
+ - **Preact Based** - Lightweight components for Preact
22
+ - **Slot Component** - Radix UI-inspired Slot for prop forwarding
23
+ - **Utility Functions** - `cn()` for class name merging
24
+ - **TypeScript Support** - Full type definitions
25
+ - **Tree-shakeable** - Import only what you need
16
26
 
17
- ```tsx
18
- import { Button } from 'tona-ui'
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install tona-ui
31
+ ```
19
32
 
20
- // 基础用法
21
- <Button>点击我</Button>
33
+ ```bash
34
+ pnpm add tona-ui
35
+ ```
22
36
 
23
- // 不同变体
24
- <Button variant="destructive">删除</Button>
25
- <Button variant="outline">轮廓</Button>
26
- <Button variant="ghost">幽灵</Button>
37
+ ```bash
38
+ yarn add tona-ui
39
+ ```
27
40
 
28
- // 不同尺寸
29
- <Button size="sm">小按钮</Button>
30
- <Button size="lg">大按钮</Button>
31
- <Button size="icon">图标按钮</Button>
41
+ ## Usage
32
42
 
33
- // 作为子组件渲染
34
- <Button asChild>
35
- <a href="/link">链接按钮</a>
36
- </Button>
43
+ ```typescript
44
+ import { Slot, cn } from 'tona-ui'
37
45
  ```
38
46
 
47
+ ## Components
48
+
39
49
  ### Slot
40
50
 
41
- Slot 组件用于将 props 传递给子组件,类似于 Radix UI Slot 组件。
51
+ The Slot component forwards props to its child element, similar to Radix UI's Slot.
42
52
 
43
53
  ```tsx
44
54
  import { Slot } from 'tona-ui'
45
55
 
46
- // 基础用法
56
+ // Basic usage
47
57
  <Slot className="custom-class">
48
- <button>按钮</button>
58
+ <button>Click me</button>
49
59
  </Slot>
60
+ // Renders: <button class="custom-class">Click me</button>
50
61
 
51
- // 事件处理
62
+ // Event handling
52
63
  <Slot onClick={() => console.log('clicked')}>
53
- <div>可点击的 div</div>
64
+ <div>Clickable div</div>
65
+ </Slot>
66
+
67
+ // Multiple children - props forwarded to all
68
+ <Slot className="item">
69
+ <span>Item 1</span>
70
+ <span>Item 2</span>
54
71
  </Slot>
55
72
  ```
56
73
 
57
74
  ### cn
58
75
 
59
- 工具函数,用于合并 CSS 类名。
76
+ Utility function for merging CSS class names.
60
77
 
61
78
  ```tsx
62
79
  import { cn } from 'tona-ui'
63
80
 
64
- const className = cn('base-class', 'conditional-class', {
65
- 'active-class': isActive
81
+ // Basic usage
82
+ const className = cn('base-class', 'conditional-class')
83
+ // Result: "base-class conditional-class"
84
+
85
+ // With conditions
86
+ const className = cn('base-class', {
87
+ 'active-class': isActive,
88
+ 'disabled-class': isDisabled,
66
89
  })
90
+ // Result when isActive=true, isDisabled=false: "base-class active-class"
91
+
92
+ // Multiple arguments
93
+ const className = cn('flex', 'items-center', isLarge && 'p-4', isSmall && 'p-2')
94
+ ```
95
+
96
+ ## Peer Dependencies
97
+
98
+ ```json
99
+ {
100
+ "preact": ">=10.0.0"
101
+ }
67
102
  ```
68
103
 
69
- ## 开发
104
+ ## Development
70
105
 
71
106
  ```bash
72
- # 开发模式
107
+ # Development mode
73
108
  pnpm dev
74
109
 
75
- # 构建
110
+ # Build
76
111
  pnpm build
77
112
  ```
78
113
 
79
- ## 许可证
114
+ ## Related
80
115
 
81
- MIT
116
+ - [tona](https://github.com/guangzan/tona/tree/main/packages/core) - Core framework
117
+ - [tona-hooks](https://github.com/guangzan/tona/tree/main/packages/hooks) - React hooks
118
+ - [tona-sonner](https://github.com/guangzan/tona/tree/main/packages/sonner) - Toast notifications
@@ -0,0 +1,118 @@
1
+ # tona-ui
2
+
3
+ <p align="center">
4
+ <img src="../../assets/tona.png" alt="Tona" width="100" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ 用于 Tona 主题的 UI 组件库,基于 Preact 构建。
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/tona-ui"><img src="https://img.shields.io/npm/v/tona-ui?style=flat-square" alt="npm version"></a>
13
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/tona-ui?style=flat-square" alt="license"></a>
14
+ <a href="https://preactjs.com"><img src="https://img.shields.io/badge/Preact->=10.0.0-673AB8?style=flat-square&logo=preact" alt="Preact"></a>
15
+ </p>
16
+
17
+ [English](./README.md) | **中文**
18
+
19
+ ## 特性
20
+
21
+ - **基于 Preact** - 为 Preact 设计的轻量级组件
22
+ - **Slot 组件** - 受 Radix UI 启发的 Slot,用于属性转发
23
+ - **工具函数** - 用于合并类名的 `cn()`
24
+ - **TypeScript 支持** - 完整的类型定义
25
+ - **可摇树优化** - 只导入你需要的
26
+
27
+ ## 安装
28
+
29
+ ```bash
30
+ npm install tona-ui
31
+ ```
32
+
33
+ ```bash
34
+ pnpm add tona-ui
35
+ ```
36
+
37
+ ```bash
38
+ yarn add tona-ui
39
+ ```
40
+
41
+ ## 使用
42
+
43
+ ```typescript
44
+ import { Slot, cn } from 'tona-ui'
45
+ ```
46
+
47
+ ## 组件
48
+
49
+ ### Slot
50
+
51
+ Slot 组件将属性转发给其子元素,类似于 Radix UI 的 Slot。
52
+
53
+ ```tsx
54
+ import { Slot } from 'tona-ui'
55
+
56
+ // 基础用法
57
+ <Slot className="custom-class">
58
+ <button>点击我</button>
59
+ </Slot>
60
+ // 渲染: <button class="custom-class">点击我</button>
61
+
62
+ // 事件处理
63
+ <Slot onClick={() => console.log('clicked')}>
64
+ <div>可点击的 div</div>
65
+ </Slot>
66
+
67
+ // 多个子元素 - 属性转发给所有子元素
68
+ <Slot className="item">
69
+ <span>Item 1</span>
70
+ <span>Item 2</span>
71
+ </Slot>
72
+ ```
73
+
74
+ ### cn
75
+
76
+ 用于合并 CSS 类名的工具函数。
77
+
78
+ ```tsx
79
+ import { cn } from 'tona-ui'
80
+
81
+ // 基础用法
82
+ const className = cn('base-class', 'conditional-class')
83
+ // 结果: "base-class conditional-class"
84
+
85
+ // 带条件
86
+ const className = cn('base-class', {
87
+ 'active-class': isActive,
88
+ 'disabled-class': isDisabled,
89
+ })
90
+ // 当 isActive=true, isDisabled=false 时的结果: "base-class active-class"
91
+
92
+ // 多个参数
93
+ const className = cn('flex', 'items-center', isLarge && 'p-4', isSmall && 'p-2')
94
+ ```
95
+
96
+ ## 对等依赖
97
+
98
+ ```json
99
+ {
100
+ "preact": ">=10.0.0"
101
+ }
102
+ ```
103
+
104
+ ## 开发
105
+
106
+ ```bash
107
+ # 开发模式
108
+ pnpm dev
109
+
110
+ # 构建
111
+ pnpm build
112
+ ```
113
+
114
+ ## 相关
115
+
116
+ - [tona](https://github.com/guangzan/tona/tree/main/packages/core) - 核心框架
117
+ - [tona-hooks](https://github.com/guangzan/tona/tree/main/packages/hooks) - React hooks
118
+ - [tona-sonner](https://github.com/guangzan/tona/tree/main/packages/sonner) - Toast 通知
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as preact_compat0 from "preact/compat";
2
- import * as preact0 from "preact";
2
+ import * as preact from "preact";
3
3
  import { ComponentChildren, Ref } from "preact";
4
4
 
5
5
  //#region src/components/slot.d.ts
@@ -19,7 +19,7 @@ interface SlotProps {
19
19
  * 当作为子组件时,会将父组件的 props 合并到子组件上
20
20
  * 当作为普通元素时,会渲染为 div 元素
21
21
  */
22
- declare const Slot: preact0.FunctionalComponent<preact_compat0.PropsWithoutRef<SlotProps> & {
22
+ declare const Slot: preact.FunctionalComponent<preact_compat0.PropsWithoutRef<SlotProps> & {
23
23
  ref?: Ref<HTMLElement> | undefined;
24
24
  }>;
25
25
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/components/slot.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;AAOiB,UAAA,SAAA,CACJ;EAYA,QAoBZ,CAAA,EAhCY,iBAgCZ;EApBgB,SAAA,CAAA,EAAA,MAAA;EAAA,KAAA,CAAA,EAAA,GAAA;oBATG;;;;;;;;cASP,cAAI,oBAAA,cAAA,CAAA,gBAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/components/slot.tsx"],"mappings":";;;;;;;;;UAOiB,SAAA;EACf,QAAA,GAAW,iBAAA;EACX,SAAA;EACA,KAAA;EACA,OAAA,IAAW,KAAA,EAAO,KAAA;EAAA,CACjB,GAAA;AAAA;;;;;;cAQU,IAAA,SAAI,mBAAA,CAAA,cAAA,CAAA,eAAA,CAAA,SAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/components/slot.tsx"],"sourcesContent":["import type { ComponentChildren, Ref } from 'preact'\nimport { cloneElement, forwardRef, isValidElement } from 'preact/compat'\n\n/**\n * Slot 组件用于将 props 传递给子组件,类似于 Radix UI 的 Slot 组件\n * 它允许父组件将 props 传递给子组件,而子组件可以决定如何处理这些 props\n */\nexport interface SlotProps {\n children?: ComponentChildren\n className?: string\n style?: any\n onClick?: (event: Event) => void\n [key: string]: any\n}\n\n/**\n * Slot 组件实现\n * 当作为子组件时,会将父组件的 props 合并到子组件上\n * 当作为普通元素时,会渲染为 div 元素\n */\nexport const Slot = forwardRef<HTMLElement, SlotProps>(\n ({ children, ...props }, forwardedRef) => {\n if (isValidElement(children)) {\n return cloneElement(\n children as any,\n {\n ...mergeProps(props, (children as any).props),\n ref: forwardedRef\n ? composeRefs(forwardedRef, (children as any).ref)\n : (children as any).ref,\n } as any,\n )\n }\n\n return (\n <div {...props} ref={forwardedRef as Ref<HTMLDivElement>}>\n {children}\n </div>\n )\n },\n)\n\nSlot.displayName = 'Slot'\n\n/**\n * 合并 props,子组件的 props 优先级更高\n */\nfunction mergeProps(parentProps: any, childProps: any) {\n const overrideProps = { ...childProps }\n\n for (const propName in childProps) {\n const parentPropValue = parentProps[propName]\n const childPropValue = childProps[propName]\n\n const isHandler = /^on[A-Z]/.test(propName)\n if (isHandler) {\n // 对于事件处理器,需要同时调用父组件和子组件的处理器\n if (childPropValue && parentPropValue) {\n overrideProps[propName] = (...args: any[]) => {\n childPropValue(...args)\n parentPropValue(...args)\n }\n } else if (parentPropValue) {\n overrideProps[propName] = parentPropValue\n }\n } else if (propName === 'style') {\n // 对于 style,需要合并对象\n overrideProps[propName] = { ...parentPropValue, ...childPropValue }\n } else if (propName === 'className') {\n // 对于 className,需要合并字符串\n overrideProps[propName] = [parentPropValue, childPropValue]\n .filter(Boolean)\n .join(' ')\n }\n }\n\n return { ...parentProps, ...overrideProps }\n}\n\n/**\n * 组合多个 ref\n */\nfunction composeRefs<T>(...refs: (Ref<T> | undefined)[]): Ref<T> {\n return (node: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(node)\n } else if (ref != null) {\n ; (ref as any).current = node\n }\n })\n }\n}\n"],"mappings":";;;;;;;;;AAoBA,MAAa,OAAO,YACjB,EAAE,UAAU,GAAG,SAAS,iBAAiB;AACxC,KAAI,eAAe,SAAS,CAC1B,QAAO,aACL,UACA;EACE,GAAG,WAAW,OAAQ,SAAiB,MAAM;EAC7C,KAAK,eACD,YAAY,cAAe,SAAiB,IAAI,GAC/C,SAAiB;EACvB,CACF;AAGH,QACE,oBAAC;EAAI,GAAI;EAAO,KAAK;EAClB;GACG;EAGX;AAED,KAAK,cAAc;;;;AAKnB,SAAS,WAAW,aAAkB,YAAiB;CACrD,MAAM,gBAAgB,EAAE,GAAG,YAAY;AAEvC,MAAK,MAAM,YAAY,YAAY;EACjC,MAAM,kBAAkB,YAAY;EACpC,MAAM,iBAAiB,WAAW;AAGlC,MADkB,WAAW,KAAK,SAAS,EAGzC;OAAI,kBAAkB,gBACpB,eAAc,aAAa,GAAG,SAAgB;AAC5C,mBAAe,GAAG,KAAK;AACvB,oBAAgB,GAAG,KAAK;;YAEjB,gBACT,eAAc,YAAY;aAEnB,aAAa,QAEtB,eAAc,YAAY;GAAE,GAAG;GAAiB,GAAG;GAAgB;WAC1D,aAAa,YAEtB,eAAc,YAAY,CAAC,iBAAiB,eAAe,CACxD,OAAO,QAAQ,CACf,KAAK,IAAI;;AAIhB,QAAO;EAAE,GAAG;EAAa,GAAG;EAAe;;;;;AAM7C,SAAS,YAAe,GAAG,MAAsC;AAC/D,SAAQ,SAAmB;AACzB,OAAK,SAAS,QAAQ;AACpB,OAAI,OAAO,QAAQ,WACjB,KAAI,KAAK;YACA,OAAO,KACd,CAAC,IAAY,UAAU;IAE3B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/components/slot.tsx"],"sourcesContent":["import type { ComponentChildren, Ref } from 'preact'\nimport { cloneElement, forwardRef, isValidElement } from 'preact/compat'\n\n/**\n * Slot 组件用于将 props 传递给子组件,类似于 Radix UI 的 Slot 组件\n * 它允许父组件将 props 传递给子组件,而子组件可以决定如何处理这些 props\n */\nexport interface SlotProps {\n children?: ComponentChildren\n className?: string\n style?: any\n onClick?: (event: Event) => void\n [key: string]: any\n}\n\n/**\n * Slot 组件实现\n * 当作为子组件时,会将父组件的 props 合并到子组件上\n * 当作为普通元素时,会渲染为 div 元素\n */\nexport const Slot = forwardRef<HTMLElement, SlotProps>(\n ({ children, ...props }, forwardedRef) => {\n if (isValidElement(children)) {\n return cloneElement(\n children as any,\n {\n ...mergeProps(props, (children as any).props),\n ref: forwardedRef\n ? composeRefs(forwardedRef, (children as any).ref)\n : (children as any).ref,\n } as any,\n )\n }\n\n return (\n <div {...props} ref={forwardedRef as Ref<HTMLDivElement>}>\n {children}\n </div>\n )\n },\n)\n\nSlot.displayName = 'Slot'\n\n/**\n * 合并 props,子组件的 props 优先级更高\n */\nfunction mergeProps(parentProps: any, childProps: any) {\n const overrideProps = { ...childProps }\n\n for (const propName in childProps) {\n const parentPropValue = parentProps[propName]\n const childPropValue = childProps[propName]\n\n const isHandler = /^on[A-Z]/.test(propName)\n if (isHandler) {\n // 对于事件处理器,需要同时调用父组件和子组件的处理器\n if (childPropValue && parentPropValue) {\n overrideProps[propName] = (...args: any[]) => {\n childPropValue(...args)\n parentPropValue(...args)\n }\n } else if (parentPropValue) {\n overrideProps[propName] = parentPropValue\n }\n } else if (propName === 'style') {\n // 对于 style,需要合并对象\n overrideProps[propName] = { ...parentPropValue, ...childPropValue }\n } else if (propName === 'className') {\n // 对于 className,需要合并字符串\n overrideProps[propName] = [parentPropValue, childPropValue]\n .filter(Boolean)\n .join(' ')\n }\n }\n\n return { ...parentProps, ...overrideProps }\n}\n\n/**\n * 组合多个 ref\n */\nfunction composeRefs<T>(...refs: (Ref<T> | undefined)[]): Ref<T> {\n return (node: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === 'function') {\n ref(node)\n } else if (ref != null) {\n ;(ref as any).current = node\n }\n })\n }\n}\n"],"mappings":";;;;;;;;;AAoBA,MAAa,OAAO,YACjB,EAAE,UAAU,GAAG,SAAS,iBAAiB;AACxC,KAAI,eAAe,SAAS,CAC1B,QAAO,aACL,UACA;EACE,GAAG,WAAW,OAAQ,SAAiB,MAAM;EAC7C,KAAK,eACD,YAAY,cAAe,SAAiB,IAAI,GAC/C,SAAiB;EACvB,CACF;AAGH,QACE,oBAAC,OAAD;EAAK,GAAI;EAAO,KAAK;EAClB;EACG;EAGX;AAED,KAAK,cAAc;;;;AAKnB,SAAS,WAAW,aAAkB,YAAiB;CACrD,MAAM,gBAAgB,EAAE,GAAG,YAAY;AAEvC,MAAK,MAAM,YAAY,YAAY;EACjC,MAAM,kBAAkB,YAAY;EACpC,MAAM,iBAAiB,WAAW;AAGlC,MADkB,WAAW,KAAK,SAAS,EAGzC;OAAI,kBAAkB,gBACpB,eAAc,aAAa,GAAG,SAAgB;AAC5C,mBAAe,GAAG,KAAK;AACvB,oBAAgB,GAAG,KAAK;;YAEjB,gBACT,eAAc,YAAY;aAEnB,aAAa,QAEtB,eAAc,YAAY;GAAE,GAAG;GAAiB,GAAG;GAAgB;WAC1D,aAAa,YAEtB,eAAc,YAAY,CAAC,iBAAiB,eAAe,CACxD,OAAO,QAAQ,CACf,KAAK,IAAI;;AAIhB,QAAO;EAAE,GAAG;EAAa,GAAG;EAAe;;;;;AAM7C,SAAS,YAAe,GAAG,MAAsC;AAC/D,SAAQ,SAAmB;AACzB,OAAK,SAAS,QAAQ;AACpB,OAAI,OAAO,QAAQ,WACjB,KAAI,KAAK;YACA,OAAO,KACf,CAAC,IAAY,UAAU;IAE1B"}
package/package.json CHANGED
@@ -1,35 +1,32 @@
1
1
  {
2
2
  "name": "tona-ui",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "UI components for Tona",
5
+ "keywords": [
6
+ "components",
7
+ "react",
8
+ "ui",
9
+ "博客园"
10
+ ],
11
+ "homepage": "https://github.com/guangzan/tona/tree/main/packages/ui#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/guangzan/tona/issues"
14
+ },
15
+ "license": "MIT",
5
16
  "author": {
6
17
  "name": "guangzan",
7
- "url": "https://www.cnblogs.com/guangzan",
8
- "email": "guangzan1999@outlook.com"
18
+ "email": "guangzan1999@outlook.com",
19
+ "url": "https://www.cnblogs.com/guangzan"
9
20
  },
10
- "license": "MIT",
11
- "homepage": "https://github.com/guangzan/tona/tree/main/packages/ui#readme",
12
21
  "repository": {
13
22
  "type": "git",
14
23
  "url": "git+https://github.com/guangzan/tona.git",
15
24
  "directory": "packages/ui"
16
25
  },
17
- "bugs": {
18
- "url": "https://github.com/guangzan/tona/issues"
19
- },
20
- "keywords": [
21
- "ui",
22
- "components",
23
- "react",
24
- "博客园"
26
+ "files": [
27
+ "dist"
25
28
  ],
26
29
  "sideEffects": false,
27
- "exports": {
28
- ".": {
29
- "types": "./dist/index.d.ts",
30
- "import": "./dist/index.mjs"
31
- }
32
- },
33
30
  "main": "./dist/index.mjs",
34
31
  "module": "./dist/index.mjs",
35
32
  "types": "./dist/index.d.ts",
@@ -41,19 +38,22 @@
41
38
  ]
42
39
  }
43
40
  },
44
- "files": [
45
- "dist"
46
- ],
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/index.d.ts",
44
+ "import": "./dist/index.mjs"
45
+ }
46
+ },
47
47
  "devDependencies": {
48
- "@types/node": "^25.0.3",
49
- "tsdown": "latest",
50
- "vitest": "^4.0.16"
48
+ "@types/node": "^25.5.0",
49
+ "vite-plus": "latest",
50
+ "vitest": "npm:@voidzero-dev/vite-plus-test@latest"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "preact": ">=10.0.0"
54
54
  },
55
55
  "scripts": {
56
- "dev": "tsdown --watch",
57
- "build": "tsdown"
56
+ "dev": "vp pack --watch",
57
+ "build": "vp pack"
58
58
  }
59
59
  }