@arbidocs/blocks 0.4.98 → 0.4.99

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.
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { NativeDocxEditor } from './chunk-FIEAWH4K.js';
2
+ import { NativeDocxEditor } from './chunk-4ZTIMQ7Z.js';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  function StreamedWordArtifact({
@@ -37,5 +37,5 @@ function StreamedWordArtifact({
37
37
  }
38
38
 
39
39
  export { StreamedWordArtifact };
40
- //# sourceMappingURL=chunk-6B2AWE3I.js.map
41
- //# sourceMappingURL=chunk-6B2AWE3I.js.map
40
+ //# sourceMappingURL=chunk-3ICWR3BK.js.map
41
+ //# sourceMappingURL=chunk-3ICWR3BK.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/docx/StreamedWordArtifact.tsx"],"names":[],"mappings":";;;AAmBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,OAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAA8B;AAC5B,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,uBACE,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QAEC,OAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OAAA;AAAA,MAJK;AAAA,KAKP;AAAA,EAEJ;AACA,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MAEC,OAAA;AAAA,MACA,UAAA,EAAW,gBAAA;AAAA,MACX,KAAA;AAAA,MACA,YAAA,EAAa,EAAA;AAAA,MACb,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,EAAM,KAAA;AAAM,KAAA;AAAA,IAL3B;AAAA,GAMN;AAEJ","file":"chunk-6B2AWE3I.js","sourcesContent":["import { NativeDocxEditor, type NativeDocxAdapter } from './NativeDocxEditor'\n\nexport interface StreamedWordArtifactProps {\n adapter: NativeDocxAdapter\n /** Streamed Markdown, shown as a read-only preview while the draft is generated. */\n content: string\n title: string\n busy: boolean\n error?: string | null\n /** The DOCX draft the server stored for this generation (`doc-…`), once known. */\n documentId?: string\n onSaved?: (documentId: string) => void\n}\n\n/**\n * One drafting surface for an AI document draft. The server stores every draft as DOCX, so\n * this component never creates a document: it previews the streamed Markdown until generation\n * ends and the stored DOCX is known, then opens that DOCX in the live collaborative editor.\n */\nexport function StreamedWordArtifact({\n adapter,\n content,\n title,\n busy,\n error,\n documentId,\n onSaved,\n}: StreamedWordArtifactProps) {\n if (!busy && documentId) {\n return (\n <NativeDocxEditor\n key={documentId}\n adapter={adapter}\n documentId={documentId}\n title={title}\n onSaved={onSaved}\n />\n )\n }\n return (\n <NativeDocxEditor\n key=\"stream-preview\"\n adapter={adapter}\n documentId=\"stream-preview\"\n title={title}\n draftContent=\"\"\n stream={{ content, busy, error }}\n />\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/docx/StreamedWordArtifact.tsx"],"names":[],"mappings":";;;AAmBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,OAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAA8B;AAC5B,EAAA,IAAI,CAAC,QAAQ,UAAA,EAAY;AACvB,IAAA,uBACE,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QAEC,OAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OAAA;AAAA,MAJK;AAAA,KAKP;AAAA,EAEJ;AACA,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MAEC,OAAA;AAAA,MACA,UAAA,EAAW,gBAAA;AAAA,MACX,KAAA;AAAA,MACA,YAAA,EAAa,EAAA;AAAA,MACb,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,EAAM,KAAA;AAAM,KAAA;AAAA,IAL3B;AAAA,GAMN;AAEJ","file":"chunk-3ICWR3BK.js","sourcesContent":["import { NativeDocxEditor, type NativeDocxAdapter } from './NativeDocxEditor'\n\nexport interface StreamedWordArtifactProps {\n adapter: NativeDocxAdapter\n /** Streamed Markdown, shown as a read-only preview while the draft is generated. */\n content: string\n title: string\n busy: boolean\n error?: string | null\n /** The DOCX draft the server stored for this generation (`doc-…`), once known. */\n documentId?: string\n onSaved?: (documentId: string) => void\n}\n\n/**\n * One drafting surface for an AI document draft. The server stores every draft as DOCX, so\n * this component never creates a document: it previews the streamed Markdown until generation\n * ends and the stored DOCX is known, then opens that DOCX in the live collaborative editor.\n */\nexport function StreamedWordArtifact({\n adapter,\n content,\n title,\n busy,\n error,\n documentId,\n onSaved,\n}: StreamedWordArtifactProps) {\n if (!busy && documentId) {\n return (\n <NativeDocxEditor\n key={documentId}\n adapter={adapter}\n documentId={documentId}\n title={title}\n onSaved={onSaved}\n />\n )\n }\n return (\n <NativeDocxEditor\n key=\"stream-preview\"\n adapter={adapter}\n documentId=\"stream-preview\"\n title={title}\n draftContent=\"\"\n stream={{ content, busy, error }}\n />\n )\n}\n"]}
@@ -1285,8 +1285,6 @@ function DocxMentions({
1285
1285
  }
1286
1286
  ) });
1287
1287
  }
