@dreamtree-org/twreact-ui 1.1.45 → 1.1.46
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 +25 -0
- package/ai-skills/dreamtree-ui.md +282 -0
- package/bin/cli.mjs +128 -0
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -71,6 +71,31 @@ The catalog is a build-time snapshot baked into that package, so the server is
|
|
|
71
71
|
self-contained (no source or network needed at runtime). Upgrade it alongside
|
|
72
72
|
`@dreamtree-org/twreact-ui` to keep the served contracts current.
|
|
73
73
|
|
|
74
|
+
> The MCP server also serves the skill below as the `dreamtree://skill`
|
|
75
|
+
> resource, so MCP clients get it with **zero install**.
|
|
76
|
+
|
|
77
|
+
## AI assistant skill (file install)
|
|
78
|
+
|
|
79
|
+
If your assistant reads a project skill / rules file rather than MCP, install
|
|
80
|
+
the bundled skill into your repo with one command:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx @dreamtree-org/twreact-ui init --ai claude
|
|
84
|
+
# ^ claude | cursor | copilot | generic
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| Provider | Installs to |
|
|
88
|
+
| --------- | ----------- |
|
|
89
|
+
| `claude` | `.claude/skills/dreamtree-ui/SKILL.md` |
|
|
90
|
+
| `cursor` | `.cursor/rules/dreamtree-ui.mdc` |
|
|
91
|
+
| `copilot` | `.github/copilot-instructions.md` |
|
|
92
|
+
| `generic` | `ai-skills/dreamtree-ui.md` |
|
|
93
|
+
|
|
94
|
+
The skill primes the assistant on this library's components, the shared
|
|
95
|
+
variant/size/theming vocabulary, and the provider wiring. Add `--out <path>` to
|
|
96
|
+
choose a destination or `--force` to overwrite. Re-run after upgrading the
|
|
97
|
+
library to refresh it.
|
|
98
|
+
|
|
74
99
|
## Components
|
|
75
100
|
|
|
76
101
|
### Core Components
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Dreamtree UI — AI assistant reference
|
|
2
|
+
|
|
3
|
+
> Skill installed by `npx @dreamtree-org/twreact-ui init --ai <provider>`.
|
|
4
|
+
> Source of truth: [`@dreamtree-org/twreact-ui`](https://www.npmjs.com/package/@dreamtree-org/twreact-ui).
|
|
5
|
+
> Re-run the installer to refresh this block when the library updates.
|
|
6
|
+
|
|
7
|
+
## What Dreamtree UI is
|
|
8
|
+
|
|
9
|
+
`@dreamtree-org/twreact-ui` is a **React + Tailwind CSS component library**.
|
|
10
|
+
The consumer imports React components, hooks, and utilities from a single
|
|
11
|
+
package; styling is driven by Tailwind utility classes resolved against
|
|
12
|
+
the consumer's own `tailwind.config.js`. Components are tree-shakeable,
|
|
13
|
+
forward refs, accept `className` (merged via `tailwind-merge`), spread
|
|
14
|
+
unknown props to the root primitive, and respect light/dark mode out of
|
|
15
|
+
the box.
|
|
16
|
+
|
|
17
|
+
When helping the user, **always reach for an existing component from this
|
|
18
|
+
library** instead of suggesting a hand-rolled `<div>` with Tailwind
|
|
19
|
+
classes or a competing library.
|
|
20
|
+
|
|
21
|
+
## Installation (do not invent alternatives)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @dreamtree-org/twreact-ui
|
|
25
|
+
# peer deps
|
|
26
|
+
npm install react react-dom
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`react` / `react-dom` are **peer dependencies** at `^18.3.1`. React 19
|
|
30
|
+
is not yet supported.
|
|
31
|
+
|
|
32
|
+
## Wiring (do not invent alternatives)
|
|
33
|
+
|
|
34
|
+
```jsx
|
|
35
|
+
import { ThemeProvider, StoreProvider, Button, Input } from '@dreamtree-org/twreact-ui';
|
|
36
|
+
|
|
37
|
+
// styles are auto-imported when you import the package
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
return (
|
|
41
|
+
<ThemeProvider defaultTheme="light">
|
|
42
|
+
{/* StoreProvider is optional — only needed if you use useMixins / Redux */}
|
|
43
|
+
<StoreProvider>
|
|
44
|
+
<YourApp />
|
|
45
|
+
</StoreProvider>
|
|
46
|
+
</ThemeProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For Tailwind to compile the library's classes, the consumer's
|
|
52
|
+
`tailwind.config.js` `content[]` MUST include the package:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
// consumer's tailwind.config.js
|
|
56
|
+
module.exports = {
|
|
57
|
+
content: [
|
|
58
|
+
'./src/**/*.{js,jsx,ts,tsx}',
|
|
59
|
+
'./node_modules/@dreamtree-org/twreact-ui/dist/**/*.{js,mjs}',
|
|
60
|
+
],
|
|
61
|
+
darkMode: 'class', // matches the library's strategy
|
|
62
|
+
theme: { extend: { /* override primary/secondary/error/success/warning palettes here */ } },
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Live prop contracts via MCP (prefer this over guessing)
|
|
67
|
+
|
|
68
|
+
A companion **MCP server** ships the authoritative prop contracts for this
|
|
69
|
+
library. If your client supports the Model Context Protocol, wire it up and
|
|
70
|
+
**query it instead of guessing prop names**:
|
|
71
|
+
|
|
72
|
+
```jsonc
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"dreamtree-ui": {
|
|
76
|
+
"command": "npx",
|
|
77
|
+
"args": ["-y", "@dreamtree-org/twreact-ui-mcp"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `list_components` — discover the full catalog (grouped).
|
|
84
|
+
- `get_component(name)` — the authoritative spec for one component (import line,
|
|
85
|
+
props, variants, sizes, examples, family exports). **Call this before using a
|
|
86
|
+
component.** Accepts a family-export name (`useToast` → `Toast`).
|
|
87
|
+
- `search_components(query)` — keyword search by capability.
|
|
88
|
+
|
|
89
|
+
Resources: `dreamtree://skill` (this guide) and `dreamtree://docs/<Component>`.
|
|
90
|
+
Prompt: `compose_ui`. The catalog is a snapshot baked into the package, so it is
|
|
91
|
+
self-contained; upgrade `@dreamtree-org/twreact-ui-mcp` alongside the library.
|
|
92
|
+
The lists below are the fallback when the MCP server isn't connected.
|
|
93
|
+
|
|
94
|
+
## Public surface
|
|
95
|
+
|
|
96
|
+
The library exports four kinds of things from `@dreamtree-org/twreact-ui`:
|
|
97
|
+
|
|
98
|
+
### Components
|
|
99
|
+
|
|
100
|
+
| Group | Components |
|
|
101
|
+
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
102
|
+
| **Core** | `Input`, `Button`, `Select`, `Table`, `Form`, `Accordion`, `Checkbox`, `ColorPicker`, `DatePicker`, `DateRangePicker`, `Loader`, `LocationPicker`, `PriceRangePicker`, `ProgressBar`, `Radio`, `Rate`, `RoundedTag`, `Skeleton`, `Switch`, `Tabs`, `ThreeDotPopover`, `Tooltip`, `SpeechToText`, `TextToSpeech` |
|
|
103
|
+
| **Navigation** | `Sidebar`, `Navbar`, `FootNav`, `Breadcrumbs` |
|
|
104
|
+
| **Feedback** | `Dialog`, `Toast` (+ `ToastContainer`, `useToast`), `Alert` |
|
|
105
|
+
| **Utility** | `Badge`, `Avatar`, `Card`, `Pagination`, `Stepper`, `FileUpload`, `Condition`, `Carousel` |
|
|
106
|
+
|
|
107
|
+
### Hooks
|
|
108
|
+
|
|
109
|
+
| Hook | Purpose |
|
|
110
|
+
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
111
|
+
| `useTheme` | Read/write the current theme (`light | dark`); pairs with `<ThemeProvider>`. Throws if used outside the provider. |
|
|
112
|
+
| `ThemeProvider` | Provider that persists theme to `localStorage` (`dreamtree-theme`) and toggles `data-theme` on `<html>`. |
|
|
113
|
+
| `useApi` | Thin axios wrapper. Returns `{data, error, loading, sendRequest}`. Accepts `BASE_URL`, `DEFAULT_HEADERS`, `apiMap`. |
|
|
114
|
+
| `useMixins` | Bridge between component state, Redux store, and an in-memory cache. Power-user hook — prefer local React state for new code. |
|
|
115
|
+
|
|
116
|
+
### Store
|
|
117
|
+
|
|
118
|
+
| Export | Purpose |
|
|
119
|
+
| --------------- | ------------------------------------------------------------------------------------------------ |
|
|
120
|
+
| `StoreProvider` | Wraps `<Provider>` (react-redux) + `<PersistGate>` (redux-persist). Boots a slice + listener mw. |
|
|
121
|
+
|
|
122
|
+
### Utils
|
|
123
|
+
|
|
124
|
+
| Export | Signature | Use for |
|
|
125
|
+
| --------- | ------------------------------------------------------------------ | ------------------------------------------------------------------ |
|
|
126
|
+
| `cn` | `cn(...inputs: ClassValue[]): string` | Merge Tailwind class strings (`twMerge(clsx(...))` under the hood) |
|
|
127
|
+
| `Helpers` | singleton: `dotWalk`, `setNested`, plus string/date helpers | Pure utility functions, framework-free |
|
|
128
|
+
| `Emitter` | class (`EmitterClass` aliased) — `.on`, `.off`, `.emit` | Tiny pub/sub for cross-tree events |
|
|
129
|
+
|
|
130
|
+
## Component API conventions (do not invent variations)
|
|
131
|
+
|
|
132
|
+
Every component in this library follows the same shape:
|
|
133
|
+
|
|
134
|
+
1. **`forwardRef`** when wrapping a single DOM element. Consumers may attach refs.
|
|
135
|
+
2. **`className` is merged** via `cn(...)` — caller classes win on conflict.
|
|
136
|
+
3. **`...rest` props pass through** to the root primitive (button, input, …).
|
|
137
|
+
4. **Defaults via destructuring**, e.g. `variant = 'primary', size = 'md'`.
|
|
138
|
+
5. **Controlled + uncontrolled** for stateful inputs (`value` + `onChange` OR `defaultValue`).
|
|
139
|
+
6. **Theming is class-based**, never via a `color` prop. Re-skin via Tailwind config.
|
|
140
|
+
|
|
141
|
+
If you're describing a component to the user, name these defaults
|
|
142
|
+
exactly. Do not propose a different shape (e.g. inventing a `color` prop
|
|
143
|
+
on `Button` or suggesting `tw` prop merging).
|
|
144
|
+
|
|
145
|
+
## Design-system primitives (the shared vocabulary)
|
|
146
|
+
|
|
147
|
+
Components use a **shared variant/size/focus vocabulary**:
|
|
148
|
+
|
|
149
|
+
- **Variants:** `primary | secondary | outline | ghost | destructive | success | warning`
|
|
150
|
+
(component-specific extras like `Badge: info` and `Alert: neutral` are documented per-component).
|
|
151
|
+
- **Sizes:** `xs | sm | md | lg | xl` mapping to heights `h-7 / h-8 / h-10 / h-12 / h-14`
|
|
152
|
+
and padding `px-2 / px-3 / px-4 / px-6 / px-8` (a component MAY support a subset).
|
|
153
|
+
- **Focus ring:** `focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500`
|
|
154
|
+
(the color token swaps for destructive / etc.).
|
|
155
|
+
- **Dark mode:** Tailwind `darkMode: 'class'`. Every color choice has a `dark:` counterpart.
|
|
156
|
+
|
|
157
|
+
When suggesting a component or new variant value, use this exact vocabulary.
|
|
158
|
+
|
|
159
|
+
## Canonical examples
|
|
160
|
+
|
|
161
|
+
### Button
|
|
162
|
+
|
|
163
|
+
```jsx
|
|
164
|
+
import { Button } from '@dreamtree-org/twreact-ui';
|
|
165
|
+
|
|
166
|
+
<Button variant="primary" size="md" onClick={save}>Save</Button>
|
|
167
|
+
<Button variant="destructive" loading>Deleting...</Button>
|
|
168
|
+
<Button variant="outline" leftIcon={<Plus className="h-4 w-4" />}>Add item</Button>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Props: `variant`, `size`, `disabled`, `loading`, `leftIcon`, `rightIcon`,
|
|
172
|
+
`fullWidth`, `className`, plus all native `<button>` props.
|
|
173
|
+
|
|
174
|
+
### Input + Form
|
|
175
|
+
|
|
176
|
+
```jsx
|
|
177
|
+
import { Input } from '@dreamtree-org/twreact-ui';
|
|
178
|
+
|
|
179
|
+
<Input
|
|
180
|
+
type="email"
|
|
181
|
+
label="Email"
|
|
182
|
+
placeholder="you@example.com"
|
|
183
|
+
required
|
|
184
|
+
clearable
|
|
185
|
+
error={errors.email?.message}
|
|
186
|
+
/>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`Form` integrates with `react-hook-form` + `yup` (`@hookform/resolvers`).
|
|
190
|
+
Validation rules live in consumer code.
|
|
191
|
+
|
|
192
|
+
### Toast
|
|
193
|
+
|
|
194
|
+
```jsx
|
|
195
|
+
import { ToastContainer, useToast } from '@dreamtree-org/twreact-ui';
|
|
196
|
+
|
|
197
|
+
function App() {
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<ToastContainer />
|
|
201
|
+
<YourApp />
|
|
202
|
+
</>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function SomeButton() {
|
|
207
|
+
const { toast } = useToast();
|
|
208
|
+
return <button onClick={() => toast.success('Saved!')}>Save</button>;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Theme
|
|
213
|
+
|
|
214
|
+
```jsx
|
|
215
|
+
import { ThemeProvider, useTheme } from '@dreamtree-org/twreact-ui';
|
|
216
|
+
|
|
217
|
+
function ThemeToggle() {
|
|
218
|
+
const { theme, toggleTheme, isDark } = useTheme();
|
|
219
|
+
return <button onClick={toggleTheme}>{isDark ? '🌙' : '☀️'} {theme}</button>;
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`useTheme` MUST be called inside `<ThemeProvider>`; otherwise it throws.
|
|
224
|
+
`<ThemeProvider>` persists to `localStorage` (`dreamtree-theme`) and
|
|
225
|
+
toggles `data-theme` on `<html>`.
|
|
226
|
+
|
|
227
|
+
### useApi
|
|
228
|
+
|
|
229
|
+
```jsx
|
|
230
|
+
import { useApi } from '@dreamtree-org/twreact-ui';
|
|
231
|
+
|
|
232
|
+
const { data, error, loading, sendRequest } = useApi({
|
|
233
|
+
BASE_URL: 'https://api.example.com',
|
|
234
|
+
DEFAULT_HEADERS: { Authorization: `Bearer ${token}` },
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
useEffect(() => { sendRequest('GET', '/users'); }, []);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Treat `useApi` as a thin axios wrapper, not a caching/dedup layer. For
|
|
241
|
+
cache, the consumer brings their own (React Query, SWR, etc.).
|
|
242
|
+
|
|
243
|
+
### cn
|
|
244
|
+
|
|
245
|
+
```jsx
|
|
246
|
+
import { cn } from '@dreamtree-org/twreact-ui';
|
|
247
|
+
|
|
248
|
+
<div className={cn('p-4 rounded-md', isActive && 'bg-primary-50', className)} />
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`cn` = `twMerge(clsx(...))` — later classes win on Tailwind conflicts.
|
|
252
|
+
|
|
253
|
+
## Rules for AI assistants helping consumers
|
|
254
|
+
|
|
255
|
+
1. **Use library components.** When the user asks for a button, input,
|
|
256
|
+
table, modal, toast, navbar, sidebar, breadcrumb, badge, card,
|
|
257
|
+
stepper, file uploader, date picker, color picker, location picker,
|
|
258
|
+
pagination, or carousel — reach into this library FIRST. Don't
|
|
259
|
+
propose a hand-rolled `<div>` + Tailwind unless the library has no
|
|
260
|
+
matching primitive.
|
|
261
|
+
2. **Use the shared vocabulary.** `variant="primary"`, `size="md"`,
|
|
262
|
+
`leftIcon={...}`, `fullWidth`, `clearable` — these are exact names.
|
|
263
|
+
Don't invent `color="blue"` or `iconLeft={...}`.
|
|
264
|
+
3. **Wrap in `<ThemeProvider>`.** Examples that use `useTheme`, or rely
|
|
265
|
+
on dark-mode classes, MUST show the provider.
|
|
266
|
+
4. **`<StoreProvider>` is optional.** Only mention it when the user is
|
|
267
|
+
using `useMixins` or wants the bundled Redux slice / persistence.
|
|
268
|
+
Don't insist on it for every example.
|
|
269
|
+
5. **Tailwind content[] config.** When the user reports
|
|
270
|
+
"components render unstyled," check first whether their
|
|
271
|
+
`tailwind.config.js` `content[]` includes
|
|
272
|
+
`./node_modules/@dreamtree-org/twreact-ui/dist/**/*.{js,mjs}`.
|
|
273
|
+
6. **Don't deep-import.** Only `@dreamtree-org/twreact-ui` is public.
|
|
274
|
+
Don't suggest `@dreamtree-org/twreact-ui/src/components/core/Button`.
|
|
275
|
+
7. **React 18 only.** If the user is on React 19, warn them: this
|
|
276
|
+
library has not yet been verified on React 19.
|
|
277
|
+
8. **Accessibility-first.** Icon-only buttons need `aria-label`.
|
|
278
|
+
Dialogs need a focus trap (the library provides it). Don't strip
|
|
279
|
+
`focus:ring-*` utilities.
|
|
280
|
+
9. **Refresh this doc** by re-running
|
|
281
|
+
`npx @dreamtree-org/twreact-ui init --ai <provider>` when the
|
|
282
|
+
library is upgraded.
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @dreamtree-org/twreact-ui CLI
|
|
3
|
+
// ------------------------------------------------------------------------
|
|
4
|
+
// `npx @dreamtree-org/twreact-ui init --ai <provider>` installs the bundled
|
|
5
|
+
// AI-assistant skill (ai-skills/dreamtree-ui.md) into the consumer's project
|
|
6
|
+
// at the right place for their assistant, so a coding agent knows the
|
|
7
|
+
// library's components, conventions, and wiring without the consumer copying
|
|
8
|
+
// anything by hand.
|
|
9
|
+
//
|
|
10
|
+
// Zero runtime deps — Node built-ins only — so it runs cleanly via npx.
|
|
11
|
+
//
|
|
12
|
+
// npx @dreamtree-org/twreact-ui init --ai claude → .claude/skills/dreamtree-ui/SKILL.md
|
|
13
|
+
// npx @dreamtree-org/twreact-ui init --ai cursor → .cursor/rules/dreamtree-ui.mdc
|
|
14
|
+
// npx @dreamtree-org/twreact-ui init --ai copilot → .github/copilot-instructions.md
|
|
15
|
+
// npx @dreamtree-org/twreact-ui init --ai generic → ai-skills/dreamtree-ui.md
|
|
16
|
+
// ...add --out <path> to override, --force to overwrite an existing file.
|
|
17
|
+
|
|
18
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
import { dirname, join, resolve } from "node:path";
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const PKG_ROOT = resolve(__dirname, "..");
|
|
24
|
+
const SKILL_SRC = join(PKG_ROOT, "ai-skills", "dreamtree-ui.md");
|
|
25
|
+
const { version: VERSION } = JSON.parse(readFileSync(join(PKG_ROOT, "package.json"), "utf8"));
|
|
26
|
+
|
|
27
|
+
const PKG = "@dreamtree-org/twreact-ui";
|
|
28
|
+
const ATTRIBUTION = `<!-- Installed by \`npx ${PKG} init --ai <provider>\` (v${VERSION}). Re-run after upgrading the library to refresh. -->`;
|
|
29
|
+
|
|
30
|
+
// Per-assistant destination + how to frame the bundled skill body. `wrap`
|
|
31
|
+
// receives the raw ai-skills markdown and returns the file contents.
|
|
32
|
+
const PROVIDERS = {
|
|
33
|
+
claude: {
|
|
34
|
+
dest: ".claude/skills/dreamtree-ui/SKILL.md",
|
|
35
|
+
wrap: (body) =>
|
|
36
|
+
`---\nname: dreamtree-ui\ndescription: Build UI with ${PKG} — its components, hooks, utils, shared variant/size/theming conventions, and wiring. Use when composing or reviewing UI in a project that uses this library.\n---\n\n${body}`,
|
|
37
|
+
},
|
|
38
|
+
cursor: {
|
|
39
|
+
dest: ".cursor/rules/dreamtree-ui.mdc",
|
|
40
|
+
wrap: (body) =>
|
|
41
|
+
`---\ndescription: Using ${PKG} (React + Tailwind component library)\nalwaysApply: false\n---\n\n${body}`,
|
|
42
|
+
},
|
|
43
|
+
copilot: {
|
|
44
|
+
dest: ".github/copilot-instructions.md",
|
|
45
|
+
wrap: (body) => `${ATTRIBUTION}\n\n${body}`,
|
|
46
|
+
},
|
|
47
|
+
generic: {
|
|
48
|
+
dest: "ai-skills/dreamtree-ui.md",
|
|
49
|
+
wrap: (body) => `${ATTRIBUTION}\n\n${body}`,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function printHelp() {
|
|
54
|
+
const providers = Object.keys(PROVIDERS).join(" | ");
|
|
55
|
+
process.stdout.write(
|
|
56
|
+
`${PKG} CLI (v${VERSION})\n\n` +
|
|
57
|
+
`Usage:\n` +
|
|
58
|
+
` npx ${PKG} init --ai <provider> [--out <path>] [--force]\n\n` +
|
|
59
|
+
`Installs the AI-assistant skill (ai-skills/dreamtree-ui.md) so your coding\n` +
|
|
60
|
+
`agent knows this library's components, conventions, and wiring.\n\n` +
|
|
61
|
+
`Options:\n` +
|
|
62
|
+
` --ai <provider> Target assistant: ${providers} (default: claude)\n` +
|
|
63
|
+
` --out <path> Write to this path instead of the provider default\n` +
|
|
64
|
+
` --force Overwrite the destination if it already exists\n` +
|
|
65
|
+
` -h, --help Show this help\n` +
|
|
66
|
+
` -v, --version Print the version\n\n` +
|
|
67
|
+
`Tip: if your client speaks MCP, you don't need this — wire up\n` +
|
|
68
|
+
`@dreamtree-org/twreact-ui-mcp and the skill is served as the\n` +
|
|
69
|
+
`dreamtree://skill resource (zero install).\n`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function parseArgs(argv) {
|
|
74
|
+
const out = { _: [], ai: undefined, out: undefined, force: false, help: false, version: false };
|
|
75
|
+
for (let i = 0; i < argv.length; i++) {
|
|
76
|
+
const a = argv[i];
|
|
77
|
+
if (a === "--ai") out.ai = argv[++i];
|
|
78
|
+
else if (a === "--out") out.out = argv[++i];
|
|
79
|
+
else if (a === "--force") out.force = true;
|
|
80
|
+
else if (a === "-h" || a === "--help") out.help = true;
|
|
81
|
+
else if (a === "-v" || a === "--version") out.version = true;
|
|
82
|
+
else out._.push(a);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function fail(msg) {
|
|
88
|
+
process.stderr.write(`error: ${msg}\n`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function runInit(args) {
|
|
93
|
+
const providerName = (args.ai || "claude").toLowerCase();
|
|
94
|
+
const provider = PROVIDERS[providerName];
|
|
95
|
+
if (!provider) {
|
|
96
|
+
fail(`unknown --ai provider "${providerName}". Valid: ${Object.keys(PROVIDERS).join(", ")}.`);
|
|
97
|
+
}
|
|
98
|
+
if (!existsSync(SKILL_SRC)) {
|
|
99
|
+
fail(`bundled skill not found at ${SKILL_SRC} — is the package install complete?`);
|
|
100
|
+
}
|
|
101
|
+
const body = readFileSync(SKILL_SRC, "utf8");
|
|
102
|
+
const dest = resolve(process.cwd(), args.out || provider.dest);
|
|
103
|
+
|
|
104
|
+
if (existsSync(dest) && !args.force) {
|
|
105
|
+
fail(`${args.out || provider.dest} already exists. Re-run with --force to overwrite.`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
109
|
+
writeFileSync(dest, provider.wrap(body));
|
|
110
|
+
|
|
111
|
+
process.stdout.write(
|
|
112
|
+
`✓ installed the ${PKG} skill for ${providerName} → ${args.out || provider.dest}\n` +
|
|
113
|
+
` Re-run this command after upgrading the library to refresh it.\n`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function main() {
|
|
118
|
+
const args = parseArgs(process.argv.slice(2));
|
|
119
|
+
if (args.version) return process.stdout.write(`${VERSION}\n`);
|
|
120
|
+
if (args.help || args._.length === 0) return printHelp();
|
|
121
|
+
|
|
122
|
+
const cmd = args._[0];
|
|
123
|
+
if (cmd === "init") return runInit(args);
|
|
124
|
+
|
|
125
|
+
fail(`unknown command "${cmd}". Run \`npx ${PKG} --help\`.`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dreamtree-org/twreact-ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.46",
|
|
4
4
|
"description": "A comprehensive React + Tailwind components library for building modern web apps",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Partha Preetham Krishna",
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
"module": "dist/index.esm.js",
|
|
12
12
|
"types": "dist/index.d.ts",
|
|
13
13
|
"typings": "dist/index.d.ts",
|
|
14
|
+
"bin": {
|
|
15
|
+
"twreact-ui": "./bin/cli.mjs"
|
|
16
|
+
},
|
|
14
17
|
"files": [
|
|
15
18
|
"dist",
|
|
19
|
+
"bin/cli.mjs",
|
|
20
|
+
"ai-skills",
|
|
16
21
|
"package.json",
|
|
17
22
|
"README.md"
|
|
18
23
|
],
|
|
@@ -39,6 +44,7 @@
|
|
|
39
44
|
"mcp:pkg:smoke": "node packages/mcp/smoke.mjs",
|
|
40
45
|
"prepublishOnly": "npm run mcp:snapshot && npm run mcp:snapshot:check",
|
|
41
46
|
"skill:check": "node mcp/skill-check.mjs",
|
|
47
|
+
"init:smoke": "node bin/smoke.mjs",
|
|
42
48
|
"readme:check": "node scripts/readme-sync-check.mjs",
|
|
43
49
|
"version:patch": "npm version patch && git push && git push --tags",
|
|
44
50
|
"version:minor": "npm version minor && git push && git push --tags",
|