@arbidocs/blocks 0.4.69 → 0.4.71
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 +161 -1
- package/bin/arbidocs-copy-pdf-assets.mjs +112 -0
- package/dist/{StreamedArtifactEditor-OPL4KXOT.js → StreamedArtifactEditor-HTNPG4NB.js} +3 -2
- package/dist/StreamedArtifactEditor-HTNPG4NB.js.map +1 -0
- package/dist/{StreamedArtifactEditor-RIKG6CJQ.cjs → StreamedArtifactEditor-IZWYNFMM.cjs} +3 -2
- package/dist/StreamedArtifactEditor-IZWYNFMM.cjs.map +1 -0
- package/dist/agents/index.cjs +221 -220
- package/dist/agents/index.js +5 -4
- package/dist/artifacts/editor/index.cjs +1 -0
- package/dist/artifacts/editor/index.js +1 -0
- package/dist/artifacts/index.cjs +1 -0
- package/dist/artifacts/index.js +1 -0
- package/dist/auth/index.cjs +1 -0
- package/dist/auth/index.js +1 -0
- package/dist/chat/index.cjs +67 -66
- package/dist/chat/index.js +3 -2
- package/dist/{chunk-CW4WXGEN.js → chunk-3TVTG7FK.js} +3 -3
- package/dist/{chunk-CW4WXGEN.js.map → chunk-3TVTG7FK.js.map} +1 -1
- package/dist/chunk-4DVEGXZQ.cjs +72 -0
- package/dist/chunk-4DVEGXZQ.cjs.map +1 -0
- package/dist/{chunk-EHXSBH6U.js → chunk-5HOAOKZL.js} +4 -2
- package/dist/chunk-5HOAOKZL.js.map +1 -0
- package/dist/{chunk-ZYZMCNIS.cjs → chunk-7M22KND4.cjs} +5 -5
- package/dist/{chunk-ZYZMCNIS.cjs.map → chunk-7M22KND4.cjs.map} +1 -1
- package/dist/{chunk-ZQB7HNE6.js → chunk-BMWZTNZB.js} +3 -3
- package/dist/{chunk-ZQB7HNE6.js.map → chunk-BMWZTNZB.js.map} +1 -1
- package/dist/chunk-DES3K4SD.cjs +18 -0
- package/dist/chunk-DES3K4SD.cjs.map +1 -0
- package/dist/{chunk-4HZ46XP2.js → chunk-HLMFU7L2.js} +5 -5
- package/dist/{chunk-4HZ46XP2.js.map → chunk-HLMFU7L2.js.map} +1 -1
- package/dist/{chunk-BR2CPKFU.cjs → chunk-LTA2IAQB.cjs} +6 -6
- package/dist/{chunk-BR2CPKFU.cjs.map → chunk-LTA2IAQB.cjs.map} +1 -1
- package/dist/chunk-ODWCTAH7.js +66 -0
- package/dist/chunk-ODWCTAH7.js.map +1 -0
- package/dist/{chunk-TLQQV7WW.cjs → chunk-THO7DZNN.cjs} +4 -2
- package/dist/chunk-THO7DZNN.cjs.map +1 -0
- package/dist/chunk-VUNV25KB.js +15 -0
- package/dist/chunk-VUNV25KB.js.map +1 -0
- package/dist/{chunk-WKNAFILY.cjs → chunk-XNRGCQPZ.cjs} +3 -3
- package/dist/{chunk-WKNAFILY.cjs.map → chunk-XNRGCQPZ.cjs.map} +1 -1
- package/dist/citations/index.cjs +1 -0
- package/dist/citations/index.js +1 -0
- package/dist/collaboration/index.cjs +1 -0
- package/dist/collaboration/index.js +1 -0
- package/dist/connect/docx.cjs +3 -2
- package/dist/connect/docx.cjs.map +1 -1
- package/dist/connect/docx.js +2 -1
- package/dist/connect/docx.js.map +1 -1
- package/dist/connect/index.cjs +26 -25
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +7 -6
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectionProvider.d.ts +5 -0
- package/dist/connection/types.d.ts +6 -0
- package/dist/document-tools/DocumentToolButtons.d.ts +29 -0
- package/dist/document-tools/MarkupNotices.d.ts +12 -0
- package/dist/document-tools/MarkupViewNote.d.ts +11 -0
- package/dist/document-tools/SignDocumentDialog.d.ts +20 -0
- package/dist/document-tools/SignatureCertificate.d.ts +26 -0
- package/dist/document-tools/SignatureStatus.d.ts +24 -0
- package/dist/document-tools/VersionSnapshotBar.d.ts +27 -0
- package/dist/document-tools/index.cjs +637 -0
- package/dist/document-tools/index.cjs.map +1 -0
- package/dist/document-tools/index.d.ts +7 -0
- package/dist/document-tools/index.js +623 -0
- package/dist/document-tools/index.js.map +1 -0
- package/dist/document-tools/production/ProductionSetDialog.d.ts +23 -0
- package/dist/document-tools/production/index.cjs +102 -0
- package/dist/document-tools/production/index.cjs.map +1 -0
- package/dist/document-tools/production/index.d.ts +1 -0
- package/dist/document-tools/production/index.js +100 -0
- package/dist/document-tools/production/index.js.map +1 -0
- package/dist/document-tools/viewer/AnnotatedPdfViewer.d.ts +54 -0
- package/dist/document-tools/viewer/SignaturePlacementViewer.d.ts +20 -0
- package/dist/document-tools/viewer/index.cjs +273 -0
- package/dist/document-tools/viewer/index.cjs.map +1 -0
- package/dist/document-tools/viewer/index.d.ts +2 -0
- package/dist/document-tools/viewer/index.js +268 -0
- package/dist/document-tools/viewer/index.js.map +1 -0
- package/dist/docx/index.cjs +1 -0
- package/dist/docx/index.cjs.map +1 -1
- package/dist/docx/index.js +1 -0
- package/dist/docx/index.js.map +1 -1
- package/dist/facts/index.cjs +1 -0
- package/dist/facts/index.cjs.map +1 -1
- package/dist/facts/index.js +1 -0
- package/dist/facts/index.js.map +1 -1
- package/dist/files/cells/DocumentNameCell.d.ts +3 -1
- package/dist/files/index.cjs +39 -67
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.js +20 -63
- package/dist/files/index.js.map +1 -1
- package/dist/home/index.cjs +1 -0
- package/dist/home/index.cjs.map +1 -1
- package/dist/home/index.js +1 -0
- package/dist/home/index.js.map +1 -1
- package/dist/index.cjs +481 -480
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/lib-6QPUXAQS.cjs +9674 -0
- package/dist/lib-6QPUXAQS.cjs.map +1 -0
- package/dist/lib-NRGL2JGF.js +9672 -0
- package/dist/lib-NRGL2JGF.js.map +1 -0
- package/dist/retrieval/index.cjs +1 -0
- package/dist/retrieval/index.js +1 -0
- package/dist/settings/index.cjs +2 -1
- package/dist/settings/index.cjs.map +1 -1
- package/dist/settings/index.js +2 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/shell/index.cjs +1 -0
- package/dist/shell/index.js +1 -0
- package/dist/site/index.cjs +1 -0
- package/dist/site/index.js +1 -0
- 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/timeline/index.cjs +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/workspaces/index.cjs +1 -0
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.js +1 -0
- package/dist/workspaces/index.js.map +1 -1
- package/package.json +32 -4
- package/dist/StreamedArtifactEditor-OPL4KXOT.js.map +0 -1
- package/dist/StreamedArtifactEditor-RIKG6CJQ.cjs.map +0 -1
- package/dist/chunk-EHXSBH6U.js.map +0 -1
- package/dist/chunk-TLQQV7WW.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Optional peers, only needed for the entry that uses them:
|
|
|
19
19
|
|
|
20
20
|
| Peer | Needed by |
|
|
21
21
|
| --- | --- |
|
|
22
|
-
| `@tanstack/react-query` | `@arbidocs/blocks/connect`, `@arbidocs/blocks/studio` |
|
|
22
|
+
| `@tanstack/react-query` | `@arbidocs/blocks/connect`, `@arbidocs/blocks/studio`, `@arbidocs/blocks/document-tools` |
|
|
23
23
|
| `react-router-dom` | `@arbidocs/blocks/studio` |
|
|
24
24
|
| `@measured/puck` | `@arbidocs/blocks/studio` |
|
|
25
25
|
| `@playwright/test` | types of `@arbidocs/blocks/record` (no runtime import) |
|
|
@@ -67,6 +67,8 @@ Every capability is its own entry, so a bundler only loads what you use:
|
|
|
67
67
|
| `/files`, `/facts` | document grid, facts table | `ag-grid-*` |
|
|
68
68
|
| `/artifacts` | artifact editor, version bar, track changes | none |
|
|
69
69
|
| `/artifacts/editor` | rich-text (markdown) editing surface | `@mdxeditor/editor` (optional peer) |
|
|
70
|
+
| `/document-tools` | PDF markup, signing and version parts (see below) | `@tanstack/react-query` |
|
|
71
|
+
| `/document-tools/viewer` | annotated PDF viewer, signature placement | `pdf-lib`, `react-pdf` (optional peers of `@arbidocs/react`) |
|
|
70
72
|
| `/home`, `/workspaces` | dashboard, workspace cards and forms | `@dnd-kit/*` |
|
|
71
73
|
| `/settings` | settings, billing, modals | `cmdk` |
|
|
72
74
|
| `/connect` | demo/live connection layer | `@tanstack/react-query` |
|
|
@@ -157,6 +159,164 @@ draft is stored and parsed, then the editor on the stored version (the presentat
|
|
|
157
159
|
<StreamedArtifact artifacts={task.artifacts} workspaceId={workspaceId} busy={task.status === 'running'} error={task.error} />
|
|
158
160
|
```
|
|
159
161
|
|
|
162
|
+
## Using the document tools in another frontend
|
|
163
|
+
|
|
164
|
+
The PDF document tools are what ARBI's document page uses: annotate (highlight, comment, stamp,
|
|
165
|
+
redact) with the marks saved as the version's markup on the server (autosave, colleagues' edits
|
|
166
|
+
merged in), "Show original", "Download with markup", the notes about markup on an older version
|
|
167
|
+
("Copy open comments here") and about marks left in this browser, Freeze (a separate annotated or
|
|
168
|
+
redacted copy, with a redaction log), e-signing (choose where the signature goes, sign with the
|
|
169
|
+
password; only the signature and optionally the date are drawn), the signature details with "View
|
|
170
|
+
certificate", the public certificate page, the read-only version bar and production sets (Bates
|
|
171
|
+
numbering).
|
|
172
|
+
|
|
173
|
+
| Import | What |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `@arbidocs/react/document-tools` | `DocumentToolsProvider`, `fetchDocumentPdf`, `fetchDocumentFile`, `useDocumentMarkup`, `createMarkupStore`, `fetchMarkupPdf`, `canAnnotate`, `useDocumentSignatures`, `useSignDocument`, `useSignatureVerification`, `buildProduction`, `saveProductionFiles` |
|
|
176
|
+
| `@arbidocs/blocks/document-tools` | `AnnotateButton`, `ShowOriginalButton`, `DownloadMarkupButton`, `SignButton`, `MarkupNotices`, `MarkupViewNote`, `SignDocumentDialog`, `SignatureStatus`, `SignatureCertificate`, `VersionSnapshotBar` |
|
|
177
|
+
| `@arbidocs/blocks/document-tools/viewer` | `AnnotatedPdfViewer`, `SignaturePlacementViewer` (load lazily: pdf-lib) |
|
|
178
|
+
| `@arbidocs/blocks/document-tools/production` | `ProductionSetDialog` (load lazily; pdf-lib and JSZip load on confirm) |
|
|
179
|
+
|
|
180
|
+
What the host provides, once, around the viewer (the tools import no store, router or toast
|
|
181
|
+
library of their own):
|
|
182
|
+
|
|
183
|
+
- an ARBI API client signed in as the user: `arbi.getClient().fetch` from an `@arbidocs/sdk`
|
|
184
|
+
`Arbi`, or `createArbiClient(...).fetch` from `@arbidocs/client`;
|
|
185
|
+
- `user: { name, email }` for signing (without a user marks are authored as "You") and the
|
|
186
|
+
`deploymentDomain` the user's keys are derived for. Inside an `ArbiProvider` (or
|
|
187
|
+
`ArbiAppProvider`, which mounts one) `deploymentDomain` defaults to the SDK's own,
|
|
188
|
+
`arbi.getDeploymentDomain()` (the `deploymentDomain` option, else the API URL's hostname), which
|
|
189
|
+
is also `useDeploymentDomain()` from `@arbidocs/react` and `deploymentDomain` on
|
|
190
|
+
`useConnection()`. Pass it only when the API is served from another host than the one users
|
|
191
|
+
registered on (`ArbiConnectionConfig.deploymentDomain` sets it for the whole app);
|
|
192
|
+
- callbacks, all optional: `notify(message, kind, { description, action })`, `openDocument(ref)`
|
|
193
|
+
(the copy just frozen, the signed copy, a saved production), `onDocumentsChanged(ids, 'markup' |
|
|
194
|
+
'copy' | 'signed')` to refresh your lists, `emailDocument(ref)` (adds "Email it" after signing),
|
|
195
|
+
`uploadDocument`, `saveFile` and `certificateUrl` (defaults: the API client, a download link, the
|
|
196
|
+
backend's certificate link; see Signature certificates);
|
|
197
|
+
- a React Query `QueryClientProvider`, the blocks styles (see Styles), the optional peers
|
|
198
|
+
`react-pdf`, `pdfjs-dist` and `pdf-lib`, and the pdf.js runtime (see below).
|
|
199
|
+
|
|
200
|
+
The PDF the tools draw on is the document's `/view` rendering (the file itself for a PDF, its PDF
|
|
201
|
+
rendering for a Word or text file). Fetch it with the function the tools use:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { fetchDocumentPdf } from '@arbidocs/react/document-tools'
|
|
205
|
+
|
|
206
|
+
// GET /v1/document/{id}/view?version= with Accept: application/pdf; a `doc-…@v2` reference
|
|
207
|
+
// names a version too. Throws a DocumentFetchError (with `status`) when there is no PDF yet.
|
|
208
|
+
const pdf = await fetchDocumentPdf(arbi.getClient().fetch, doc.external_id, { version: 2 })
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Put the version in your cache key: a document keeps its id across versions (a signed copy is the
|
|
212
|
+
next version), so a new version must never show the previous one's file.
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
import { lazy, Suspense, useState } from 'react'
|
|
216
|
+
import { DocumentToolsProvider, useDocumentMarkup, useDocumentSignatures } from '@arbidocs/react/document-tools'
|
|
217
|
+
import { AnnotateButton, MarkupNotices, SignatureStatus } from '@arbidocs/blocks/document-tools'
|
|
218
|
+
const AnnotatedPdfViewer = lazy(() =>
|
|
219
|
+
import('@arbidocs/blocks/document-tools/viewer').then((m) => ({ default: m.AnnotatedPdfViewer })))
|
|
220
|
+
|
|
221
|
+
<DocumentToolsProvider
|
|
222
|
+
client={arbi.getClient().fetch}
|
|
223
|
+
user={{ name: 'Ana Lopez', email: 'ana@firm.example' }}
|
|
224
|
+
notify={(message, kind) => toast[kind](message)}
|
|
225
|
+
openDocument={(ref) => navigate(`/documents/${ref}`)}
|
|
226
|
+
onDocumentsChanged={() => queryClient.invalidateQueries({ queryKey: ['documents'] })}
|
|
227
|
+
certificateUrl={(ref) => `${location.origin}/verify/${ref}`}
|
|
228
|
+
>
|
|
229
|
+
<DocumentPage doc={doc} pdf={pdfBlob} />
|
|
230
|
+
</DocumentToolsProvider>
|
|
231
|
+
|
|
232
|
+
function DocumentPage({ doc, pdf }) {
|
|
233
|
+
// `doc` is the document record (DocResponse): external_id, shared, folder, current_version, versions.
|
|
234
|
+
const [editing, setEditing] = useState(false)
|
|
235
|
+
const markup = useDocumentMarkup(doc, undefined)
|
|
236
|
+
const { data: signatures } = useDocumentSignatures(doc.external_id)
|
|
237
|
+
return (
|
|
238
|
+
<>
|
|
239
|
+
<AnnotateButton active={editing} onClick={() => setEditing((on) => !on)} />
|
|
240
|
+
{signatures?.signed && <SignatureStatus status={signatures} />}
|
|
241
|
+
<MarkupNotices legacyPrompt={markup.legacyPrompt} olderNote={markup.olderNote}
|
|
242
|
+
onOpenVersion={(n) => navigate(`/documents/${doc.external_id}@v${n}`)} />
|
|
243
|
+
<Suspense fallback={null}>
|
|
244
|
+
<AnnotatedPdfViewer file={pdf} documentId={doc.external_id} fileName={doc.file_name}
|
|
245
|
+
shared={!!doc.shared} folder={doc.folder} editing={editing}
|
|
246
|
+
onMarkupChange={markup.onMarkupChange} />
|
|
247
|
+
</Suspense>
|
|
248
|
+
</>
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
A signed version is locked: only a further signature changes it. Pass `signed` to
|
|
254
|
+
`AnnotatedPdfViewer` and a `disabledReason` (`SIGNED_LOCKED_REASON`, from `isSignedVersion(doc)` or
|
|
255
|
+
the signature status) to `DownloadMarkupButton`: marks stay in the markup layer and are never
|
|
256
|
+
written into its PDF, and the plain download is the signed file. Show `SignedEditNote` above any
|
|
257
|
+
editor of a signed version ("Editing creates a new unsigned version").
|
|
258
|
+
|
|
259
|
+
`AnnotatedPdfViewer` and `SignaturePlacementViewer` take your own binding of the kit viewer as
|
|
260
|
+
`viewer` (for example one that reports the visible page); `SignaturePlacementViewer`'s
|
|
261
|
+
`onContinue(appearance)` hands the box to `SignDocumentDialog`.
|
|
262
|
+
|
|
263
|
+
### Signature certificates
|
|
264
|
+
|
|
265
|
+
Serve `SignatureCertificate` on a route that needs no sign-in (ARBI uses `/verify/:reference`),
|
|
266
|
+
inside a `DocumentToolsProvider` with an unauthenticated client. "View certificate" (in
|
|
267
|
+
`SignatureStatus`, and after signing) opens the provider's `certificateUrl(reference)` when you
|
|
268
|
+
give one, so it lands on your own page; without it, the `certificate_url` the backend returned,
|
|
269
|
+
else `/verify/{reference}` on this origin. The link drawn into the signed PDF itself is set by the
|
|
270
|
+
backend and always points at the deployment domain (`https://{DEPLOYMENT_DOMAIN}/verify/{ref}`):
|
|
271
|
+
serve the certificate page there too, or redirect that path to yours.
|
|
272
|
+
|
|
273
|
+
### Production sets
|
|
274
|
+
|
|
275
|
+
`ProductionSetDialog` numbers the selected documents with Bates labels (optionally a QR code back
|
|
276
|
+
to each document and an index page), downloads the result (one PDF, or a ZIP with each file and an
|
|
277
|
+
`index.csv`) and saves it to the workspace as new documents derived from all their sources
|
|
278
|
+
(`derived_from` repeated, role `production`) in a Productions folder, shared only if every source
|
|
279
|
+
is. A PDF is numbered as stored, anything else through its `/view` PDF; media are left out. It uses
|
|
280
|
+
the provider's client, `uploadDocument`, `saveFile`, `notify`, `onDocumentsChanged(ids, 'copy')`
|
|
281
|
+
and `openDocument` (its "Open" action); you give it the selection and your deep link:
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
const ProductionSetDialog = lazy(() =>
|
|
285
|
+
import('@arbidocs/blocks/document-tools/production').then((m) => ({ default: m.ProductionSetDialog })))
|
|
286
|
+
|
|
287
|
+
<ProductionSetDialog open={open} onOpenChange={setOpen} documents={selectedDocs}
|
|
288
|
+
documentUrl={(id) => `${location.origin}/documents/${id}`} />
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
A custom `uploadDocument` receives the upload query typed from the API schema
|
|
292
|
+
(`DocumentUploadQuery`: `derived_from` is a list, `shared` a boolean). If you post the upload
|
|
293
|
+
yourself (an XHR with progress), build the query string with `uploadQueryString(query)`, which
|
|
294
|
+
repeats `derived_from` for each source; the default, `clientUpload(client)`, does this already.
|
|
295
|
+
|
|
296
|
+
### The pdf.js runtime
|
|
297
|
+
|
|
298
|
+
The kit `PdfViewer` loads the pdf.js worker and its data from your site: `/pdf.worker.min.mjs`,
|
|
299
|
+
`/cmaps/`, `/standard_fonts/` and `/wasm/` (the JPEG 2000 and JBIG2 decoders: without them
|
|
300
|
+
scanned PDFs render blank). `@arbidocs/blocks` ships a command that copies them from your installed
|
|
301
|
+
`pdfjs-dist` into your public directory, with shims for the newer built-ins pdf.js needs in older
|
|
302
|
+
browsers. It fails if your `pdfjs-dist` differs from the one `react-pdf` runs, which would break
|
|
303
|
+
every PDF with "API version does not match Worker version":
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"scripts": {
|
|
308
|
+
"pdf-assets": "arbidocs-copy-pdf-assets public",
|
|
309
|
+
"predev": "npm run pdf-assets",
|
|
310
|
+
"prebuild": "npm run pdf-assets"
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Pin `pdfjs-dist` to the exact version `react-pdf` depends on, and keep the copied files out of
|
|
316
|
+
version control (`public/pdf.worker*.mjs`, `public/cmaps/`, `public/standard_fonts/`,
|
|
317
|
+
`public/wasm/`). `--images` also copies the pdf.js annotation icons to `/images/`. To serve them
|
|
318
|
+
elsewhere, pass `assets` (`workerSrc`, `cMapUrl`, `standardFontDataUrl`, `wasmUrl`) to the viewer.
|
|
319
|
+
|
|
160
320
|
## Editorial site parts
|
|
161
321
|
|
|
162
322
|
`@arbidocs/blocks/site` (and the root) carry the layout parts for static marketing pages:
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* arbidocs-copy-pdf-assets <publicDir> [--images]
|
|
4
|
+
*
|
|
5
|
+
* Serve the pdf.js runtime the document tools' PDF viewer loads (the kit `PdfViewer` of
|
|
6
|
+
* @arbidocs/react/viewers, whose default asset paths these are):
|
|
7
|
+
*
|
|
8
|
+
* /pdf.worker.min.mjs, /pdf.worker.mjs the worker, with shims for newer built-ins
|
|
9
|
+
* /cmaps/ character maps (CJK and other non-embedded encodings)
|
|
10
|
+
* /standard_fonts/ the standard 14 fonts
|
|
11
|
+
* /wasm/ JPEG 2000 / JBIG2 / colour decoders: without them a
|
|
12
|
+
* scanned PDF renders blank white pages
|
|
13
|
+
* /images/ (with --images) pdf.js annotation icons
|
|
14
|
+
*
|
|
15
|
+
* Copied from the pdfjs-dist installed for the app (resolved from the current directory), so the
|
|
16
|
+
* worker always matches the library react-pdf runs: a mismatch fails every PDF with "API version
|
|
17
|
+
* does not match Worker version". Run it before dev and build, e.g. in `predev` / `prebuild`.
|
|
18
|
+
*
|
|
19
|
+
* The worker gets small shims for the newer built-ins pdf.js 5+ relies on (Uint8Array hex,
|
|
20
|
+
* Map.prototype.getOrInsertComputed, Math.sumPrecise); each steps aside where the browser has the
|
|
21
|
+
* real one. Without them older browsers fail to parse ("x.toHex is not a function") or draw no
|
|
22
|
+
* pages at all.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
26
|
+
import { createRequire } from 'node:module'
|
|
27
|
+
import { dirname, join, resolve } from 'node:path'
|
|
28
|
+
|
|
29
|
+
const args = process.argv.slice(2)
|
|
30
|
+
const withImages = args.includes('--images')
|
|
31
|
+
const target = args.find((arg) => !arg.startsWith('--'))
|
|
32
|
+
if (!target || args.includes('--help')) {
|
|
33
|
+
console.error('Usage: arbidocs-copy-pdf-assets <publicDir> [--images]')
|
|
34
|
+
process.exit(target ? 0 : 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Resolve from the app (the current directory), not from this package: the app's pdfjs-dist is
|
|
38
|
+
// the one its bundle runs.
|
|
39
|
+
const appRequire = createRequire(join(process.cwd(), 'package.json'))
|
|
40
|
+
let pdfjsRoot
|
|
41
|
+
try {
|
|
42
|
+
pdfjsRoot = dirname(appRequire.resolve('pdfjs-dist/package.json'))
|
|
43
|
+
} catch {
|
|
44
|
+
console.error('arbidocs-copy-pdf-assets: pdfjs-dist is not installed (npm install pdfjs-dist)')
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
const versionOf = (dir) => JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).version
|
|
48
|
+
|
|
49
|
+
// react-pdf may use a nested copy of pdfjs-dist; the worker must match that one.
|
|
50
|
+
try {
|
|
51
|
+
const reactPdfRequire = createRequire(appRequire.resolve('react-pdf'))
|
|
52
|
+
const reactPdfPdfjs = dirname(reactPdfRequire.resolve('pdfjs-dist/package.json'))
|
|
53
|
+
if (versionOf(reactPdfPdfjs) !== versionOf(pdfjsRoot)) {
|
|
54
|
+
console.error(
|
|
55
|
+
`arbidocs-copy-pdf-assets: pdfjs-dist ${versionOf(pdfjsRoot)} differs from the ` +
|
|
56
|
+
`${versionOf(reactPdfPdfjs)} react-pdf uses. Pin "pdfjs-dist" to ` +
|
|
57
|
+
`"${versionOf(reactPdfPdfjs)}" (no ^) in package.json and reinstall.`
|
|
58
|
+
)
|
|
59
|
+
process.exit(1)
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
// No react-pdf installed: nothing to match.
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const SHIMS = `
|
|
66
|
+
if (typeof Uint8Array.prototype.toHex !== 'function') {
|
|
67
|
+
Object.defineProperty(Uint8Array.prototype, 'toHex', { configurable: true, writable: true,
|
|
68
|
+
value() { let s = ''; for (let i = 0; i < this.length; i++) s += this[i].toString(16).padStart(2, '0'); return s; } });
|
|
69
|
+
}
|
|
70
|
+
if (typeof Uint8Array.fromHex !== 'function') {
|
|
71
|
+
Object.defineProperty(Uint8Array, 'fromHex', { configurable: true, writable: true,
|
|
72
|
+
value(hex) { const h = hex.replace(/\\s+/g, ''); if (h.length % 2) throw new SyntaxError('Uint8Array.fromHex: odd length');
|
|
73
|
+
const out = new Uint8Array(h.length / 2);
|
|
74
|
+
for (let i = 0; i < out.length; i++) { const b = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
75
|
+
if (Number.isNaN(b)) throw new SyntaxError('Uint8Array.fromHex: non-hex digit'); out[i] = b; }
|
|
76
|
+
return out; } });
|
|
77
|
+
}
|
|
78
|
+
if (typeof Map.prototype.getOrInsertComputed !== 'function') {
|
|
79
|
+
Object.defineProperty(Map.prototype, 'getOrInsertComputed', { configurable: true, writable: true,
|
|
80
|
+
value(key, make) { if (this.has(key)) return this.get(key); const v = make(key); this.set(key, v); return v; } });
|
|
81
|
+
}
|
|
82
|
+
if (typeof Math.sumPrecise !== 'function') {
|
|
83
|
+
Object.defineProperty(Math, 'sumPrecise', { configurable: true, writable: true,
|
|
84
|
+
value(values) { let sum = 0, c = 0; for (const v of values) { const t = sum + v;
|
|
85
|
+
c += Math.abs(sum) >= Math.abs(v) ? sum - t + v : v - t + sum; sum = t; } return sum + c; } });
|
|
86
|
+
}
|
|
87
|
+
`
|
|
88
|
+
|
|
89
|
+
const publicDir = resolve(target)
|
|
90
|
+
mkdirSync(publicDir, { recursive: true })
|
|
91
|
+
for (const name of ['pdf.worker.min.mjs', 'pdf.worker.mjs']) {
|
|
92
|
+
const source = readFileSync(join(pdfjsRoot, 'build', name), 'utf8')
|
|
93
|
+
writeFileSync(join(publicDir, name), SHIMS + source)
|
|
94
|
+
}
|
|
95
|
+
const dirs = [
|
|
96
|
+
['cmaps', 'cmaps'],
|
|
97
|
+
['standard_fonts', 'standard_fonts'],
|
|
98
|
+
['wasm', 'wasm'],
|
|
99
|
+
...(withImages ? [['web/images', 'images']] : []),
|
|
100
|
+
]
|
|
101
|
+
for (const [from, to] of dirs) {
|
|
102
|
+
const source = join(pdfjsRoot, from)
|
|
103
|
+
if (!existsSync(source)) {
|
|
104
|
+
console.error(`arbidocs-copy-pdf-assets: pdfjs-dist ${versionOf(pdfjsRoot)} has no ${from}/`)
|
|
105
|
+
process.exit(1)
|
|
106
|
+
}
|
|
107
|
+
cpSync(source, join(publicDir, to), { recursive: true })
|
|
108
|
+
}
|
|
109
|
+
console.log(
|
|
110
|
+
`pdf.js ${versionOf(pdfjsRoot)} worker, ${dirs.map(([, to]) => `${to}/`).join(', ')} ` +
|
|
111
|
+
`copied to ${publicDir}`
|
|
112
|
+
)
|
|
@@ -3,6 +3,7 @@ import { ArtifactMarkdownEditor } from './chunk-NEFHQHQV.js';
|
|
|
3
3
|
import { ArtifactEditor, ArtifactRedlineView } from './chunk-65HZ36MY.js';
|
|
4
4
|
import './chunk-LOJVUGBJ.js';
|
|
5
5
|
import './chunk-7F6CBP3Z.js';
|
|
6
|
+
import './chunk-VUNV25KB.js';
|
|
6
7
|
import { useState } from 'react';
|
|
7
8
|
import { Copy, Download } from 'lucide-react';
|
|
8
9
|
import { Button, cn } from '@arbidocs/react/ui';
|
|
@@ -100,5 +101,5 @@ function StreamedArtifactEditor({
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
export { StreamedArtifactEditor as default };
|
|
103
|
-
//# sourceMappingURL=StreamedArtifactEditor-
|
|
104
|
-
//# sourceMappingURL=StreamedArtifactEditor-
|
|
104
|
+
//# sourceMappingURL=StreamedArtifactEditor-HTNPG4NB.js.map
|
|
105
|
+
//# sourceMappingURL=StreamedArtifactEditor-HTNPG4NB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":[],"mappings":";;;;;;;;;;;AAmCe,SAAR,sBAAA,CAAwC;AAAA,EAC7C,WAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,kBAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,IAAI,kBAAA,CAAmB;AAAA,IAC3B,WAAA;AAAA,IACA,KAAA,EAAO,MAAA;AAAA,IACP,KAAA;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,KAAA,EAAO,MAAK,KAAM;AAC5B,MAAA,IAAI,IAAA,YAAgB,IAAI,CAAA;AACxB,MAAA,OAAA,GAAU,IAAI,CAAA;AAAA,IAChB,CAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,OAAO,MAAM,KAAK,UAAU,SAAA,CAAU,SAAA,CAAU,EAAE,OAAO,CAAA;AAC/D,EAAA,MAAM,WAAW,MAAM;AACrB,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,IAAA,CAAK,CAAC,CAAA,CAAE,OAAO,CAAA,EAAG,EAAE,IAAA,EAAM,eAAA,EAAiB,CAAC,CAAA;AAChF,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACpC,IAAA,CAAA,CAAE,IAAA,GAAO,GAAA;AACT,IAAA,CAAA,CAAE,WAAW,CAAA,EAAG,KAAA,CAAM,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAC,CAAA,GAAA,CAAA;AAC3C,IAAA,CAAA,CAAE,KAAA,EAAM;AACR,IAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AAAA,EACzB,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,qEAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,aAAA,EAAa,MAAA;AAAA,MAEb,QAAA,kBAAA,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACE,GAAG,CAAA,CAAE,IAAA;AAAA,UACN,SAAA,EAAU,sBAAA;AAAA,UACV,MAAA;AAAA,UACA,aAAA,EAAe,SAAA;AAAA,UACf,cAAA,EAAgB,sBAAA;AAAA,UAChB,wBAAQ,GAAA,CAAC,sBAAA,EAAA,EAAwB,GAAG,WAAA,EAAc,GAAG,EAAE,WAAA,EAAa,CAAA;AAAA,UACpE,yBACE,GAAA,CAAC,mBAAA,EAAA,EAAqB,GAAG,CAAA,CAAE,YAAA,EAAc,gBAAgB,sBAAA,EAAwB,CAAA;AAAA,UAEnF,yBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,YAAA,CAAC,sCACA,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,8BAAA,IAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAQ,OAAA;AAAA,kBACR,IAAA,EAAK,IAAA;AAAA,kBACL,OAAA,EAAS,IAAA;AAAA,kBACT,aAAA,EAAa,GAAG,MAAM,CAAA,KAAA,CAAA;AAAA,kBACtB,SAAA,EAAU,yBAAA;AAAA,kBAEV,QAAA,EAAA;AAAA,oCAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EAAS,aAAA,EAAW,IAAA,EAAC,CAAA;AAAA,oBAAE;AAAA;AAAA;AAAA,eACzC;AAAA,8BACA,IAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAQ,OAAA;AAAA,kBACR,IAAA,EAAK,IAAA;AAAA,kBACL,OAAA,EAAS,QAAA;AAAA,kBACT,aAAA,EAAa,GAAG,MAAM,CAAA,SAAA,CAAA;AAAA,kBACtB,SAAA,EAAU,yBAAA;AAAA,kBAEV,QAAA,EAAA;AAAA,oCAAA,GAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAU,QAAA,EAAS,aAAA,EAAW,IAAA,EAAC,CAAA;AAAA,oBAAE;AAAA;AAAA;AAAA;AAC7C,aAAA,EACF,CAAA;AAAA,YAED,UAAU,EAAE,OAAA,EAAS,CAAA,CAAE,OAAA,EAAS,OAAO;AAAA,WAAA,EAC1C;AAAA;AAAA;AAEJ;AAAA,GACF;AAEJ","file":"StreamedArtifactEditor-HTNPG4NB.js","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
|
|
@@ -5,6 +5,7 @@ var chunkQS4RV3MA_cjs = require('./chunk-QS4RV3MA.cjs');
|
|
|
5
5
|
var chunkSVJQWLOF_cjs = require('./chunk-SVJQWLOF.cjs');
|
|
6
6
|
require('./chunk-QVBZESYQ.cjs');
|
|
7
7
|
require('./chunk-MHVNT4J3.cjs');
|
|
8
|
+
require('./chunk-DES3K4SD.cjs');
|
|
8
9
|
var react = require('react');
|
|
9
10
|
var lucideReact = require('lucide-react');
|
|
10
11
|
var ui = require('@arbidocs/react/ui');
|
|
@@ -102,5 +103,5 @@ function StreamedArtifactEditor({
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
module.exports = StreamedArtifactEditor;
|
|
105
|
-
//# sourceMappingURL=StreamedArtifactEditor-
|
|
106
|
-
//# sourceMappingURL=StreamedArtifactEditor-
|
|
106
|
+
//# sourceMappingURL=StreamedArtifactEditor-IZWYNFMM.cjs.map
|
|
107
|
+
//# sourceMappingURL=StreamedArtifactEditor-IZWYNFMM.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/connection/StreamedArtifactEditor.tsx"],"names":["useState","useArtifactSession","jsx","cn","ArtifactEditor","renderArtifactMarkdown","ArtifactMarkdownEditor","ArtifactRedlineView","jsxs","Fragment","Button","Copy","Download"],"mappings":"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","file":"StreamedArtifactEditor-IZWYNFMM.cjs","sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { Copy, Download } from 'lucide-react'\nimport { Button, cn } from '@arbidocs/react/ui'\nimport { renderArtifactMarkdown, useArtifactSession } from '@arbidocs/react/artifacts'\nimport { ArtifactEditor, ArtifactRedlineView, type ArtifactEditorLabels } from '../artifacts'\nimport {\n ArtifactMarkdownEditor,\n type ArtifactMarkdownEditorProps,\n} from '../artifacts/editor/ArtifactMarkdownEditor'\n\nexport interface StreamedArtifactEditorProps {\n workspaceId: string | undefined\n /** The stored first version (the lineage's root as far as this panel goes). */\n docId: string\n /** File name for the versions saved from here. */\n title: string\n testId: string\n className?: string\n /** Extra props of the rich-text editor (`dictation`, labels). */\n editorProps?: Partial<Omit<ArtifactMarkdownEditorProps, 'markdown' | 'onChange' | 'onNormalized'>>\n /** Called after a version is saved. */\n onSaved?: (docId: string | undefined) => void\n onSaveError?: (error: unknown) => void\n /** Extra header actions next to the toolbar. */\n actions?: (ctx: { content: string; title: string }) => ReactNode\n /** Hide the default Copy and Download buttons. */\n hideDefaultActions?: boolean\n labels?: Partial<ArtifactEditorLabels>\n}\n\n/**\n * The editing stage of `StreamedArtifact`: `ArtifactEditor` bound to `useArtifactSession`. It is\n * a separate module because it pulls the rich-text editor (Lexical), which must stay behind a\n * `lazy()` boundary.\n */\nexport default function StreamedArtifactEditor({\n workspaceId,\n docId,\n title,\n testId,\n className,\n editorProps,\n onSaved,\n onSaveError,\n actions,\n hideDefaultActions,\n labels,\n}: StreamedArtifactEditorProps) {\n const [openId, setOpenId] = useState(docId)\n const s = useArtifactSession({\n workspaceId,\n docId: openId,\n title,\n onSaved: ({ docId: next }) => {\n if (next) setOpenId(next)\n onSaved?.(next)\n },\n onSaveError,\n })\n\n const copy = () => void navigator.clipboard.writeText(s.content)\n const download = () => {\n const url = URL.createObjectURL(new Blob([s.content], { type: 'text/markdown' }))\n const a = document.createElement('a')\n a.href = url\n a.download = `${title.replace(/\\.md$/i, '')}.md`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex min-h-[560px] flex-col rounded-xl border border-border bg-card',\n className\n )}\n data-testid={testId}\n >\n <ArtifactEditor\n {...s.view}\n className=\"min-h-[560px] flex-1\"\n labels={labels}\n onOpenVersion={setOpenId}\n renderMarkdown={renderArtifactMarkdown}\n editor={<ArtifactMarkdownEditor {...editorProps} {...s.editorProps} />}\n redline={\n <ArtifactRedlineView {...s.redlineProps} renderMarkdown={renderArtifactMarkdown} />\n }\n actions={\n <>\n {!hideDefaultActions && (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={copy}\n data-testid={`${testId}-copy`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Copy className=\"size-4\" aria-hidden /> Copy\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={download}\n data-testid={`${testId}-download`}\n className=\"pointer-coarse:min-h-11\"\n >\n <Download className=\"size-4\" aria-hidden /> Download\n </Button>\n </>\n )}\n {actions?.({ content: s.content, title })}\n </>\n }\n />\n </div>\n )\n}\n"]}
|