@asharca/ui 0.1.0 → 0.2.0

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
@@ -5,12 +5,18 @@ Reusable React controls, chat thread, conversation sidebar, and responsive shell
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- pnpm add @asharca/ui
9
- # or: npm install @asharca/ui
8
+ pnpm add @asharca/ui @assistant-ui/react@0.15.18
9
+ # or: npm install @asharca/ui @assistant-ui/react@0.15.18
10
10
  ```
11
11
 
12
12
  The package uses React 19 and Tailwind CSS 4. `ChatThread` additionally accepts an assistant-ui `AssistantRuntime`, so transport and persistence stay in the host application.
13
13
 
14
+ The runtime peer is pinned to `@assistant-ui/react@0.15.18`, paired with
15
+ `@assistant-ui/react-streamdown@0.3.13`. These are the latest releases verified on
16
+ September 5, 2026. Older runtime versions are not supported. Hosts that also use
17
+ the Streamdown adapter should use `0.3.13` so the renderer and host share the same
18
+ assistant-ui context. No package patch or legacy runtime hook is required.
19
+
14
20
  Import the stylesheet once from the host application's global Tailwind stylesheet:
15
21
 
16
22
  ```css
@@ -114,23 +120,50 @@ Theme defaults are scoped to package component roots. Override them with HSL-cha
114
120
  ## Build and pack
115
121
 
116
122
  ```bash
117
- pnpm --filter @asharca/ui build
118
- pnpm --dir packages/ui pack
123
+ pnpm install --frozen-lockfile
124
+ pnpm lint
125
+ pnpm build
126
+ pnpm test
127
+ pnpm test:package
128
+ pnpm pack
119
129
  ```
120
130
 
131
+ Development uses Node 24 and pnpm. Tests run without ToolPlane, Next.js,
132
+ Postgres, or Docker. `test:package` installs the tarball into a temporary consumer
133
+ with strict peer checking and verifies imports, rendering, CSS, and Tailwind
134
+ source scanning.
135
+
121
136
  ## Release
122
137
 
123
- This package is versioned independently from the ToolPlane application, like
124
- `packages/ai` in the Pi monorepo. To release a new version, update
125
- `packages/ui/package.json`, merge it, and create a matching `ui-vX.Y.Z` tag.
126
- The `publish-ui.yml` workflow builds and publishes that exact version to npm.
138
+ This package is maintained in `asharca/ui`, independently from ToolPlane.
139
+ Changes go through a PR with required CI checks; merging to `main` does not
140
+ repeat the full CI run. CI can also be started manually.
141
+
142
+ To release, update `package.json` in a PR, merge it, and tag the merged commit
143
+ on `main`. Replace `X.Y.Z` with the package version:
144
+
145
+ ```bash
146
+ git tag ui-vX.Y.Z
147
+ git push origin ui-vX.Y.Z
148
+ ```
149
+
150
+ The `publish-ui.yml` workflow checks that the tag matches the package version
151
+ and belongs to `main`, builds and tests the tagged commit, verifies the tarball,
152
+ then publishes that exact version to npm with provenance. Published npm versions
153
+ are immutable; use a new version and tag for each release.
127
154
 
128
155
  Publishing requires access to the `@asharca` npm scope. Configure npm trusted
129
- publishing for `asharca/ToolPlane` and `publish-ui.yml`, allowing direct
156
+ publishing for `asharca/ui` and `publish-ui.yml`, allowing direct
130
157
  publishing with `npm publish`. The workflow uses OIDC rather than a long-lived
131
- npm token.
158
+ npm token. No `NPM_TOKEN` or `NODE_AUTH_TOKEN` repository secret is needed.
159
+
160
+ Version `0.2.0` is the first release from this repository. It requires
161
+ `@assistant-ui/react@0.15.18`; consumers upgrading from `0.1.x` must update that
162
+ runtime peer as well. Component exports and CSS variables are unchanged by the
163
+ repository migration. Consuming applications update their dependency and rebuild
164
+ to adopt a release.
132
165
 
133
166
  ## License
134
167
 
