@peers-app/peers-ui 0.18.6 → 0.19.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 ADDED
@@ -0,0 +1,83 @@
1
+ # @peers-app/peers-ui
2
+
3
+ React components and hooks for building [Peers](https://peers.app) package UIs.
4
+
5
+ ## What is Peers?
6
+
7
+ Peers is a local-first personal computing platform. Your data lives on your devices, syncs peer-to-peer, and is end-to-end encrypted — no servers in the middle. You own your data and your identity. Build apps with the SDK or use AI coding tools to create them; either way, the platform handles sync, encryption, and persistence automatically.
8
+
9
+ ## What this package provides
10
+
11
+ ### React Hooks
12
+
13
+ Hooks that bridge `@peers-app/peers-sdk` observables to React 18 with concurrent rendering support.
14
+
15
+ | Hook | Purpose |
16
+ |------|---------|
17
+ | `useObservable` | Subscribe to an observable or computed; returns `[value, setter]` |
18
+ | `useObservableState` | Create a component-local observable that persists across renders |
19
+ | `usePromise` | Resolve a promise in a component with an optional initial value |
20
+ | `useSubscription` | Run a side-effect whenever an observable changes |
21
+ | `useOnScreen` | IntersectionObserver hook for visibility detection |
22
+
23
+ ### Rich Text
24
+
25
+ - **`MarkdownEditor`** — Lexical-based rich text editor with @mention support, toolbar, and markdown serialization
26
+ - **`MarkdownWithMentions`** — Render markdown with resolved @user and $tool mentions
27
+
28
+ ### Layout
29
+
30
+ - **`TabsLayout`** — Multi-tab application shell used by the Peers desktop and PWA clients
31
+ - **`SortableList`** — Drag-and-drop list powered by SortableJS
32
+ - **`InverseLazyList`** — Bottom-anchored lazy-loading list for chat-style UIs
33
+ - **`Tabs`** / **`ScreenTabBody`** — Tab strip and content container
34
+
35
+ ### Communication
36
+
37
+ - **`ChatOverlay`** — Floating chat panel for AI assistant conversations
38
+ - **`VoiceIndicator`** — Visual indicator for active voice sessions
39
+
40
+ ### Tab Management
41
+
42
+ | Export | Purpose |
43
+ |--------|---------|
44
+ | `goToTabPath` | Navigate to a path within the Peers tab system |
45
+ | `activeTabId` | Observable of the currently active tab ID |
46
+ | `activeTabs` | Observable of all open tabs |
47
+ | `closeCurrentTab` | Close the active tab |
48
+ | `updateActiveTabTitle` | Set the title of the active tab |
49
+ | `TabState` | Tab state management class |
50
+ | `mainContentPath` | Hash-synced route observable |
51
+
52
+ ## Peer Dependencies
53
+
54
+ ```json
55
+ {
56
+ "@peers-app/peers-sdk": "^0.18.8",
57
+ "bootstrap": "^5.3.3",
58
+ "react": "^18.0.0",
59
+ "react-dom": "^18.0.0"
60
+ }
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ```bash
66
+ npm install @peers-app/peers-ui
67
+ ```
68
+
69
+ The fastest way to build a Peers package with a UI is to start from the template:
70
+
71
+ **[peers-package-template](https://github.com/peers-app/peers-package-template)** — scaffold, build, and install a custom package into the Peers runtime.
72
+
73
+ Package UI bundles receive `PeersUI` as a webpack external, so you can import hooks and components without bundling them into your package.
74
+
75
+ ## Links
76
+
77
+ - [peers.app](https://peers.app) — try Peers in your browser or download the desktop app
78
+ - [Documentation](https://peers-app.github.io) — architecture, package development, and API reference
79
+ - [GitHub](https://github.com/peers-app) — source repositories and package template
80
+
81
+ ## License
82
+
83
+ MIT
@@ -111,9 +111,7 @@ function GroupList() {
111
111
  });
112
112
  await (0, peers_sdk_1.Groups)(groupDataContext).signAndSave(group);
113
113
  // Auto-install peers-core for the new group
114
- await peers_sdk_1.rpcServerCalls
115
- .addOrUpdatePackage(peers_sdk_1.peersCorePackageId, { dataContextId: groupId })
116
- .catch((err) => {
114
+ await peers_sdk_1.rpcServerCalls.seedBundledPeersCore(groupId).catch((err) => {
117
115
  console.error("Error auto-installing peers-core for group:", err);
118
116
  });
119
117
  (0, globals_1.mainContentPath)(`groups/${group.groupId}`);
@@ -125,7 +125,23 @@ const PackageVersionsList = (props) => {
125
125
  signature: "",
126
126
  });
127
127
  const pvHash = (0, peers_sdk_1.computePackageVersionHash)(pv.version, newTag, pv.packageBundleFileHash, pv.routesBundleFileHash, pv.uiBundleFileHash);
128
- const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash, history };
128
+ const updated = {
129
+ ...pv,
130
+ versionTag: newTag,
131
+ packageVersionHash: pvHash,
132
+ history,
133
+ };
134
+ // Auto-sign with package author key if available (server-side, key never exposed)
135
+ const authorSig = await peers_sdk_1.rpcServerCalls.signPackageAuthorVersion({
136
+ packageId: updated.packageId,
137
+ packageVersionId: updated.packageVersionId,
138
+ version: updated.version,
139
+ versionTag: newTag,
140
+ packageBundleFileHash: updated.packageBundleFileHash,
141
+ routesBundleFileHash: updated.routesBundleFileHash,
142
+ uiBundleFileHash: updated.uiBundleFileHash,
143
+ });
144
+ updated.packageAuthorSignature = authorSig;
129
145
  await (0, peers_sdk_1.PackageVersions)().signAndSave(updated, { saveAsSnapshot: true });
130
146
  refreshKey(refreshKey() + 1);
131
147
  }
@@ -91,5 +91,6 @@ exports.systemPackage = {
91
91
  appNavs: exports.systemApps,
92
92
  createdBy: "system",
93
93
  disabled: false,
94
+ publishPublicKey: "",
94
95
  signature: "",
95
96
  };
@@ -5,6 +5,7 @@ export declare const allPackages: import("@peers-app/peers-sdk").Observable<{
5
5
  signature: string;
6
6
  packageId: string;
7
7
  createdBy: string;
8
+ publishPublicKey: string;
8
9
  disabled?: boolean | undefined;
9
10
  appNavs?: {
10
11
  name: string;
@@ -16,5 +17,6 @@ export declare const allPackages: import("@peers-app/peers-sdk").Observable<{
16
17
  activePackageVersionId?: string | undefined;
17
18
  versionFollowRange?: "pinned" | "patch" | "minor" | "latest" | undefined;
18
19
  followVersionTags?: string | undefined;
20
+ updateUrl?: string | undefined;
19
21
  }[]>;
20
22
  export declare const loadAllRoutes: () => Promise<true | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-ui",
3
- "version": "0.18.6",
3
+ "version": "0.19.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-ui.git"
@@ -28,7 +28,7 @@
28
28
  "lint:fix": "biome check --write ."
29
29
  },
30
30
  "peerDependencies": {
31
- "@peers-app/peers-sdk": "^0.18.6",
31
+ "@peers-app/peers-sdk": "^0.19.0",
32
32
  "bootstrap": "^5.3.3",
33
33
  "react": "^18.0.0",
34
34
  "react-dom": "^18.0.0"
@@ -39,7 +39,7 @@
39
39
  "@babel/preset-env": "^7.24.5",
40
40
  "@babel/preset-react": "^7.24.1",
41
41
  "@babel/preset-typescript": "^7.27.1",
42
- "@peers-app/peers-sdk": "0.18.6",
42
+ "@peers-app/peers-sdk": "0.19.0",
43
43
  "@testing-library/dom": "^10.4.0",
44
44
  "@testing-library/jest-dom": "^6.6.3",
45
45
  "@testing-library/react": "^16.3.0",
@@ -7,7 +7,6 @@ import {
7
7
  newid,
8
8
  newKeys,
9
9
  observable,
10
- peersCorePackageId,
11
10
  rpcServerCalls,
12
11
  setUserTrustLevel,
13
12
  TrustLevel,
@@ -132,11 +131,9 @@ export function GroupList() {
132
131
  await Groups(groupDataContext).signAndSave(group);
133
132
 
134
133
  // Auto-install peers-core for the new group
135
- await rpcServerCalls
136
- .addOrUpdatePackage(peersCorePackageId, { dataContextId: groupId })
137
- .catch((err: unknown) => {
138
- console.error("Error auto-installing peers-core for group:", err);
139
- });
134
+ await rpcServerCalls.seedBundledPeersCore(groupId).catch((err: unknown) => {
135
+ console.error("Error auto-installing peers-core for group:", err);
136
+ });
140
137
 
141
138
  mainContentPath(`groups/${group.groupId}`);
142
139
  return group;
@@ -8,6 +8,7 @@ import {
8
8
  Packages,
9
9
  PackageVersions,
10
10
  packagePrefsVar,
11
+ rpcServerCalls,
11
12
  Users,
12
13
  updatePackagePrefs,
13
14
  } from "@peers-app/peers-sdk";
@@ -136,7 +137,25 @@ export const PackageVersionsList = (props: { pkg: IDoc<IPackage> }) => {
136
137
  pv.routesBundleFileHash,
137
138
  pv.uiBundleFileHash,
138
139
  );
139
- const updated = { ...pv, versionTag: newTag, packageVersionHash: pvHash, history };
140
+ const updated: IPackageVersion = {
141
+ ...pv,
142
+ versionTag: newTag,
143
+ packageVersionHash: pvHash,
144
+ history,
145
+ };
146
+
147
+ // Auto-sign with package author key if available (server-side, key never exposed)
148
+ const authorSig = await rpcServerCalls.signPackageAuthorVersion({
149
+ packageId: updated.packageId,
150
+ packageVersionId: updated.packageVersionId,
151
+ version: updated.version,
152
+ versionTag: newTag,
153
+ packageBundleFileHash: updated.packageBundleFileHash,
154
+ routesBundleFileHash: updated.routesBundleFileHash,
155
+ uiBundleFileHash: updated.uiBundleFileHash,
156
+ });
157
+ updated.packageAuthorSignature = authorSig;
158
+
140
159
  await PackageVersions().signAndSave(updated, { saveAsSnapshot: true });
141
160
  refreshKey(refreshKey() + 1);
142
161
  } catch (err: unknown) {
@@ -80,5 +80,6 @@ export const systemPackage: IPackage = {
80
80
  appNavs: systemApps,
81
81
  createdBy: "system",
82
82
  disabled: false,
83
+ publishPublicKey: "",
83
84
  signature: "",
84
85
  };