@arbidocs/blocks 0.4.21 → 0.4.23
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/dist/agents/index.cjs +212 -212
- package/dist/agents/index.js +6 -6
- package/dist/chat/index.cjs +116 -115
- package/dist/chat/index.js +4 -3
- package/dist/chunk-5TRALRWN.js +42 -0
- package/dist/chunk-5TRALRWN.js.map +1 -0
- package/dist/{chunk-MLSRLLU7.cjs → chunk-6XQJTEBM.cjs} +6 -6
- package/dist/{chunk-MLSRLLU7.cjs.map → chunk-6XQJTEBM.cjs.map} +1 -1
- package/dist/chunk-7UTB4PHM.cjs +300 -0
- package/dist/chunk-7UTB4PHM.cjs.map +1 -0
- package/dist/chunk-AA3PT6KR.js +286 -0
- package/dist/chunk-AA3PT6KR.js.map +1 -0
- package/dist/{chunk-5LUI4G5R.js → chunk-BV7FEMSI.js} +3 -3
- package/dist/{chunk-5LUI4G5R.js.map → chunk-BV7FEMSI.js.map} +1 -1
- package/dist/{chunk-B6N5UXQX.js → chunk-CQ6CYPV4.js} +7 -281
- package/dist/chunk-CQ6CYPV4.js.map +1 -0
- package/dist/chunk-EUOGPUMJ.cjs +59 -0
- package/dist/chunk-EUOGPUMJ.cjs.map +1 -0
- package/dist/{chunk-BTDL4Q27.cjs → chunk-JCVZKCXC.cjs} +22 -69
- package/dist/chunk-JCVZKCXC.cjs.map +1 -0
- package/dist/chunk-NNH7N62N.cjs +876 -0
- package/dist/chunk-NNH7N62N.cjs.map +1 -0
- package/dist/{chunk-C7SMJ6GJ.js → chunk-PPZAAQZI.js} +6 -6
- package/dist/{chunk-C7SMJ6GJ.js.map → chunk-PPZAAQZI.js.map} +1 -1
- package/dist/{chunk-54WQYICJ.cjs → chunk-TL2DHSC5.cjs} +10 -296
- package/dist/chunk-TL2DHSC5.cjs.map +1 -0
- package/dist/chunk-UOLMFC5K.js +846 -0
- package/dist/chunk-UOLMFC5K.js.map +1 -0
- package/dist/{chunk-TO4FAMQP.cjs → chunk-XKSFJYOD.cjs} +3 -3
- package/dist/{chunk-TO4FAMQP.cjs.map → chunk-XKSFJYOD.cjs.map} +1 -1
- package/dist/{chunk-2T2ZMOA6.js → chunk-ZEIOREJY.js} +5 -36
- package/dist/chunk-ZEIOREJY.js.map +1 -0
- package/dist/connect/docx.cjs +86 -0
- package/dist/connect/docx.cjs.map +1 -0
- package/dist/connect/docx.d.ts +1 -0
- package/dist/connect/docx.js +84 -0
- package/dist/connect/docx.js.map +1 -0
- package/dist/connect/index.cjs +114 -47
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +89 -23
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedNativeDocxEditor.d.ts +5 -0
- package/dist/connection/useConnectedDocxNotifications.d.ts +9 -0
- package/dist/docx/DocxMentions.d.ts +17 -0
- package/dist/docx/NativeDocxComparison.d.ts +10 -0
- package/dist/docx/NativeDocxEditor.d.ts +50 -0
- package/dist/docx/export.d.ts +2 -0
- package/dist/docx/fonts.d.ts +2 -0
- package/dist/docx/index.cjs +116 -0
- package/dist/docx/index.cjs.map +1 -0
- package/dist/docx/index.d.ts +10 -0
- package/dist/docx/index.js +63 -0
- package/dist/docx/index.js.map +1 -0
- package/dist/docx/mentions.d.ts +8 -0
- package/dist/facts/index.cjs +2 -2
- package/dist/facts/index.js +2 -2
- package/dist/files/index.cjs +3 -3
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +1 -1
- package/dist/home/index.js +1 -1
- package/dist/index.cjs +923 -922
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +17 -16
- package/dist/index.js.map +1 -1
- package/dist/settings/index.cjs +35 -35
- package/dist/settings/index.js +4 -4
- package/dist/shell/index.cjs +26 -26
- package/dist/shell/index.js +4 -4
- package/dist/studio/index.cjs +5 -4
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.js +3 -2
- package/dist/studio/index.js.map +1 -1
- package/dist/workspaces/index.cjs +1 -1
- package/dist/workspaces/index.js +1 -1
- package/package.json +48 -7
- package/src/docx/README.md +68 -0
- package/src/docx/styles.css +36 -0
- package/dist/chunk-2T2ZMOA6.js.map +0 -1
- package/dist/chunk-54WQYICJ.cjs.map +0 -1
- package/dist/chunk-B6N5UXQX.js.map +0 -1
- package/dist/chunk-BTDL4Q27.cjs.map +0 -1
|
@@ -5,9 +5,9 @@ var chunkXZIYRKLW_cjs = require('../chunk-XZIYRKLW.cjs');
|
|
|
5
5
|
var chunkXAJIKT6Y_cjs = require('../chunk-XAJIKT6Y.cjs');
|
|
6
6
|
var chunkOB5F4577_cjs = require('../chunk-OB5F4577.cjs');
|
|
7
7
|
require('../chunk-C54XEN5T.cjs');
|
|
8
|
+
var chunkKDG6FER6_cjs = require('../chunk-KDG6FER6.cjs');
|
|
8
9
|
var chunk7G2LJMUG_cjs = require('../chunk-7G2LJMUG.cjs');
|
|
9
10
|
var chunk2ZTONLT5_cjs = require('../chunk-2ZTONLT5.cjs');
|
|
10
|
-
var chunkKDG6FER6_cjs = require('../chunk-KDG6FER6.cjs');
|
|
11
11
|
require('../chunk-DCDVWPMB.cjs');
|
|
12
12
|
var react = require('react');
|
|
13
13
|
var lucideReact = require('lucide-react');
|
package/dist/workspaces/index.js
CHANGED
|
@@ -3,9 +3,9 @@ import { CollapsibleSection, KeyValueRow } from '../chunk-LGBAZD37.js';
|
|
|
3
3
|
import { MemberAvatarStack } from '../chunk-XNOASBGW.js';
|
|
4
4
|
import { ActionLink } from '../chunk-S7PSMMRG.js';
|
|
5
5
|
import '../chunk-76JDDMSP.js';
|
|
6
|
+
import { fromNow, fmtDate } from '../chunk-OXF2IFXG.js';
|
|
6
7
|
export { RoleBadge, WorkspaceTypeBadgeView } from '../chunk-NBV56SGU.js';
|
|
7
8
|
import { ModalHeader } from '../chunk-CPMNAJLF.js';
|
|
8
|
-
import { fromNow, fmtDate } from '../chunk-OXF2IFXG.js';
|
|
9
9
|
import '../chunk-TJMKFY5P.js';
|
|
10
10
|
import { createContext, useContext, useMemo, useState, useCallback, useId } from 'react';
|
|
11
11
|
import { FileText, MessagesSquare, Users, Check, ChevronRight, UserPlus, LogOut, AlertCircle, Plus, ArrowUpRight, AlignLeft, Globe, CreditCard, Loader2, FolderLock } from 'lucide-react';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arbidocs/blocks",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.23",
|
|
4
4
|
"description": "Composable, domain-neutral UI blocks for ARBI apps, organised by capability (retrieval, facts, agents, workspaces, citations, collaboration) plus shell, theme and site primitives, on top of @arbidocs/react.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -112,6 +112,17 @@
|
|
|
112
112
|
"types": "./dist/artifacts/editor/index.d.ts",
|
|
113
113
|
"import": "./dist/artifacts/editor/index.js",
|
|
114
114
|
"require": "./dist/artifacts/editor/index.cjs"
|
|
115
|
+
},
|
|
116
|
+
"./docx": {
|
|
117
|
+
"types": "./dist/docx/index.d.ts",
|
|
118
|
+
"import": "./dist/docx/index.js",
|
|
119
|
+
"require": "./dist/docx/index.cjs"
|
|
120
|
+
},
|
|
121
|
+
"./docx.css": "./src/docx/styles.css",
|
|
122
|
+
"./connect/docx": {
|
|
123
|
+
"types": "./dist/connect/docx.d.ts",
|
|
124
|
+
"import": "./dist/connect/docx.js",
|
|
125
|
+
"require": "./dist/connect/docx.cjs"
|
|
115
126
|
}
|
|
116
127
|
},
|
|
117
128
|
"typesVersions": {
|
|
@@ -172,6 +183,12 @@
|
|
|
172
183
|
],
|
|
173
184
|
"artifacts/editor": [
|
|
174
185
|
"./dist/artifacts/editor/index.d.ts"
|
|
186
|
+
],
|
|
187
|
+
"docx": [
|
|
188
|
+
"./dist/docx/index.d.ts"
|
|
189
|
+
],
|
|
190
|
+
"connect/docx": [
|
|
191
|
+
"./dist/connect/docx.d.ts"
|
|
175
192
|
]
|
|
176
193
|
}
|
|
177
194
|
},
|
|
@@ -181,7 +198,9 @@
|
|
|
181
198
|
"src/blocks.css",
|
|
182
199
|
"src/studio/studio.css",
|
|
183
200
|
"src/components/grid.css",
|
|
184
|
-
"src/source.css"
|
|
201
|
+
"src/source.css",
|
|
202
|
+
"src/docx/styles.css",
|
|
203
|
+
"src/docx/README.md"
|
|
185
204
|
],
|
|
186
205
|
"scripts": {
|
|
187
206
|
"build": "rm -rf dist && tsup && tsc -p tsconfig.build.json",
|
|
@@ -194,7 +213,7 @@
|
|
|
194
213
|
"example:test:e2e": "playwright test -c examples/custom-ui/playwright.config.ts"
|
|
195
214
|
},
|
|
196
215
|
"dependencies": {
|
|
197
|
-
"@arbidocs/client": "0.4.
|
|
216
|
+
"@arbidocs/client": "0.4.23",
|
|
198
217
|
"@dnd-kit/core": "^6.3.1",
|
|
199
218
|
"@dnd-kit/sortable": "^10.0.0",
|
|
200
219
|
"@dnd-kit/utilities": "^3.2.2",
|
|
@@ -206,17 +225,23 @@
|
|
|
206
225
|
"cmdk": "^1.1.1",
|
|
207
226
|
"dompurify": "^3.4.7",
|
|
208
227
|
"lucide-react": "^1.22.0",
|
|
209
|
-
"zustand": "^5.0.14"
|
|
228
|
+
"zustand": "^5.0.14",
|
|
229
|
+
"fflate": "^0.8.2",
|
|
230
|
+
"@hocuspocus/provider": "4.6.0"
|
|
210
231
|
},
|
|
211
232
|
"peerDependencies": {
|
|
212
|
-
"@arbidocs/react": "0.4.
|
|
233
|
+
"@arbidocs/react": "0.4.23",
|
|
213
234
|
"@mdxeditor/editor": "^4.0.4",
|
|
214
235
|
"@measured/puck": ">=0.20",
|
|
215
236
|
"@playwright/test": ">=1.40",
|
|
216
237
|
"@tanstack/react-query": ">=5",
|
|
217
238
|
"react": ">=18",
|
|
218
239
|
"react-dom": ">=18",
|
|
219
|
-
"react-router-dom": ">=6"
|
|
240
|
+
"react-router-dom": ">=6",
|
|
241
|
+
"@docx-editor.dev/core": "2.27.0",
|
|
242
|
+
"@docx-editor.dev/react": "2.27.0",
|
|
243
|
+
"@docx-editor.dev/pro": "2.27.0",
|
|
244
|
+
"yjs": "^13.6.32"
|
|
220
245
|
},
|
|
221
246
|
"peerDependenciesMeta": {
|
|
222
247
|
"@mdxeditor/editor": {
|
|
@@ -233,6 +258,18 @@
|
|
|
233
258
|
},
|
|
234
259
|
"react-router-dom": {
|
|
235
260
|
"optional": true
|
|
261
|
+
},
|
|
262
|
+
"@docx-editor.dev/core": {
|
|
263
|
+
"optional": true
|
|
264
|
+
},
|
|
265
|
+
"@docx-editor.dev/react": {
|
|
266
|
+
"optional": true
|
|
267
|
+
},
|
|
268
|
+
"@docx-editor.dev/pro": {
|
|
269
|
+
"optional": true
|
|
270
|
+
},
|
|
271
|
+
"yjs": {
|
|
272
|
+
"optional": true
|
|
236
273
|
}
|
|
237
274
|
},
|
|
238
275
|
"devDependencies": {
|
|
@@ -248,7 +285,11 @@
|
|
|
248
285
|
"react": "^19.2.7",
|
|
249
286
|
"react-dom": "^19.2.7",
|
|
250
287
|
"react-router-dom": "^6.30.1",
|
|
251
|
-
"vitest": "^4.0.18"
|
|
288
|
+
"vitest": "^4.0.18",
|
|
289
|
+
"@docx-editor.dev/core": "2.27.0",
|
|
290
|
+
"@docx-editor.dev/react": "2.27.0",
|
|
291
|
+
"@docx-editor.dev/pro": "2.27.0",
|
|
292
|
+
"yjs": "^13.6.32"
|
|
252
293
|
},
|
|
253
294
|
"license": "MIT",
|
|
254
295
|
"publishConfig": {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Native DOCX building blocks
|
|
2
|
+
|
|
3
|
+
Import from `@arbidocs/blocks/docx`. This optional entry is separate from the root
|
|
4
|
+
package so apps that do not edit Word files do not load the DOCX engine.
|
|
5
|
+
Install the three `@docx-editor.dev` peer packages at 2.27.0 and `yjs`. The blocks package supplies the Hocuspocus provider.
|
|
6
|
+
The Pro package requires an appropriate production licence.
|
|
7
|
+
|
|
8
|
+
```tsx
|
|
9
|
+
import {
|
|
10
|
+
NativeDocxEditor, loadDocxFonts, type NativeDocxAdapter,
|
|
11
|
+
} from '@arbidocs/blocks/docx'
|
|
12
|
+
import '@docx-editor.dev/react/styles.css'
|
|
13
|
+
import '@arbidocs/blocks/docx.css'
|
|
14
|
+
|
|
15
|
+
// Keep this adapter stable for the mounted document. Supply your authenticated
|
|
16
|
+
// fetch implementation; `request` paths are relative to ARBI's /v1/editor.
|
|
17
|
+
const adapter: NativeDocxAdapter = {
|
|
18
|
+
request: authenticatedEditorRequest,
|
|
19
|
+
open: id => authenticatedEditorRequest(`/${id}/session`, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
}).then(r => r.json()),
|
|
22
|
+
save: (id, state) => authenticatedEditorRequest(`/${id}/save`, {
|
|
23
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
24
|
+
body: JSON.stringify({ state }),
|
|
25
|
+
}).then(r => r.json()),
|
|
26
|
+
loadFonts: () => loadDocxFonts('/native-docx/fonts'),
|
|
27
|
+
baseUrl: apiOrigin,
|
|
28
|
+
author: currentUserName,
|
|
29
|
+
onDirtyChange: setNavigationGuard,
|
|
30
|
+
onVersionSaved: refreshDocumentCache,
|
|
31
|
+
subscribeTokenChanges: subscribeToSessionRenewal,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
<NativeDocxEditor documentId={documentId} title="Contract.docx"
|
|
35
|
+
adapter={adapter} onSaved={openSavedVersion} />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The complete widget handles Yjs/Hocuspocus collaboration, encrypted server
|
|
39
|
+
recovery acknowledgements, reconnects, tracked changes, comments, review actions,
|
|
40
|
+
immutable Save version, DOCX download, read-only snapshots, and new Word notes.
|
|
41
|
+
Use `snapshot` for immutable history/compare documents. Supply `draftContent`
|
|
42
|
+
for a new note; `/prepare` converts its initial content and `/notes` saves DOCX.
|
|
43
|
+
|
|
44
|
+
Fonts are supplied by the host: either provide your own `FontConfiguration`, or
|
|
45
|
+
serve the twelve Liberation TTF files used by `loadDocxFonts`. The ARBI app serves
|
|
46
|
+
these at `/native-docx/fonts`; this library does not assume a consumer's asset
|
|
47
|
+
server or copy assets automatically.
|
|
48
|
+
|
|
49
|
+
For custom layouts, the same entry exports `DocxRibbon`, `DocxParticipants`,
|
|
50
|
+
`DocxEditor` compound primitives, `DocxEditorReview`, editor/review hooks and
|
|
51
|
+
`createHocuspocusCollaboration`. Mount the ribbon within `DocxEditor.Root` and the
|
|
52
|
+
review UI inside `DocxEditor.Viewport`. There are no imports from the ARBI app,
|
|
53
|
+
Zustand stores, app routing, notification singletons, or app query keys.
|
|
54
|
+
|
|
55
|
+
Backend services are still required: ARBI native editor endpoints, one
|
|
56
|
+
Hocuspocus room owner and object storage; LibreOffice provides document compare.
|
|
57
|
+
Workspace people and agents are available through the adapter's `mentions` and
|
|
58
|
+
`requestAgent` callbacks. `@ARBI` wakes the managed assistant; replies remain in
|
|
59
|
+
the originating comment thread. `ConnectedNativeDocxEditor` from `@arbidocs/blocks/connect/docx` supplies these
|
|
60
|
+
callbacks using the blocks connection and authenticated SDK, including normal
|
|
61
|
+
session recovery. Import the same two stylesheets and serve the document fonts.
|
|
62
|
+
For a prompt panel, pass `activeArtifactExtId: documentId` to
|
|
63
|
+
`useConnectedAiTask().run(prompt, [], options)`; the backend edits the live DOCX
|
|
64
|
+
with tracked operations and refuses stale targets.
|
|
65
|
+
|
|
66
|
+
`NativeDocxComparison` uses the same adapter and native editor for the LibreOffice
|
|
67
|
+
Word redline. Pass `baseId`, `revisedId`, `title` and optionally `onCompared` to
|
|
68
|
+
refresh only the generated document in your host cache. Source files stay intact.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.native-docx-viewer{position:relative;height:100%;min-height:0;display:flex;flex-direction:column;background:var(--background);color:var(--foreground);font:inherit}
|
|
2
|
+
.native-docx-body{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}
|
|
3
|
+
.native-docx-body .docx-toolbar{flex:none;width:100%;margin:0;border-radius:0;border-width:0 0 1px;padding:4px 8px;background:var(--background);box-shadow:none}
|
|
4
|
+
.native-docx-stage{position:relative;flex:1;min-height:0;overflow:hidden}
|
|
5
|
+
.native-docx-viewport{height:100%;padding-top:8px;padding-bottom:64px;background:var(--muted)}
|
|
6
|
+
.native-docx-body .docx-paginated-surface{margin-top:0;margin-bottom:0}
|
|
7
|
+
.native-docx-actions{position:absolute;z-index:30;right:12px;bottom:12px;left:12px;display:flex;align-items:center;gap:8px;pointer-events:none;font-size:11px}
|
|
8
|
+
.native-docx-actions>*{pointer-events:auto;flex-shrink:0}
|
|
9
|
+
.native-docx-actions .native-docx-status{margin-right:auto;display:flex;align-items:center;gap:5px;max-width:45%;padding:6px 8px;border:1px solid var(--border);border-radius:8px;background:var(--background);color:var(--muted-foreground);box-shadow:0 2px 8px #0000000a}
|
|
10
|
+
.native-docx-actions button{display:inline-flex;align-items:center;gap:5px;padding:6px 8px;border:1px solid var(--border);border-radius:8px;background:var(--background);cursor:pointer;font:inherit;box-shadow:0 2px 8px #0000000a}
|
|
11
|
+
.native-docx-actions button:hover{background:var(--muted)}.native-docx-actions button:disabled{opacity:.5;cursor:default}.native-docx-actions button:focus-visible{outline:2px solid var(--ring);outline-offset:2px}
|
|
12
|
+
.native-docx-actions .native-docx-save{background:#285c4b;color:white;border-color:#285c4b}
|
|
13
|
+
.native-docx-presence{display:flex;gap:4px}.native-docx-avatar{display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:#d7e9e0;color:#285c4b;font-size:10px}
|
|
14
|
+
.native-docx-error{padding:24px;display:grid;gap:12px;color:var(--foreground)}
|
|
15
|
+
.native-docx-notice{position:absolute;z-index:40;top:48px;left:12px;right:12px;padding:8px 12px;font-size:11px;border-radius:8px;background:#fff6e5;color:#76572f;box-shadow:0 2px 10px #00000014}.native-docx-notice[data-error=true]{background:#fff0ef;color:#a23832}
|
|
16
|
+
.native-docx-body .docx-review__card{font-family:inherit}
|
|
17
|
+
@media(max-width:600px){.native-docx-actions{right:8px;left:8px;gap:5px}.native-docx-actions .native-docx-status{font-size:10px;padding:5px;max-width:40%}.native-docx-actions button{padding:6px}.native-docx-presence{display:none}}
|
|
18
|
+
|
|
19
|
+
/* Review controls overlay the page, matching the other ARBI viewers. */
|
|
20
|
+
.native-docx-body .native-docx-viewport[data-review-pane]{padding-inline:8px;scrollbar-gutter:stable;transition:none}
|
|
21
|
+
.native-docx-viewport .docx-review{left:auto!important;right:8px!important}
|
|
22
|
+
.native-docx-stage .docx-editor__page-number{top:auto;bottom:56px;right:12px;transform:none}
|
|
23
|
+
|
|
24
|
+
.native-docx-ribbon{display:flex;align-items:center;flex:none;min-width:0;border-bottom:1px solid var(--border);background:var(--background)}
|
|
25
|
+
.native-docx-ribbon>select{flex:none;width:76px;margin:4px;padding:6px 4px;border:0;border-radius:4px;background:var(--muted);color:var(--foreground);font:inherit;font-size:12px;cursor:pointer}
|
|
26
|
+
.native-docx-body .native-docx-ribbon .docx-toolbar{min-width:0;flex:1;width:auto;border:0;overflow:visible;flex-wrap:nowrap}
|
|
27
|
+
.native-docx-ribbon .docx-toolbar>*{flex-shrink:0}
|
|
28
|
+
|
|
29
|
+
.native-docx-ribbon{position:relative;z-index:35}
|
|
30
|
+
.native-docx-ribbon>select{width:64px;margin-inline:2px}
|
|
31
|
+
.native-docx-ribbon .docx-toolbar{gap:2px}
|
|
32
|
+
.native-docx-ribbon-menu{position:static;display:flex;align-items:center}
|
|
33
|
+
.native-docx-ribbon-trigger{display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer}
|
|
34
|
+
.native-docx-ribbon-trigger:hover,.native-docx-ribbon-trigger[aria-expanded=true]{background:var(--muted)}
|
|
35
|
+
.native-docx-ribbon-popover{position:absolute;top:100%;right:8px;display:flex;align-items:center;flex-wrap:wrap;gap:8px;width:270px;max-width:calc(100% - 16px);padding:12px;border:1px solid var(--border);border-radius:8px;background:var(--background);box-shadow:0 4px 16px #0002}
|
|
36
|
+
.native-docx-ribbon .docx-toolbar__button{width:28px;min-width:28px;padding-inline:4px}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/ConnectionProvider.tsx","../src/connection/ai.tsx"],"names":["useKitAiTask","useCallback","useKitWorkspaceDocs","useKitSemanticSearch","jsx"],"mappings":"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","file":"chunk-2T2ZMOA6.js","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport { useArbi, type LoginProfile } from '@arbidocs/react'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /** Fallback workspace ext_id when none is actively selected. */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>('disconnected')\n const [user, setUser] = useState<ArbiUser | null>(null)\n const [workspaceId, setWorkspaceId] = useState<string | null>(null)\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n storageUserRef.current = null\n setUser(null)\n setWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n setWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId])\n\n const login = useCallback(\n async (email: string, password: string) => {\n setError(null)\n // No backend configured → run the seeded demo workspace.\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n await arbi.login(email, password)\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n workspaces[0]\n await arbi.selectWorkspace(target.external_id)\n setWorkspaceId(target.external_id)\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n setUser(resolved)\n setStatus('authenticated')\n } catch (e) {\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured, config.workspaceId, config.apiUrl]\n )\n\n const logout = useCallback(() => {\n if (mode === 'live') {\n void arbi.logout?.()\n }\n setUser(null)\n setWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n }, [arbi, mode, config.apiUrl])\n\n // Affirmative selection: open the workspace on the server (live), then remember\n // it in state + storage so every surface — and the next login — is in sync.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n await arbi.selectWorkspace(id)\n }\n setWorkspaceId(id)\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped\n // it. Idempotent: re-running `/open` for the already-selected workspace is safe.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n const id =\n workspaceId ??\n readPersistedWorkspace(config.apiUrl, storageUserRef.current) ??\n config.workspaceId\n if (id) await arbi.selectWorkspace(id)\n }, [arbi, mode, workspaceId, config.apiUrl, config.workspaceId])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n return <ConnectionContext.Provider value={value}>{children}</ConnectionContext.Provider>\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection must be used within ConnectionProvider')\n return ctx\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n","/**\n * The connected agent hooks — thin adapters over the reusable AI kit in\n * `@arbidocs/react`. The streaming/accumulation/search plumbing lives once in\n * the SDK; these hooks only bind the *workspace source* (from the connection\n * context, falling back to the configured workspace) and inject the host's\n * default assistant *configuration* so call sites needn't know the config\n * ext_id. An explicit `opts.model` still wins.\n */\nimport { useCallback } from 'react'\nimport {\n useAiTask as useKitAiTask,\n useWorkspaceDocs as useKitWorkspaceDocs,\n useSemanticSearch as useKitSemanticSearch,\n useArbiChat,\n type ArbiChat,\n type UseArbiChatOptions,\n type AiRunOptions,\n} from '@arbidocs/react'\nimport { useConnection } from './ConnectionProvider'\nimport { AssistantDock, type AssistantDockProps } from '../chat/AssistantDock'\n\nexport type { AiTaskStatus, AiRunOptions, SearchChunk, ArtifactEvent } from '@arbidocs/react'\n\n/** Client-side redlining, re-exported so a host app has one import surface. */\nexport { toRedlineMarkdown, redlineStats, textToArtifact } from '@arbidocs/react'\n\n/**\n * The kit's `useAiTask` with the host's default assistant configuration\n * injected, so call sites needn't know the config ext_id.\n */\nexport function useConnectedAiTask() {\n const { assistantConfig } = useConnection()\n const task = useKitAiTask()\n const kitRun = task.run\n const run = useCallback(\n (question: string, docIds: string[], opts?: AiRunOptions) =>\n kitRun(question, docIds, { ...opts, model: opts?.model ?? assistantConfig }),\n [kitRun, assistantConfig]\n )\n return { ...task, run }\n}\n\n/** Resolve the active workspace + its document ids (what we ground the agent on). */\nexport function useWorkspaceDocs() {\n const { workspaceId, fallbackWorkspaceId } = useConnection()\n return useKitWorkspaceDocs(workspaceId ?? fallbackWorkspaceId)\n}\n\n/** Search the active workspace's documents and return the top matching passages. */\nexport function useSemanticSearch() {\n const { docIds } = useWorkspaceDocs()\n return useKitSemanticSearch(docIds)\n}\n\n/**\n * The chat controller for `ChatPage` bound to the connection: the active workspace and the host's\n * default assistant configuration are injected, so a host writes\n * `<ChatPage chat={useConnectedChat()} />`.\n */\nexport function useConnectedChat(options?: Omit<UseArbiChatOptions, 'workspaceId'>): ArbiChat {\n const { workspaceId, fallbackWorkspaceId, assistantConfig } = useConnection()\n return useArbiChat({\n ...options,\n workspaceId: workspaceId ?? fallbackWorkspaceId,\n model: options?.model ?? assistantConfig,\n })\n}\n\n/**\n * The assistant dock bound to the connection: mount it once in the layout (`Shell.Root`'s `aside`)\n * and put `AssistantDockToggle` in the topbar. Chat state lives here, so it survives closing the dock.\n */\nexport function ConnectedAssistantDock(props: Omit<AssistantDockProps, 'chat'>) {\n const chat = useConnectedChat()\n return <AssistantDock {...props} chat={chat} />\n}\n"]}
|