1288
-
1289
- // src/docx/definitions/fragment.ts
1290
1288
  var DEFINED_TERM_STYLE = "DefinedTerm";
1291
1289
  var FRAGMENT_STYLES = chunkAOFATOT3_cjs.stylesXml(
1292
1290
  "",
@@ -1319,12 +1317,13 @@ function base64(bytes) {
1319
1317
  binary += String.fromCharCode(...bytes.subarray(i, i + 32768));
1320
1318
  return btoa(binary);
1321
1319
  }
1322
- function fragmentHtml(body, covered2) {
1323
- const bytes = chunkAOFATOT3_cjs.docxPackage({
1320
+ function fragmentHtml(body, covered2, revision) {
1321
+ const untracked = chunkAOFATOT3_cjs.docxPackage({
1324
1322
  document: chunkAOFATOT3_cjs.documentXml(body),
1325
1323
  styles: FRAGMENT_STYLES,
1326
1324
  title: "Defined terms"
1327
1325
  });
1326
+ const bytes = revision ? template.trackInsertion(untracked, revision, covered2) : untracked;
1328
1327
  return `<div data-docx-fragment="${base64(bytes)}" data-docx-fragment-end="${covered2 ? "covered" : "open"}"></div>`;
1329
1328
  }
1330
1329
 
@@ -1581,7 +1580,7 @@ function readParagraph(node, topLevel, bookmarks) {
1581
1580
  links
1582
1581
  };
1583
1582
  }
1584
- function editorPort(editor) {
1583
+ function editorPort(editor, revision) {
1585
1584
  const surface = () => {
1586
1585
  const s = editor.surface;
1587
1586
  if (!s) throw new Error("The document is not open.");
@@ -1600,7 +1599,7 @@ function editorPort(editor) {
1600
1599
  surface().setSelection({ anchor: from, head: to });
1601
1600
  surface().deleteSelection();
1602
1601
  },
1603
- paste: (body, text, covered2) => editor.exec({ type: "paste", text, html: fragmentHtml(body, covered2) }).ok,
1602
+ paste: (body, text, covered2) => editor.exec({ type: "paste", text, html: fragmentHtml(body, covered2, revision) }).ok,
1604
1603
  splitParagraph: () => surface().splitParagraph()
1605
1604
  };
1606
1605
  }
@@ -1643,6 +1642,70 @@ function holdCaret(editor, timeoutMs = 5e3) {
1643
1642
  const offSelection = editor.on("selectionChange", restore);
1644
1643
  const timer = setTimeout(stop, timeoutMs);
1645
1644
  }
1645
+
1646
+ // src/docx/structural/trackedOrNoted.ts
1647
+ var revisionDate = (at = /* @__PURE__ */ new Date()) => at.toISOString().replace(/\.\d{3}Z$/, "Z");
1648
+ function trackedOrNoted(port, { label, author, insert, inserted = Boolean }) {
1649
+ const mode = port.mode();
1650
+ if (mode === "viewing") throw new Error("This document is read only.");
1651
+ if (mode !== "suggesting") return { result: insert(null), how: "direct" };
1652
+ const revision = { author, date: revisionDate() };
1653
+ const before = port.caret();
1654
+ const tracked = port.trackedBy(revision);
1655
+ port.setMode("editing");
1656
+ let result;
1657
+ try {
1658
+ result = insert(revision);
1659
+ } finally {
1660
+ port.setMode("suggesting");
1661
+ }
1662
+ if (!inserted(result) || port.trackedBy(revision) > tracked)
1663
+ return { result, how: inserted(result) ? "tracked" : "direct" };
1664
+ const after = port.caret();
1665
+ if (before && after && port.comment(before, after, label)) return { result, how: "noted" };
1666
+ return { result, how: "direct" };
1667
+ }
1668
+ var attr2 = (node, name) => node.attributes?.find((a) => a.localName === name)?.value;
1669
+ function structuralPort(editor) {
1670
+ return {
1671
+ mode: () => editor.getEditingMode(),
1672
+ setMode: (mode) => void editor.setEditingMode(mode),
1673
+ caret: () => {
1674
+ const head = editor.surface?.state().selection?.head;
1675
+ return head ? { paragraphId: head.paragraphId, offset: head.offset } : null;
1676
+ },
1677
+ // Read from the story's tree: the review pane merges adjacent insertions by one author into
1678
+ // one card, so a card's date need not be this insert's.
1679
+ trackedBy: ({ author, date }) => {
1680
+ const root = editor.surface?.session.part().root;
1681
+ let count = 0;
1682
+ const visit = (node) => {
1683
+ if (node.localName === "ins" && attr2(node, "author") === author && attr2(node, "date") === date)
1684
+ count++;
1685
+ node.children?.forEach(visit);
1686
+ };
1687
+ if (root) visit(root);
1688
+ return count;
1689
+ },
1690
+ comment: (from, to, text) => {
1691
+ const surface = editor.surface;
1692
+ if (!surface) return false;
1693
+ surface.setSelection({ anchor: from, head: to });
1694
+ const ok2 = editor.addComment(text).ok;
1695
+ surface.setSelection({ anchor: to, head: to });
1696
+ return ok2;
1697
+ }
1698
+ };
1699
+ }
1700
+ var DocxAuthorContext = React3.createContext("You");
1701
+ function useTrackedOrNoted() {
1702
+ const editor = react.useDocxEditor();
1703
+ const author = React3.useContext(DocxAuthorContext);
1704
+ return React3.useCallback(
1705
+ (spec) => editor ? trackedOrNoted(structuralPort(editor), { ...spec, author }) : void 0,
1706
+ [editor, author]
1707
+ );
1708
+ }
1646
1709
  var DEFINED_TERM_TRIGGER = "@@";
1647
1710
  var TRIGGER_QUERY = /(?:^|[\s([{"“‘'])@@([^@\n\t]{0,40})$/;
1648
1711
  var MAX_GROUPS = 8;
@@ -1686,6 +1749,7 @@ function DefinedTermsProvider({
1686
1749
  labels
1687
1750
  }) {
1688
1751
  const editor = react.useDocxEditor();
1752
+ const track = useTrackedOrNoted();
1689
1753
  const l = React3.useMemo(() => ({ ...DEFAULT_DEFINED_TERMS_LABELS, ...labels }), [labels]);
1690
1754
  const [sources, setSources] = React3.useState(null);
1691
1755
  const loadedAt = React3.useRef(0);
@@ -1742,35 +1806,46 @@ function DefinedTermsProvider({
1742
1806
  refreshRef.current = refresh;
1743
1807
  const firstHover = React3.useCallback(() => void refreshRef.current(), []);
1744
1808
  const caretRect = () => container().querySelector(".docx-editor-one-surface__caret")?.getBoundingClientRect();
1745
- const run = React3.useCallback(
1809
+ const attempt = React3.useCallback(
1746
1810
  (fn) => {
1747
- if (!editor) return void 0;
1748
1811
  try {
1749
- return withDirectEditing(editor, fn);
1812
+ return fn();
1750
1813
  } catch (error) {
1751
1814
  notify?.(error instanceof Error ? error.message : "Could not change the document.", "error");
1752
1815
  return void 0;
1753
1816
  }
1754
1817
  },
1755
- [editor, notify]
1818
+ [notify]
1819
+ );
1820
+ const run = React3.useCallback(
1821
+ (fn) => editor ? attempt(() => withDirectEditing(editor, fn)) : void 0,
1822
+ [editor, attempt]
1756
1823
  );
1757
1824
  const pick = React3.useCallback(
1758
1825
  (row) => {
1759
1826
  if (!editor || !picker || !row) return;
1760
1827
  const port = editorPort(editor);
1761
- const result = run(() => {
1828
+ const placed = run(() => {
1762
1829
  if (picker.mode === "search" && picker.caret) port.setCaret(picker.caret);
1763
- return insertDefinedTerm(port, row.definition, {
1764
- replace: picker.mode === "typing" ? DEFINED_TERM_TRIGGER.length + picker.query.length : 0
1765
- });
1830
+ const caret = port.caret();
1831
+ if (!caret) throw new Error("Place the cursor where the term should go.");
1832
+ const typed = picker.mode === "typing" ? DEFINED_TERM_TRIGGER.length + picker.query.length : 0;
1833
+ if (typed) port.deleteRange({ ...caret, offset: Math.max(0, caret.offset - typed) }, caret);
1834
+ return true;
1766
1835
  });
1836
+ const result = placed ? attempt(
1837
+ () => track({
1838
+ label: `Inserted defined term: ${row.definition.term}`,
1839
+ insert: (revision) => insertDefinedTerm(editorPort(editor, revision), row.definition)
1840
+ })?.result
1841
+ ) : void 0;
1767
1842
  setPicker(null);
1768
1843
  editor.surface?.focus();
1769
1844
  if (result) holdCaret(editor);
1770
1845
  if (result?.addedDefinition)
1771
1846
  notify?.(`\u201C${row.definition.term}\u201D added to the Definitions section.`, "success");
1772
1847
  },
1773
- [editor, picker, run, notify]
1848
+ [editor, picker, run, attempt, track, notify]
1774
1849
  );
1775
1850
  const openPicker = React3.useCallback(
1776
1851
  (anchor) => {
@@ -2174,6 +2249,7 @@ function HouseTemplateProvider({
2174
2249
  children
2175
2250
  }) {
2176
2251
  const editor = react.useDocxEditor();
2252
+ const track = useTrackedOrNoted();
2177
2253
  const [template$1, setTemplate] = React3.useState(builtinHouseTemplate);
2178
2254
  const [divergence, setDivergence] = React3.useState(null);
2179
2255
  const [basedOnTemplate, setBasedOnTemplate] = React3.useState(false);
@@ -2214,11 +2290,18 @@ function HouseTemplateProvider({
2214
2290
  const fragment = template.buildingBlockFragment(template$1.bytes, name);
2215
2291
  if (!fragment) return false;
2216
2292
  try {
2217
- const result = withDirectEditing(
2218
- editor,
2219
- () => editor.exec({ type: "paste", text: "", html: template.fragmentClipboardHtml(fragment) })
2220
- );
2221
- if (!result.ok) throw new Error(result.reason ?? "The block could not be inserted here.");
2293
+ const result = track({
2294
+ label: `Inserted Quick Part: ${name}`,
2295
+ insert: (revision) => editor.exec({
2296
+ type: "paste",
2297
+ text: "",
2298
+ html: template.fragmentClipboardHtml(
2299
+ revision ? template.trackInsertion(fragment, revision, true) : fragment
2300
+ )
2301
+ }),
2302
+ inserted: (r) => r.ok
2303
+ })?.result;
2304
+ if (!result?.ok) throw new Error(result?.reason ?? "The block could not be inserted here.");
2222
2305
  refresh();
2223
2306
  return true;
2224
2307
  } catch (failure) {
@@ -2229,7 +2312,7 @@ function HouseTemplateProvider({
2229
2312
  return false;
2230
2313
  }
2231
2314
  },
2232
- [editor, editable, template$1, notify, refresh]
2315
+ [editor, editable, template$1, notify, refresh, track]
2233
2316
  );
2234
2317
  const setAsHouseTemplate = React3.useMemo(
2235
2318
  () => host?.setFromDocument && documentId ? async () => {
@@ -3264,7 +3347,7 @@ function NativeDocxEditor({
3264
3347
  if (change.source !== "load") changed();
3265
3348
  },
3266
3349
  onFontError: (e) => setError(e.message),
3267
- children: /* @__PURE__ */ jsxRuntime.jsx(
3350
+ children: /* @__PURE__ */ jsxRuntime.jsx(DocxAuthorContext.Provider, { value: ready.author, children: /* @__PURE__ */ jsxRuntime.jsx(
3268
3351
  DefinedTermsProvider,
3269
3352
  {
3270
3353
  load: adapter.definitions,
@@ -3337,7 +3420,7 @@ function NativeDocxEditor({
3337
3420
  }
3338
3421
  )
3339
3422
  }
3340
- )
3423
+ ) })
3341
3424
  }
3342
3425
  ) }, retry) }),
3343
3426
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-actions", children: [
@@ -3436,6 +3519,7 @@ exports.BUILTIN_TEMPLATE_NAME = BUILTIN_TEMPLATE_NAME;
3436
3519
  exports.DEFAULT_DEFINED_TERMS_LABELS = DEFAULT_DEFINED_TERMS_LABELS;
3437
3520
  exports.DEFINED_TERM_TRIGGER = DEFINED_TERM_TRIGGER;
3438
3521
  exports.DefinedTermsProvider = DefinedTermsProvider;
3522
+ exports.DocxAuthorContext = DocxAuthorContext;
3439
3523
  exports.DocxCommentActivity = DocxCommentActivity;
3440
3524
  exports.DocxEditorReview = DocxEditorReview;
3441
3525
  exports.DocxMentions = DocxMentions;
@@ -3452,12 +3536,15 @@ exports.loadDocxFonts = loadDocxFonts;
3452
3536
  exports.normalizeDocxExport = normalizeDocxExport;
3453
3537
  exports.resolveHouseTemplate = resolveHouseTemplate;
3454
3538
  exports.reviewModule = reviewModule;
3539
+ exports.structuralPort = structuralPort;
3455
3540
  exports.templateFileName = templateFileName;
3541
+ exports.trackedOrNoted = trackedOrNoted;
3456
3542
  exports.updateDefinitions = updateDefinitions;
3457
3543
  exports.useDefinedTerms = useDefinedTerms;
3458
3544
  exports.useHouseTemplate = useHouseTemplate;
3459
3545
  exports.useReview = useReview;
3460
3546
  exports.useReviewItem = useReviewItem;
3547
+ exports.useTrackedOrNoted = useTrackedOrNoted;
3461
3548
  exports.withDirectEditing = withDirectEditing;
3462
- //# sourceMappingURL=chunk-MIMVRMKC.cjs.map
3463
- //# sourceMappingURL=chunk-MIMVRMKC.cjs.map
3549
+ //# sourceMappingURL=chunk-44TPPPRJ.cjs.map
3550
+ //# sourceMappingURL=chunk-44TPPPRJ.cjs.map