135
- MIT. See [LICENSE](./LICENSE). This license applies only to `packages/ui`, not
136
- to the rest of the ToolPlane repository.
168
+ MIT. See [LICENSE](./LICENSE). This repository preserves the history of the UI
169
+ package extracted from ToolPlane; it does not license the rest of ToolPlane.
@@ -11,8 +11,8 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- import { createContext, lazy, Suspense, useCallback, useContext, useMemo, useRef, useState, } from 'react';
15
- import { ActionBarPrimitive, AssistantRuntimeProvider, AttachmentPrimitive, ChainOfThoughtPrimitive, ComposerPrimitive, MessagePrimitive, ThreadPrimitive, useAuiState, useComposerRuntime, useMessagePartText, } from '@assistant-ui/react';
14
+ import { createContext, lazy, Suspense, useContext, useMemo, useRef, useState, } from 'react';
15
+ import { ActionBarPrimitive, AssistantRuntimeProvider, AttachmentPrimitive, ChainOfThoughtPrimitive, ComposerPrimitive, MessagePrimitive, ThreadPrimitive, useAuiState, useMessagePartText, } from '@assistant-ui/react';
16
16
  import { StreamdownTextPrimitive } from '@assistant-ui/react-streamdown';
17
17
  import { code } from '@streamdown/code';
18
18
  import { Popover } from 'radix-ui';
@@ -230,28 +230,7 @@ function ComposerAttachment({ attachment }) {
230
230
  }
231
231
  function AttachmentPicker({ disabled, enabled }) {
232
232
  const labels = useLabels();
233
- const composer = useComposerRuntime();
234
- const openPicker = useCallback(() => {
235
- const input = document.createElement('input');
236
- input.type = 'file';
237
- input.multiple = true;
238
- input.hidden = true;
239
- const accept = composer.getState().attachmentAccept;
240
- if (accept && accept !== '*')
241
- input.accept = accept;
242
- const removeInput = () => input.remove();
243
- input.onchange = () => {
244
- var _a;
245
- for (const file of Array.from((_a = input.files) !== null && _a !== void 0 ? _a : [])) {
246
- void composer.addAttachment(file).catch(() => undefined);
247
- }
248
- removeInput();
249
- };
250
- input.oncancel = removeInput;
251
- document.body.appendChild(input);
252
- input.click();
253
- }, [composer]);
254
- return (_jsxs(Popover.Root, { children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(IconButton, { icon: _jsx(Plus, { className: "size-[18px]" }), label: labels.openComposerTools, size: "sm", variant: "ghost", disabled: disabled, className: "size-[30px] min-h-[30px] shrink-0 rounded-full" }) }), _jsx(Popover.Portal, { children: _jsx(Popover.Content, { side: "top", align: "start", sideOffset: 8, collisionPadding: 12, "aria-label": labels.composerTools, className: "z-50 w-64 rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-xl", children: _jsx(Popover.Close, { asChild: true, children: _jsxs("button", { type: "button", disabled: !enabled, onClick: openPicker, className: "flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx(Paperclip, { className: "size-4 shrink-0" }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block", children: labels.addAttachment }), !enabled ? _jsx("span", { className: "mt-0.5 block text-[11px] text-muted-foreground", children: labels.attachmentsUnavailable }) : null] })] }) }) }) })] }));
233
+ return (_jsxs(Popover.Root, { children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(IconButton, { icon: _jsx(Plus, { className: "size-[18px]" }), label: labels.openComposerTools, size: "sm", variant: "ghost", disabled: disabled, className: "size-[30px] min-h-[30px] shrink-0 rounded-full" }) }), _jsx(Popover.Portal, { children: _jsx(Popover.Content, { side: "top", align: "start", sideOffset: 8, collisionPadding: 12, "aria-label": labels.composerTools, className: "z-50 w-64 rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-xl", children: _jsx(Popover.Close, { asChild: true, children: _jsxs(ComposerPrimitive.AddAttachment, { multiple: true, disabled: !enabled, className: "flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-sm transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx(Paperclip, { className: "size-4 shrink-0" }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block", children: labels.addAttachment }), !enabled ? _jsx("span", { className: "mt-0.5 block text-[11px] text-muted-foreground", children: labels.attachmentsUnavailable }) : null] })] }) }) }) })] }));
255
234
  }
