@arbidocs/blocks 0.4.102 → 0.4.103

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.
@@ -6,7 +6,7 @@ import { collectReviewItems, revisionItemsOf } from '@docx-editor.dev/core/store
6
6
  import React3, { createContext, useContext, useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo, useSyncExternalStore } from 'react';
7
7
  import { useDocxEditor, ReviewRailContext, useEditorSnapshot, useEditorState, useChromeTranslate, DocxEditor, createFontSource, useParagraphStyle, normalizeImageBytes, usePageSetup, useEditorCommand } from '@docx-editor.dev/react';
8
8
  import { AiMarkdown, Dialog, DialogContent, DialogHeader, DialogTitle, cn, splitMarkdownBlocks } from '@arbidocs/react/ui';
9
- import { MessageSquarePlus, MessageSquare, PencilLine, ChevronLeft, ChevronRight, X, ChevronUp, ChevronDown, CheckCheck, RotateCcw, CircleCheck, Trash2, Check, SendHorizontal, Loader2, Sparkles, Type, Ellipsis, RefreshCw, WifiOff, Download, Save, BookA, Blocks, Superscript, NotebookText, Columns2, Settings2, BetweenHorizontalStart, BetweenHorizontalEnd, BetweenVerticalStart, BetweenVerticalEnd, Merge, Split, Heading, AlignVerticalJustifyStart, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, RotateCw, FlipHorizontal2, FlipVertical2, Scaling, RectangleVertical, RectangleHorizontal, FileText, SeparatorHorizontal, Captions } from 'lucide-react';
9
+ import { MessageSquarePlus, MessageSquare, PencilLine, ChevronLeft, ChevronRight, X, ChevronUp, ChevronDown, CheckCheck, RotateCcw, CircleCheck, Trash2, Check, SendHorizontal, Loader2, Sparkles, Type, Pilcrow, UsersRound, RefreshCw, WifiOff, Download, Save, Ellipsis, BookA, Blocks, Superscript, NotebookText, Columns2, Settings2, BetweenHorizontalStart, BetweenHorizontalEnd, BetweenVerticalStart, BetweenVerticalEnd, Merge, Split, Heading, AlignVerticalJustifyStart, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, RotateCw, FlipHorizontal2, FlipVertical2, Scaling, RectangleVertical, RectangleHorizontal, FileText, SeparatorHorizontal, Captions } from 'lucide-react';
10
10
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { defaultLegalTemplate, listBuildingBlocks, attachedTemplateOf, linkedLevelStyles, styleDivergence, buildingBlockFragment, fragmentClipboardHtml, trackInsertion, newFromTemplate } from '@arbidocs/coedit/template';
@@ -2169,7 +2169,9 @@ function RibbonMenu({
2169
2169
  children,
2170
2170
  className,
2171
2171
  testId,
2172
- title
2172
+ title,
2173
+ keepMounted = false,
2174
+ popoverClassName
2173
2175
  }) {
2174
2176
  const [open, setOpen] = useState(false);
2175
2177
  const element = useRef(null);
@@ -2203,12 +2205,13 @@ function RibbonMenu({
2203
2205
  children: icon
2204
2206
  }
2205
2207
  ),
2206
- open && /* @__PURE__ */ jsx(
2208
+ (open || keepMounted) && /* @__PURE__ */ jsx(
2207
2209
  "div",
2208
2210
  {
2209
- className: "native-docx-ribbon-popover",
2211
+ className: ["native-docx-ribbon-popover", popoverClassName].filter(Boolean).join(" "),
2210
2212
  role: "group",
2211
2213
  "aria-label": label,
2214
+ hidden: !open,
2212
2215
  onMouseDown: (event) => {
2213
2216
  if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
2214
2217
  event.preventDefault();
@@ -2486,6 +2489,163 @@ var WordDraftStream = class {
2486
2489
  }
2487
2490
  };
2488
2491
 
2492
+ // src/docx/overflowPlan.ts
2493
+ function planOverflow(items, available, moreWidth) {
2494
+ const collapsed = /* @__PURE__ */ new Set();
2495
+ let used = items.reduce((sum, item) => sum + item.width, 0);
2496
+ if (used <= available) return collapsed;
2497
+ used += moreWidth;
2498
+ const order = items.map((item, index) => ({ item, index })).sort((a, b) => a.item.priority - b.item.priority || b.index - a.index);
2499
+ for (const { item } of order) {
2500
+ if (used <= available) break;
2501
+ collapsed.add(item.id);
2502
+ used -= item.width;
2503
+ }
2504
+ return collapsed;
2505
+ }
2506
+ var Overflow = createContext(null);
2507
+ var MORE_WIDTH = 32;
2508
+ var sameSet = (a, b) => a.size === b.size && [...a].every((id) => b.has(id));
2509
+ function RibbonOverflow({ tab, children }) {
2510
+ const row = useRef(null);
2511
+ const items = useRef(/* @__PURE__ */ new Map());
2512
+ const widths = useRef(/* @__PURE__ */ new Map());
2513
+ const [version, setVersion] = useState(0);
2514
+ const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
2515
+ const [slots, setSlots] = useState({});
2516
+ const [menu, setMenu] = useState([]);
2517
+ const register = useCallback((id, item) => {
2518
+ items.current.set(id, item);
2519
+ setVersion((v) => v + 1);
2520
+ return () => {
2521
+ if (items.current.get(id) === item) items.current.delete(id);
2522
+ setVersion((v) => v + 1);
2523
+ };
2524
+ }, []);
2525
+ const plan = useCallback(() => {
2526
+ const element = row.current;
2527
+ if (!element) return;
2528
+ const gap = parseFloat(getComputedStyle(element).columnGap) || 0;
2529
+ const ordered = Array.from(element.querySelectorAll("[data-ribbon-item]")).map((node) => node.dataset.ribbonItem).filter((id) => items.current.has(id));
2530
+ const measured = ordered.map((id) => {
2531
+ const { element: node, priority } = items.current.get(id);
2532
+ if (!node.hidden) {
2533
+ const width = node.getBoundingClientRect().width;
2534
+ widths.current.set(id, width ? width + gap : 0);
2535
+ }
2536
+ return { id, priority, width: widths.current.get(id) ?? 0 };
2537
+ });
2538
+ const next = planOverflow(measured, element.clientWidth, MORE_WIDTH);
2539
+ setCollapsed((current) => sameSet(current, next) ? current : next);
2540
+ const entries = ordered.filter((id) => next.has(id)).map((id) => ({ id, label: items.current.get(id).label }));
2541
+ setMenu(
2542
+ (current) => current.length === entries.length && current.every((entry, i) => entry.id === entries[i].id && entry.label === entries[i].label) ? current : entries
2543
+ );
2544
+ }, []);
2545
+ useLayoutEffect(plan, [plan, version, tab, collapsed]);
2546
+ useLayoutEffect(() => {
2547
+ const element = row.current;
2548
+ if (!element) return;
2549
+ const observer = new ResizeObserver(() => plan());
2550
+ observer.observe(element);
2551
+ for (const item of items.current.values()) observer.observe(item.element);
2552
+ return () => observer.disconnect();
2553
+ }, [plan, version]);
2554
+ const slotRef = useCallback(
2555
+ (id) => (node) => setSlots((current) => {
2556
+ if (node ? current[id] === node : !(id in current)) return current;
2557
+ const next = { ...current };
2558
+ if (node) next[id] = node;
2559
+ else delete next[id];
2560
+ return next;
2561
+ }),
2562
+ []
2563
+ );
2564
+ const context = useMemo(() => ({ collapsed, slots, register }), [collapsed, slots, register]);
2565
+ const shown = menu.filter((entry) => collapsed.has(entry.id));
2566
+ return /* @__PURE__ */ jsx(Overflow.Provider, { value: context, children: /* @__PURE__ */ jsxs("div", { className: "native-docx-ribbon-row", ref: row, "data-testid": "docx-ribbon-row", children: [
2567
+ children,
2568
+ shown.length > 0 && /* @__PURE__ */ jsx(
2569
+ RibbonMenu,
2570
+ {
2571
+ label: "More",
2572
+ title: "More commands",
2573
+ icon: /* @__PURE__ */ jsx(Ellipsis, { size: 16 }),
2574
+ testId: "docx-ribbon-more",
2575
+ keepMounted: true,
2576
+ popoverClassName: "native-docx-ribbon-more",
2577
+ children: (close) => /* @__PURE__ */ jsx(MoreRows, { entries: shown, slotRef, close })
2578
+ },
2579
+ tab
2580
+ )
2581
+ ] }) });
2582
+ }
2583
+ function MoreRows({
2584
+ entries,
2585
+ slotRef,
2586
+ close
2587
+ }) {
2588
+ const refs = useRef(/* @__PURE__ */ new Map());
2589
+ const refFor = (id) => {
2590
+ let ref = refs.current.get(id);
2591
+ if (!ref) refs.current.set(id, ref = slotRef(id));
2592
+ return ref;
2593
+ };
2594
+ const list = useRef(null);
2595
+ const latest = useRef(close);
2596
+ latest.current = close;
2597
+ useEffect(() => {
2598
+ const element = list.current;
2599
+ if (!element) return;
2600
+ const onClick = (event) => {
2601
+ const target = event.target;
2602
+ const row = target.closest(".native-docx-ribbon-more-row");
2603
+ if (!row) return;
2604
+ const control = row.querySelector(".native-docx-ribbon-more-control");
2605
+ if (!control.contains(target)) {
2606
+ control.querySelector("button:not([disabled])")?.click();
2607
+ return;
2608
+ }
2609
+ const button = target.closest("button");
2610
+ if (button && !button.disabled && !control.querySelector(".native-docx-ribbon-popover")?.contains(button) && !button.hasAttribute("aria-expanded") && !button.hasAttribute("aria-haspopup"))
2611
+ latest.current();
2612
+ };
2613
+ element.addEventListener("click", onClick, true);
2614
+ return () => element.removeEventListener("click", onClick, true);
2615
+ }, []);
2616
+ return /* @__PURE__ */ jsx("div", { className: "native-docx-ribbon-more-list", ref: list, children: entries.map((entry) => /* @__PURE__ */ jsxs("div", { className: "native-docx-ribbon-more-row", "data-ribbon-more": entry.id, children: [
2617
+ /* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-more-control", ref: refFor(entry.id) }),
2618
+ /* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-more-label", children: entry.label })
2619
+ ] }, entry.id)) });
2620
+ }
2621
+ function RibbonItem({
2622
+ id,
2623
+ label,
2624
+ priority = 0,
2625
+ children
2626
+ }) {
2627
+ const context = useContext(Overflow);
2628
+ const element = useRef(null);
2629
+ const register = context?.register;
2630
+ useLayoutEffect(() => {
2631
+ if (!register || !element.current) return;
2632
+ return register(id, { label, priority, element: element.current });
2633
+ }, [register, id, label, priority]);
2634
+ if (!context) return /* @__PURE__ */ jsx(Fragment, { children });
2635
+ const collapsed = context.collapsed.has(id);
2636
+ const slot = context.slots[id];
2637
+ return /* @__PURE__ */ jsx(
2638
+ "span",
2639
+ {
2640
+ ref: element,
2641
+ className: "native-docx-ribbon-item",
2642
+ "data-ribbon-item": id,
2643
+ hidden: collapsed || void 0,
2644
+ children: collapsed ? slot ? createPortal(children, slot) : null : children
2645
+ }
2646
+ );
2647
+ }
2648
+
2489
2649
  // src/docx/wordStyles.ts
2490
2650
  var QUICK_STYLES = ["Normal", "Title", "heading 1", "heading 2", "heading 3"];
2491
2651
  function findStyle(options, name) {
@@ -2671,18 +2831,87 @@ function StyleGallery() {
2671
2831
  }
2672
2832
  );
2673
2833
  }
2834
+ var W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
2835
+ var DEFAULT_PARAGRAPH_FONT = {
2836
+ id: "DefaultParagraphFont",
2837
+ type: "character",
2838
+ xml: '<w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont"><w:name w:val="Default Paragraph Font"/><w:uiPriority w:val="1"/><w:semiHidden/><w:unhideWhenUsed/></w:style>'
2839
+ };
2840
+ function stylesOf(kind) {
2841
+ const Kind = kind === "footnote" ? "Footnote" : "Endnote";
2842
+ const text = `${Kind}Text`;
2843
+ return [
2844
+ {
2845
+ id: text,
2846
+ type: "paragraph",
2847
+ xml: `<w:style w:type="paragraph" w:styleId="${text}"><w:name w:val="${kind} text"/><w:basedOn w:val="Normal"/><w:link w:val="${text}Char"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:pPr><w:spacing w:after="0" w:line="240" w:lineRule="auto"/></w:pPr><w:rPr><w:sz w:val="20"/><w:szCs w:val="20"/></w:rPr></w:style>`
2848
+ },
2849
+ {
2850
+ id: `${text}Char`,
2851
+ type: "character",
2852
+ xml: `<w:style w:type="character" w:customStyle="1" w:styleId="${text}Char"><w:name w:val="${Kind} Text Char"/><w:basedOn w:val="DefaultParagraphFont"/><w:link w:val="${text}"/><w:uiPriority w:val="99"/><w:semiHidden/><w:rPr><w:sz w:val="20"/><w:szCs w:val="20"/></w:rPr></w:style>`
2853
+ },
2854
+ {
2855
+ id: `${Kind}Reference`,
2856
+ type: "character",
2857
+ xml: `<w:style w:type="character" w:styleId="${Kind}Reference"><w:name w:val="${kind} reference"/><w:basedOn w:val="DefaultParagraphFont"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:rPr><w:vertAlign w:val="superscript"/></w:rPr></w:style>`
2858
+ }
2859
+ ];
2860
+ }
2861
+ function noteTextStyle(styles, kind) {
2862
+ const paragraph = styles.filter((style) => style.type === "paragraph");
2863
+ const id = kind === "footnote" ? "FootnoteText" : "EndnoteText";
2864
+ return paragraph.find((style) => style.name.toLowerCase() === `${kind} text`)?.styleId ?? paragraph.find((style) => style.styleId === id)?.styleId;
2865
+ }
2866
+ function missingNoteStyles(styles, kind) {
2867
+ const has = (type, id) => styles.some((style) => style.type === type && style.styleId === id);
2868
+ const text = noteTextStyle(styles, kind);
2869
+ const missing = stylesOf(kind).filter(
2870
+ (style) => style.type === "paragraph" ? !text : !has("character", style.id)
2871
+ );
2872
+ if (!missing.length) return [];
2873
+ const base = has("character", DEFAULT_PARAGRAPH_FONT.id) ? [] : [DEFAULT_PARAGRAPH_FONT];
2874
+ return [...base, ...missing].map((style) => style.xml);
2875
+ }
2876
+ var CONTENT_TYPES = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/><Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/></Types>';
2877
+ function stylesOnlyClipboardHtml(styles) {
2878
+ const fragment = zipSync({
2879
+ "[Content_Types].xml": strToU8(CONTENT_TYPES),
2880
+ "_rels/.rels": strToU8(
2881
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>'
2882
+ ),
2883
+ "word/document.xml": strToU8(
2884
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2885
+ <w:document xmlns:w="${W}"><w:body><w:p/></w:body></w:document>`
2886
+ ),
2887
+ "word/_rels/document.xml.rels": strToU8(
2888
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rIdStyles" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships>'
2889
+ ),
2890
+ "word/styles.xml": strToU8(
2891
+ `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2892
+ <w:styles xmlns:w="${W}">${styles.join("")}</w:styles>`
2893
+ )
2894
+ });
2895
+ return fragmentClipboardHtml(fragment, false);
2896
+ }
2897
+ function ensureNoteStyles(editor, kind, direct = (fn) => fn()) {
2898
+ if (!editor.can({ type: "insertNote", noteKind: kind }).ok) return void 0;
2899
+ const missing = missingNoteStyles(editor.getDocumentStyles(), kind);
2900
+ if (missing.length)
2901
+ direct(() => editor.exec({ type: "paste", text: "", html: stylesOnlyClipboardHtml(missing) }));
2902
+ return noteTextStyle(editor.getDocumentStyles(), kind);
2903
+ }
2674
2904
  function useInsertNote(kind) {
2675
2905
  const command = useEditorCommand(kind === "footnote" ? "insert.footnote" : "insert.endnote");
2676
- const { options } = useParagraphStyle();
2677
2906
  const editor = useDocxEditor();
2678
2907
  const insert = () => {
2908
+ const text = editor && ensureNoteStyles(editor, kind, (fn) => withDirectEditing(editor, fn));
2679
2909
  if (!command.execute()) return false;
2680
- const text = findStyle(options, `${kind} text`);
2681
- if (text && editor)
2682
- withDirectEditing(
2683
- editor,
2684
- () => editor.exec({ type: "setParagraphStyle", styleId: text.styleId })
2685
- );
2910
+ if (editor) {
2911
+ if (text)
2912
+ withDirectEditing(editor, () => editor.exec({ type: "setParagraphStyle", styleId: text }));
2913
+ editor.exec({ type: "insertText", text: " " });
2914
+ }
2686
2915
  return true;
2687
2916
  };
2688
2917
  return { insert, isEnabled: command.isEnabled, disabledReason: command.disabledReason };
@@ -2694,7 +2923,7 @@ function NoteAction({
2694
2923
  icon
2695
2924
  }) {
2696
2925
  const note = useInsertNote(kind);
2697
- return /* @__PURE__ */ jsx(
2926
+ return /* @__PURE__ */ jsx(RibbonItem, { id: `references-${kind}`, label, children: /* @__PURE__ */ jsx(
2698
2927
  DocxEditor.Toolbar.Action,
2699
2928
  {
2700
2929
  label: `${label} (${shortcut})`,
@@ -2704,7 +2933,7 @@ function NoteAction({
2704
2933
  onSelect: () => void note.insert(),
2705
2934
  className: `native-docx-insert-${kind}`
2706
2935
  }
2707
- );
2936
+ ) });
2708
2937
  }
2709
2938
  function NoteButtons() {
2710
2939
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -2989,10 +3218,10 @@ function LayoutButtons() {
2989
3218
  const [dialog, setDialog] = useState(false);
2990
3219
  const props = { setup: pageSetup, apply, openDialog: () => setDialog(true) };
2991
3220
  return /* @__PURE__ */ jsxs(Fragment, { children: [
2992
- /* @__PURE__ */ jsx(Margins, { ...props }),
2993
- /* @__PURE__ */ jsx(Orientation, { ...props }),
2994
- /* @__PURE__ */ jsx(Size, { ...props }),
2995
- /* @__PURE__ */ jsx(
3221
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-margins", label: "Margins", children: /* @__PURE__ */ jsx(Margins, { ...props }) }),
3222
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-orientation", label: "Orientation", children: /* @__PURE__ */ jsx(Orientation, { ...props }) }),
3223
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-size", label: "Size", children: /* @__PURE__ */ jsx(Size, { ...props }) }),
3224
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-columns", label: "Columns", children: /* @__PURE__ */ jsx(
2996
3225
  DocxEditor.Toolbar.Action,
2997
3226
  {
2998
3227
  label: "Columns",
@@ -3001,9 +3230,9 @@ function LayoutButtons() {
3001
3230
  disabledReason: COLUMNS_UNSUPPORTED,
3002
3231
  className: "native-docx-layout-columns"
3003
3232
  }
3004
- ),
3005
- /* @__PURE__ */ jsx(Breaks, {}),
3006
- /* @__PURE__ */ jsx(
3233
+ ) }),
3234
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-breaks", label: "Breaks", children: /* @__PURE__ */ jsx(Breaks, {}) }),
3235
+ /* @__PURE__ */ jsx(RibbonItem, { id: "layout-page-setup", label: "Page Setup\u2026", children: /* @__PURE__ */ jsx(
3007
3236
  DocxEditor.Toolbar.Action,
3008
3237
  {
3009
3238
  label: "Page Setup\u2026",
@@ -3011,7 +3240,7 @@ function LayoutButtons() {
3011
3240
  onSelect: () => setDialog(true),
3012
3241
  className: "native-docx-layout-page-setup"
3013
3242
  }
3014
- ),
3243
+ ) }),
3015
3244
  /* @__PURE__ */ jsx(DocxEditor.PageSetupDialog, { open: dialog, onClose: () => setDialog(false) })
3016
3245
  ] });
3017
3246
  }
@@ -3038,7 +3267,7 @@ function CommandGallery({
3038
3267
  rows
3039
3268
  }) {
3040
3269
  const bound = useRows(rows);
3041
- return /* @__PURE__ */ jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsx(
3270
+ return /* @__PURE__ */ jsx(RibbonItem, { id: testId, label, children: /* @__PURE__ */ jsx(RibbonMenu, { label, icon, testId, children: (close) => /* @__PURE__ */ jsx(
3042
3271
  RibbonGallery,
3043
3272
  {
3044
3273
  label,
@@ -3052,7 +3281,7 @@ function CommandGallery({
3052
3281
  })),
3053
3282
  onPick: (id) => void bound.find((row) => row.id === id)?.state.execute()
3054
3283
  }
3055
- ) });
3284
+ ) }) });
3056
3285
  }
3057
3286
  function CommandAction({
3058
3287
  command,
@@ -3061,7 +3290,7 @@ function CommandAction({
3061
3290
  testId
3062
3291
  }) {
3063
3292
  const state = useEditorCommand(command);
3064
- return /* @__PURE__ */ jsx(
3293
+ return /* @__PURE__ */ jsx(RibbonItem, { id: `table-${testId}`, label, children: /* @__PURE__ */ jsx(
3065
3294
  DocxEditor.Toolbar.Action,
3066
3295
  {
3067
3296
  label,
@@ -3072,7 +3301,7 @@ function CommandAction({
3072
3301
  onSelect: () => void state.execute(),
3073
3302
  className: `native-docx-table-${testId}`
3074
3303
  }
3075
- );
3304
+ ) });
3076
3305
  }
3077
3306
  function TableButtons() {
3078
3307
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -3172,11 +3401,11 @@ function TableButtons() {
3172
3401
  ]
3173
3402
  }
3174
3403
  ),
3175
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderTarget, {}),
3176
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderStyle, {}),
3177
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderWidth, {}),
3178
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderColor, {}),
3179
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, {})
3404
+ /* @__PURE__ */ jsx(RibbonItem, { id: "table-border-target", label: "Borders", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderTarget, {}) }),
3405
+ /* @__PURE__ */ jsx(RibbonItem, { id: "table-border-style", label: "Border style", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderStyle, {}) }),
3406
+ /* @__PURE__ */ jsx(RibbonItem, { id: "table-border-width", label: "Border width", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderWidth, {}) }),
3407
+ /* @__PURE__ */ jsx(RibbonItem, { id: "table-border-color", label: "Border color", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableBorderColor, {}) }),
3408
+ /* @__PURE__ */ jsx(RibbonItem, { id: "table-cell-fill", label: "Shading", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, {}) })
3180
3409
  ] });
3181
3410
  }
3182
3411
  var CAPTION_LABELS = ["Figure", "Table", "Equation"];
@@ -3239,7 +3468,7 @@ function TransformAction({
3239
3468
  icon
3240
3469
  }) {
3241
3470
  const state = useEditorCommand(TRANSFORMS[action]);
3242
- return /* @__PURE__ */ jsx(
3471
+ return /* @__PURE__ */ jsx(RibbonItem, { id: `picture-${action}`, label, children: /* @__PURE__ */ jsx(
3243
3472
  DocxEditor.Toolbar.Action,
3244
3473
  {
3245
3474
  label,
@@ -3249,7 +3478,7 @@ function TransformAction({
3249
3478
  onSelect: () => void state.execute(),
3250
3479
  className: `native-docx-picture-${action}`
3251
3480
  }
3252
- );
3481
+ ) });
3253
3482
  }
3254
3483
  function insertCaption(editor, label, text, track) {
3255
3484
  const surface = editor.surface;
@@ -3347,9 +3576,9 @@ function CaptionButton({ defaultLabel = "Figure" }) {
3347
3576
  }
3348
3577
  function PictureButtons() {
3349
3578
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3350
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageWrap, {}),
3351
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageProperties, {}),
3352
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageAltText, {}),
3579
+ /* @__PURE__ */ jsx(RibbonItem, { id: "picture-wrap", label: "Wrap text", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageWrap, {}) }),
3580
+ /* @__PURE__ */ jsx(RibbonItem, { id: "picture-properties", label: "Size and position", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageProperties, {}) }),
3581
+ /* @__PURE__ */ jsx(RibbonItem, { id: "picture-alt-text", label: "Alt text", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageAltText, {}) }),
3353
3582
  /* @__PURE__ */ jsx(TransformAction, { action: "rotateCW", label: "Rotate right 90\xB0", icon: /* @__PURE__ */ jsx(RotateCw, { size: 16 }) }),
3354
3583
  /* @__PURE__ */ jsx(TransformAction, { action: "rotateCCW", label: "Rotate left 90\xB0", icon: /* @__PURE__ */ jsx(RotateCcw, { size: 16 }) }),
3355
3584
  /* @__PURE__ */ jsx(
@@ -3361,7 +3590,7 @@ function PictureButtons() {
3361
3590
  }
3362
3591
  ),
3363
3592
  /* @__PURE__ */ jsx(TransformAction, { action: "flipV", label: "Flip vertical", icon: /* @__PURE__ */ jsx(FlipVertical2, { size: 16 }) }),
3364
- /* @__PURE__ */ jsx(CaptionButton, {})
3593
+ /* @__PURE__ */ jsx(RibbonItem, { id: "picture-caption", label: "Insert caption", children: /* @__PURE__ */ jsx(CaptionButton, {}) })
3365
3594
  ] });
3366
3595
  }
3367
3596
  var LAYOUT_TAB = "Layout";
@@ -3624,46 +3853,48 @@ function DocxRibbon({
3624
3853
  /* @__PURE__ */ jsx(DocxEditor.Toolbar.Undo, {}),
3625
3854
  /* @__PURE__ */ jsx(DocxEditor.Toolbar.Redo, {}),
3626
3855
  /* @__PURE__ */ jsx(DocxEditor.Toolbar.Save, {}),
3627
- tab === "Home" && /* @__PURE__ */ jsxs(Fragment, { children: [
3628
- /* @__PURE__ */ jsx(StyleGallery, {}),
3629
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Bold, {}),
3630
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Italic, {}),
3631
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Underline, {}),
3632
- /* @__PURE__ */ jsxs(RibbonMenu, { label: "Font", icon: /* @__PURE__ */ jsx(Type, { size: 16 }), children: [
3633
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontFamily, {}),
3634
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontSize, {}),
3635
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontColor, {}),
3636
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Highlight, {})
3856
+ /* @__PURE__ */ jsxs(RibbonOverflow, { tab, children: [
3857
+ tab === "Home" && /* @__PURE__ */ jsxs(Fragment, { children: [
3858
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-style", label: "Styles", priority: 80, children: /* @__PURE__ */ jsx(StyleGallery, {}) }),
3859
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-bold", label: "Bold", priority: 100, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Bold, {}) }),
3860
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-italic", label: "Italic", priority: 95, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Italic, {}) }),
3861
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-underline", label: "Underline", priority: 90, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Underline, {}) }),
3862
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-font", label: "Font", priority: 60, children: /* @__PURE__ */ jsxs(RibbonMenu, { label: "Font", icon: /* @__PURE__ */ jsx(Type, { size: 16 }), children: [
3863
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontFamily, {}),
3864
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontSize, {}),
3865
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.FontColor, {}),
3866
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.Highlight, {})
3867
+ ] }) }),
3868
+ /* @__PURE__ */ jsx(RibbonItem, { id: "home-more-formatting", label: "More formatting", priority: 50, children: /* @__PURE__ */ jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsx(Pilcrow, { size: 16 }), children: [
3869
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.Alignment, {}),
3870
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.BulletList, {}),
3871
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.NumberedList, {}),
3872
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.LineSpacing, {}),
3873
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.Indent, {}),
3874
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.Outdent, {}),
3875
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.Strike, {}),
3876
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.ClearFormatting, {})
3877
+ ] }) })
3878
+ ] }),
3879
+ tab === "Insert" && /* @__PURE__ */ jsxs(Fragment, { children: [
3880
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-table", label: "Table", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableInsert, {}) }),
3881
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-picture", label: "Picture", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageInsert, {}) }),
3882
+ imageGeneration && /* @__PURE__ */ jsx(RibbonItem, { id: "insert-generate-image", label: "Generate image", children: /* @__PURE__ */ jsx(GenerateImageButton, { generation: imageGeneration }) }),
3883
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-page-break", label: "Page break", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }) }),
3884
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-link", label: "Link", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Link, {}) }),
3885
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-defined-term", label: "Defined term", children: /* @__PURE__ */ jsx(DefinedTermButtons, {}) }),
3886
+ /* @__PURE__ */ jsx(RibbonItem, { id: "insert-quick-parts", label: "Quick Parts", children: /* @__PURE__ */ jsx(QuickParts, {}) })
3637
3887
  ] }),
3638
- /* @__PURE__ */ jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsx(Ellipsis, { size: 16 }), children: [
3639
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Alignment, {}),
3640
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.BulletList, {}),
3641
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.NumberedList, {}),
3642
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.LineSpacing, {}),
3643
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Indent, {}),
3644
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Outdent, {}),
3645
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Strike, {}),
3646
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.ClearFormatting, {})
3888
+ /* @__PURE__ */ jsx(LayoutTabContent, { tab }),
3889
+ tab === "Design" && /* @__PURE__ */ jsx(RibbonItem, { id: "design-house-template", label: "House template", children: /* @__PURE__ */ jsx(HouseTemplatePanel, {}) }),
3890
+ tab === "References" && /* @__PURE__ */ jsx(NoteButtons, {}),
3891
+ tab === "Review" && /* @__PURE__ */ jsxs(Fragment, { children: [
3892
+ /* @__PURE__ */ jsx(RibbonItem, { id: "review-editing-mode", label: "Editing mode", priority: 10, children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.EditingMode, {}) }),
3893
+ /* @__PURE__ */ jsx(RibbonItem, { id: "review-comments", label: "Comments", children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Comments, {}) }),
3894
+ /* @__PURE__ */ jsx(RibbonItem, { id: "review-options", label: "Review options", children: /* @__PURE__ */ jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsx(UsersRound, { size: 16 }), children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Reviewers, {}) }) })
3647
3895
  ] })
3648
3896
  ] }),
3649
- tab === "Insert" && /* @__PURE__ */ jsxs(Fragment, { children: [
3650
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableInsert, {}),
3651
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.ImageInsert, {}),
3652
- imageGeneration && /* @__PURE__ */ jsx(GenerateImageButton, { generation: imageGeneration }),
3653
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Button, { slotId: "insert.pageBreak" }),
3654
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Link, {}),
3655
- /* @__PURE__ */ jsx(DefinedTermButtons, {}),
3656
- /* @__PURE__ */ jsx(QuickParts, {})
3657
- ] }),
3658
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, { hidden: true }),
3659
- /* @__PURE__ */ jsx(LayoutTabContent, { tab }),
3660
- tab === "Design" && /* @__PURE__ */ jsx(HouseTemplatePanel, {}),
3661
- tab === "References" && /* @__PURE__ */ jsx(NoteButtons, {}),
3662
- tab === "Review" && /* @__PURE__ */ jsxs(Fragment, { children: [
3663
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.EditingMode, {}),
3664
- /* @__PURE__ */ jsx(DocxEditor.Toolbar.Comments, {}),
3665
- /* @__PURE__ */ jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsx(Ellipsis, { size: 16 }), children: /* @__PURE__ */ jsx(DocxEditor.Toolbar.Reviewers, {}) })
3666
- ] })
3897
+ /* @__PURE__ */ jsx(DocxEditor.Toolbar.TableCellFill, { hidden: true })
3667
3898
  ] }),
3668
3899
  badge && /* @__PURE__ */ jsx("span", { className: "native-docx-ribbon-badge", "data-testid": "docx-ribbon-badge", children: badge })
3669
3900
  ] });
@@ -4177,5 +4408,5 @@ async function loadFonts(baseUrl) {
4177
4408
  }
4178
4409
 
4179
4410
  export { BUILTIN_TEMPLATE_NAME, DEFAULT_DEFINED_TERMS_LABELS, DEFINED_TERM_TRIGGER, DefinedTermsProvider, DocxAuthorContext, DocxCommentActivity, DocxEditorReview, DocxMentions, DocxParticipants, DocxRibbon, GenerateImageButton, HouseTemplateProvider, NativeDocxEditor, builtinHouseTemplate, contentPath, editorPort, findDefinitionsSection, insertDefinedTerm, loadDocxFonts, normalizeDocxExport, resolveHouseTemplate, reviewModule, structuralPort, templateFileName, trackedOrNoted, useDefinedTerms, useHouseTemplate, useReview, useReviewItem, useTrackedOrNoted, withDirectEditing };
4180
- //# sourceMappingURL=chunk-MYALCKDR.js.map
4181
- //# sourceMappingURL=chunk-MYALCKDR.js.map
4411
+ //# sourceMappingURL=chunk-CVYY4X5R.js.map
4412
+ //# sourceMappingURL=chunk-CVYY4X5R.js.map