@shapesos/clay 0.3.0 → 0.3.1
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 +198 -73
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,45 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Clay
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Tokens, theming, and composable React components.**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@shapesos/clay)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://bundlephobia.com/package/@shapesos/clay)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
6
16
|
|
|
7
17
|
```bash
|
|
8
|
-
|
|
18
|
+
npm install @shapesos/clay
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { colors, typographyTypes } from "@shapesos/clay/tokens";
|
|
23
|
+
import { Chat } from "@shapesos/clay/chat";
|
|
24
|
+
import { Lottie } from "@shapesos/clay/lottie";
|
|
9
25
|
```
|
|
10
26
|
|
|
11
27
|
## Entry Points
|
|
12
28
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
| `@
|
|
18
|
-
| `@
|
|
29
|
+
Clay is tree-shakeable with multiple entry points — import only what you need.
|
|
30
|
+
|
|
31
|
+
| Import | Contents | Peer Dependencies |
|
|
32
|
+
| ------------------------- | ------------------------------------- | ------------------------ |
|
|
33
|
+
| `@shapesos/clay/tokens` | Colors, typography, font families | None (pure JS) |
|
|
34
|
+
| `@shapesos/clay/chat` | Chat compound components + types | React, styled-components |
|
|
35
|
+
| `@shapesos/clay/icon` | Icon, IconButton components + types | React, styled-components |
|
|
36
|
+
| `@shapesos/clay/lottie` | Lottie animation component + types | React, styled-components |
|
|
37
|
+
| `@shapesos/clay` | Everything (convenience re-export) | React, styled-components |
|
|
38
|
+
|
|
39
|
+
---
|
|
19
40
|
|
|
20
|
-
##
|
|
41
|
+
## Design Tokens
|
|
21
42
|
|
|
22
|
-
|
|
43
|
+
Pure JavaScript color and typography tokens — no React required.
|
|
23
44
|
|
|
24
45
|
```typescript
|
|
25
|
-
import { colors, typographyStyles, typographyTypes, typographyMixin } from "@
|
|
46
|
+
import { colors, typographyStyles, typographyTypes, typographyMixin } from "@shapesos/clay/tokens";
|
|
26
47
|
|
|
27
|
-
|
|
48
|
+
// Color palette
|
|
49
|
+
colors["brown-100"]; // "#171716"
|
|
50
|
+
colors["brown-900"]; // "#F7F5F3"
|
|
28
51
|
|
|
52
|
+
// Typography definitions
|
|
29
53
|
typographyStyles[typographyTypes.GEIST_BODY_S_REGULAR];
|
|
30
|
-
// { fontFamily: "Geist", fontSize: 16, fontWeight: 400, lineHeight: 24, letterSpacing: -0.08 }
|
|
54
|
+
// => { fontFamily: "Geist", fontSize: 16, fontWeight: 400, lineHeight: 24, letterSpacing: -0.08 }
|
|
31
55
|
|
|
56
|
+
// CSS mixin for styled-components
|
|
32
57
|
typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM);
|
|
33
|
-
// CSS string
|
|
58
|
+
// => CSS string ready to use in template literals
|
|
34
59
|
```
|
|
35
60
|
|
|
36
|
-
|
|
61
|
+
---
|
|
37
62
|
|
|
38
|
-
|
|
63
|
+
## Chat
|
|
64
|
+
|
|
65
|
+
Composable compound components for building chat interfaces. `Chat.Root` provides context — children consume it, giving you full control over layout.
|
|
39
66
|
|
|
40
67
|
```tsx
|
|
41
|
-
import { Chat } from "@
|
|
42
|
-
import type { ChatMessage } from "@
|
|
68
|
+
import { Chat } from "@shapesos/clay/chat";
|
|
69
|
+
import type { ChatMessage } from "@shapesos/clay/chat";
|
|
43
70
|
|
|
44
71
|
function MyChat() {
|
|
45
72
|
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
|
@@ -62,29 +89,30 @@ function MyChat() {
|
|
|
62
89
|
}
|
|
63
90
|
```
|
|
64
91
|
|
|
65
|
-
|
|
92
|
+
<details>
|
|
93
|
+
<summary><strong>Props Reference</strong></summary>
|
|
66
94
|
|
|
67
|
-
####
|
|
95
|
+
#### Chat.Root
|
|
68
96
|
|
|
69
|
-
|
|
97
|
+
| Prop | Type | Required | Description |
|
|
98
|
+
| ------------------ | ---------------------------------------------------------- | -------- | ---------------------------------- |
|
|
99
|
+
| `messages` | `ChatMessage[]` | Yes | Array of messages to display |
|
|
100
|
+
| `onSendMessage` | `(content: string) => void` | Yes | Called when the user sends |
|
|
101
|
+
| `isLoading` | `boolean` | No | Show stop button while loading |
|
|
102
|
+
| `onStop` | `() => void` | No | Called when the user clicks stop |
|
|
103
|
+
| `onCopyMessage` | `(messageId: string) => void` | No | Called when a message is copied |
|
|
104
|
+
| `onThumbUpClick` | `(messageId: string, isHelpful: boolean \| null) => void` | No | Thumbs up feedback |
|
|
105
|
+
| `onThumbDownClick` | `(messageId: string, isHelpful: boolean \| null) => void` | No | Thumbs down feedback |
|
|
70
106
|
|
|
71
|
-
|
|
72
|
-
| ------------------ | ---------------------------------------------------------- | -------- | ----------------------------------------------- |
|
|
73
|
-
| `messages` | `ChatMessage[]` | Yes | Array of messages to display |
|
|
74
|
-
| `onSendMessage` | `(content: string) => void` | Yes | Called when the user sends a message |
|
|
75
|
-
| `isLoading` | `boolean` | No | Show stop button while loading |
|
|
76
|
-
| `onStop` | `() => void` | No | Called when the user clicks stop |
|
|
77
|
-
| `onCopyMessage` | `(messageId: string) => void` | No | Called when a message is copied |
|
|
78
|
-
| `onThumbUpClick` | `(messageId: string, isHelpful: boolean \| null) => void` | No | Called when thumbs up is clicked |
|
|
79
|
-
| `onThumbDownClick` | `(messageId: string, isHelpful: boolean \| null) => void` | No | Called when thumbs down is clicked |
|
|
107
|
+
#### Chat.Composer
|
|
80
108
|
|
|
81
|
-
|
|
109
|
+
| Prop | Type | Required | Default | Description |
|
|
110
|
+
| ------------- | -------- | -------- | ---------------------- | ----------------- |
|
|
111
|
+
| `placeholder` | `string` | No | `"Type a message..."` | Input placeholder |
|
|
82
112
|
|
|
83
|
-
|
|
84
|
-
| ------------- | -------- | -------- | -------------------- | ------------------ |
|
|
85
|
-
| `placeholder` | `string` | No | `"Type a message..."` | Input placeholder |
|
|
113
|
+
#### Chat.MessageList
|
|
86
114
|
|
|
87
|
-
|
|
115
|
+
No props — reads messages from context.
|
|
88
116
|
|
|
89
117
|
#### Data Model
|
|
90
118
|
|
|
@@ -94,15 +122,21 @@ type MessageRole = "user" | "assistant";
|
|
|
94
122
|
interface ChatMessage {
|
|
95
123
|
id: string;
|
|
96
124
|
role: MessageRole;
|
|
97
|
-
content: string;
|
|
125
|
+
content: string; // Markdown supported
|
|
98
126
|
isHelpful?: boolean | null;
|
|
99
127
|
}
|
|
100
128
|
```
|
|
101
129
|
|
|
102
|
-
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Icon
|
|
135
|
+
|
|
136
|
+
Render SVG icons with consistent sizing, and icon buttons with selection states.
|
|
103
137
|
|
|
104
138
|
```tsx
|
|
105
|
-
import { Icon, IconButton } from "@
|
|
139
|
+
import { Icon, IconButton } from "@shapesos/clay/icon";
|
|
106
140
|
import { IconSearch, IconCopy } from "@tabler/icons-react";
|
|
107
141
|
|
|
108
142
|
<Icon icon={IconSearch} size={20} color="#333" aria-label="Search" />
|
|
@@ -110,38 +144,121 @@ import { IconSearch, IconCopy } from "@tabler/icons-react";
|
|
|
110
144
|
<IconButton icon={IconCopy} size="small" onClick={handleCopy} aria-label="Copy" />
|
|
111
145
|
```
|
|
112
146
|
|
|
113
|
-
|
|
147
|
+
<details>
|
|
148
|
+
<summary><strong>Props Reference</strong></summary>
|
|
114
149
|
|
|
115
|
-
|
|
150
|
+
#### Icon
|
|
116
151
|
|
|
117
|
-
| Prop | Type | Required | Default | Description
|
|
118
|
-
| ------------ | ---------------------------------------- | -------- | ------- |
|
|
152
|
+
| Prop | Type | Required | Default | Description |
|
|
153
|
+
| ------------ | ---------------------------------------- | -------- | ------- | ------------------------ |
|
|
119
154
|
| `icon` | `ComponentType<SVGProps<SVGSVGElement>>` | Yes | | Icon component to render |
|
|
120
|
-
| `size` | `number` | No | `16` |
|
|
155
|
+
| `size` | `number` | No | `16` | Size in pixels |
|
|
121
156
|
| `color` | `string` | No | | Icon color |
|
|
122
157
|
| `className` | `string` | No | | CSS class |
|
|
123
158
|
| `aria-label` | `string` | No | | Accessible label |
|
|
124
159
|
|
|
125
|
-
|
|
160
|
+
#### IconButton
|
|
161
|
+
|
|
162
|
+
| Prop | Type | Required | Default | Description |
|
|
163
|
+
| ------------ | ---------------------------------------- | -------- | --------- | ------------------------ |
|
|
164
|
+
| `icon` | `ComponentType<SVGProps<SVGSVGElement>>` | Yes | | Icon component to render |
|
|
165
|
+
| `size` | `"small" \| "medium"` | No | `"small"` | Button size |
|
|
166
|
+
| `isSelected` | `boolean` | No | `false` | Selected state |
|
|
167
|
+
| `disabled` | `boolean` | No | `false` | Disabled state |
|
|
168
|
+
| `onClick` | `() => void` | No | | Click handler |
|
|
169
|
+
| `className` | `string` | No | | CSS class |
|
|
170
|
+
| `aria-label` | `string` | No | | Accessible label |
|
|
171
|
+
|
|
172
|
+
</details>
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Lottie
|
|
126
177
|
|
|
127
|
-
|
|
128
|
-
| ------------ | ---------------------------------------- | -------- | --------- | -------------------------- |
|
|
129
|
-
| `icon` | `ComponentType<SVGProps<SVGSVGElement>>` | Yes | | Icon component to render |
|
|
130
|
-
| `size` | `"small" \| "medium"` | No | `"small"` | Button size |
|
|
131
|
-
| `isSelected` | `boolean` | No | `false` | Selected/active state |
|
|
132
|
-
| `disabled` | `boolean` | No | `false` | Disabled state |
|
|
133
|
-
| `onClick` | `() => void` | No | | Click handler |
|
|
134
|
-
| `className` | `string` | No | | CSS class |
|
|
135
|
-
| `aria-label` | `string` | No | | Accessible label |
|
|
178
|
+
Render [Lottie](https://airbnb.io/lottie/) animations with declarative props, hover interactions, and imperative playback control.
|
|
136
179
|
|
|
137
|
-
|
|
180
|
+
```tsx
|
|
181
|
+
import { Lottie } from "@shapesos/clay/lottie";
|
|
182
|
+
import animationData from "./my-animation.json";
|
|
183
|
+
|
|
184
|
+
// Basic — loops forever
|
|
185
|
+
<Lottie animationData={animationData} />
|
|
186
|
+
|
|
187
|
+
// Interactive — plays once, then replays on hover
|
|
188
|
+
<Lottie
|
|
189
|
+
animationData={animationData}
|
|
190
|
+
loop={false}
|
|
191
|
+
playOnHover
|
|
192
|
+
loopOnHover
|
|
193
|
+
width={80}
|
|
194
|
+
height={80}
|
|
195
|
+
/>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Imperative control** via ref:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import type { LottieRef } from "@shapesos/clay/lottie";
|
|
202
|
+
|
|
203
|
+
const ref = useRef<LottieRef>(null);
|
|
204
|
+
|
|
205
|
+
<Lottie ref={ref} animationData={animationData} autoplay={false} />
|
|
206
|
+
<button onClick={() => ref.current?.play()}>Play</button>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Props Reference</strong></summary>
|
|
211
|
+
|
|
212
|
+
#### Lottie
|
|
213
|
+
|
|
214
|
+
| Prop | Type | Required | Default | Description |
|
|
215
|
+
| ------------------- | ---------------------------------------------------------------- | -------- | ------- | ------------------------------ |
|
|
216
|
+
| `animationData` | `LottieAnimationData` | Yes | | Lottie JSON data |
|
|
217
|
+
| `autoplay` | `boolean` | No | `true` | Play on mount |
|
|
218
|
+
| `loop` | `boolean \| number` | No | `true` | Loop forever, or N times |
|
|
219
|
+
| `speed` | `number` | No | `1` | Playback speed |
|
|
220
|
+
| `direction` | `1 \| -1` | No | `1` | Forward or reverse |
|
|
221
|
+
| `width` | `string \| number` | No | | Container width |
|
|
222
|
+
| `height` | `string \| number` | No | | Container height |
|
|
223
|
+
| `playOnHover` | `boolean` | No | `false` | Replay on mouse enter |
|
|
224
|
+
| `loopOnHover` | `boolean` | No | `false` | Loop while hovering |
|
|
225
|
+
| `className` | `string` | No | | CSS class |
|
|
226
|
+
| `aria-label` | `string` | No | | Accessible label |
|
|
227
|
+
| `onAnimationLoaded` | `(animation: AnimationItem) => void` | No | | Fired when animation loads |
|
|
228
|
+
| `onComplete` | `() => void` | No | | Fired on completion |
|
|
229
|
+
| `onLoopComplete` | `() => void` | No | | Fired on each loop |
|
|
230
|
+
| `onEnterFrame` | `(frame: { currentTime: number; totalTime: number }) => void` | No | | Fired on each frame |
|
|
231
|
+
|
|
232
|
+
#### LottieRef (imperative handle)
|
|
233
|
+
|
|
234
|
+
| Method | Description |
|
|
235
|
+
| ---------------------------------- | ---------------------------------- |
|
|
236
|
+
| `play()` | Start playback |
|
|
237
|
+
| `pause()` | Pause playback |
|
|
238
|
+
| `stop()` | Stop and reset to frame 0 |
|
|
239
|
+
| `goToAndPlay(value, isFrame?)` | Jump to value and play |
|
|
240
|
+
| `goToAndStop(value, isFrame?)` | Jump to value and stop |
|
|
241
|
+
| `setDirection(direction)` | Set direction (1 or -1) |
|
|
242
|
+
| `setSpeed(speed)` | Set playback speed |
|
|
243
|
+
| `getAnimationItem()` | Access underlying lottie-web instance |
|
|
244
|
+
|
|
245
|
+
</details>
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## TypeScript
|
|
250
|
+
|
|
251
|
+
All components export their prop types:
|
|
138
252
|
|
|
139
253
|
```typescript
|
|
140
|
-
import type { ColorToken, TypographyStyle, TypographyType } from "@
|
|
141
|
-
import type { ChatMessage, MessageRole, ChatContextValue } from "@
|
|
142
|
-
import type { IconProps, IconButtonProps, IconButtonSize } from "@
|
|
254
|
+
import type { ColorToken, TypographyStyle, TypographyType } from "@shapesos/clay/tokens";
|
|
255
|
+
import type { ChatMessage, MessageRole, ChatContextValue } from "@shapesos/clay/chat";
|
|
256
|
+
import type { IconProps, IconButtonProps, IconButtonSize } from "@shapesos/clay/icon";
|
|
257
|
+
import type { LottieProps, LottieRef, LottieAnimationData } from "@shapesos/clay/lottie";
|
|
143
258
|
```
|
|
144
259
|
|
|
260
|
+
---
|
|
261
|
+
|
|
145
262
|
## Development
|
|
146
263
|
|
|
147
264
|
```bash
|
|
@@ -150,20 +267,28 @@ cd shapes-clay
|
|
|
150
267
|
bun install
|
|
151
268
|
```
|
|
152
269
|
|
|
153
|
-
| Command
|
|
154
|
-
|
|
|
155
|
-
| `bun run storybook`
|
|
156
|
-
| `bun run build`
|
|
157
|
-
| `bun run dev`
|
|
158
|
-
| `bun run test`
|
|
159
|
-
| `bun run test:coverage`
|
|
160
|
-
| `bun run test:e2e`
|
|
161
|
-
| `bun run
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
270
|
+
| Command | Description |
|
|
271
|
+
| ----------------------- | ------------------------------------------- |
|
|
272
|
+
| `bun run storybook` | Component playground (localhost:6006) |
|
|
273
|
+
| `bun run build` | Build package (tsup) |
|
|
274
|
+
| `bun run dev` | Build in watch mode |
|
|
275
|
+
| `bun run test` | Unit tests (Vitest) |
|
|
276
|
+
| `bun run test:coverage` | Unit tests with coverage |
|
|
277
|
+
| `bun run test:e2e` | E2E tests (Playwright + Storybook) |
|
|
278
|
+
| `bun run check` | All quality gates (lint + typecheck + test) |
|
|
279
|
+
|
|
280
|
+
### Releasing
|
|
281
|
+
|
|
282
|
+
Clay uses [changesets](https://github.com/changesets/changesets) for versioning. When making changes:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
bunx changeset # Describe your change and its semver impact
|
|
286
|
+
git add .changeset/ # Commit the changeset with your PR
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
On merge to `master`, a "Version Packages" PR is created automatically. Merging that PR publishes to npm.
|
|
290
|
+
|
|
291
|
+
---
|
|
167
292
|
|
|
168
293
|
## License
|
|
169
294
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shapesos/clay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"main": "./dist/index.cjs",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"devDependencies": {
|
|
7
|
+
"@changesets/changelog-github": "^0.6.0",
|
|
8
|
+
"@changesets/cli": "^2.30.0",
|
|
7
9
|
"@eslint/js": "^10.0.1",
|
|
8
10
|
"@playwright/test": "^1.58.2",
|
|
9
11
|
"@storybook/react": "^10.2.13",
|