256
235
  function BranchNavigator({ branch, disabled, onSelect, }) {
257
236
  const labels = useLabels();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asharca/ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Reusable ToolPlane components and chat UI for React applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,13 +16,13 @@
16
16
  ],
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/asharca/ToolPlane.git",
20
- "directory": "packages/ui"
19
+ "url": "git+https://github.com/asharca/ui.git"
21
20
  },
22
- "homepage": "https://github.com/asharca/ToolPlane/tree/main/packages/ui",
21
+ "homepage": "https://github.com/asharca/ui#readme",
23
22
  "bugs": {
24
- "url": "https://github.com/asharca/ToolPlane/issues"
23
+ "url": "https://github.com/asharca/ui/issues"
25
24
  },
25
+ "packageManager": "pnpm@10.32.1",
26
26
  "engines": {
27
27
  "node": ">=20"
28
28
  },
@@ -82,17 +82,26 @@
82
82
  },
83
83
  "./styles.css": "./src/styles.css"
84
84
  },
85
+ "scripts": {
86
+ "lint": "eslint src tests",
87
+ "test": "vitest run",
88
+ "test:watch": "vitest",
89
+ "test:package": "node scripts/check-package.mjs",
90
+ "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
91
+ "postbuild": "node --input-type=module -e \"import { readFileSync, writeFileSync } from 'node:fs'; const path = 'dist/index.d.ts'; writeFileSync(path, readFileSync(path, 'utf8').replaceAll('.tsx', '.js').replaceAll('.ts', '.js'))\"",
92
+ "prepack": "pnpm build"
93
+ },
85
94
  "publishConfig": {
86
95
  "access": "public"
87
96
  },
88
97
  "peerDependencies": {
89
- "@assistant-ui/react": "^0.14.26",
98
+ "@assistant-ui/react": "0.15.18",
90
99
  "react": "^19.0.0",
91
100
  "react-dom": "^19.0.0",
92
101
  "tailwindcss": "^4.0.0"
93
102
  },
94
103
  "dependencies": {
95
- "@assistant-ui/react-streamdown": "0.3.5",
104
+ "@assistant-ui/react-streamdown": "0.3.13",
96
105
  "@streamdown/code": "^1.1.1",
97
106
  "@streamdown/mermaid": "^1.0.2",
98
107
  "lucide-react": "^1.21.0",
@@ -100,8 +109,25 @@
100
109
  "remark-breaks": "^4.0.0",
101
110
  "streamdown": "^2.5.0"
102
111
  },
103
- "scripts": {
104
- "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
105
- "postbuild": "node --input-type=module -e \"import { readFileSync, writeFileSync } from 'node:fs'; const path = 'dist/index.d.ts'; writeFileSync(path, readFileSync(path, 'utf8').replaceAll('.tsx', '.js').replaceAll('.ts', '.js'))\""
112
+ "devDependencies": {
113
+ "@assistant-ui/react": "0.15.18",
114
+ "@tailwindcss/postcss": "^4",
115
+ "@testing-library/jest-dom": "6.9.1",
116
+ "@testing-library/react": "^16.3.2",
117
+ "@testing-library/user-event": "^14.6.1",
118
+ "@types/node": "^24",
119
+ "@types/react": "^19",
120
+ "@types/react-dom": "^19",
121
+ "@vitejs/plugin-react": "^6.0.3",
122
+ "eslint": "^10",
123
+ "eslint-plugin-react-hooks": "^7",
124
+ "jsdom": "^29.1.1",
125
+ "postcss": "^8",
126
+ "react": "19.2.4",
127
+ "react-dom": "19.2.4",
128
+ "tailwindcss": "^4",
129
+ "typescript": "^5",
130
+ "typescript-eslint": "^8",
131
+ "vitest": "^4.1.9"
106
132
  }
107
- }
133
+ }