superdoc 2.18.1-next.5 → 2.19.0-next.2
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/chunks/{create-super-doc-ui-C3HDE1IE.es.js → create-super-doc-ui-BFJ9Y0YV.cjs} +1396 -1
- package/dist/chunks/{create-super-doc-ui-Gxk1m05U.cjs → create-super-doc-ui-Dfw1b6h_.es.js} +1318 -66
- package/dist/collaboration-upgrade-engine.cjs +1 -1
- package/dist/collaboration-upgrade-engine.es.js +1 -1
- package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
- package/dist/document-api/src/contract/operation-definitions.d.ts +9 -0
- package/dist/document-api/src/index.d.ts +1 -0
- package/dist/document-api/src/types/track-changes.types.d.ts +35 -2
- package/dist/document-api/src/validation-primitives.d.ts +1 -1
- package/dist/document-api/src/watermarks/watermarks.d.ts +4 -1
- package/dist/document-api/src/watermarks/watermarks.types.d.ts +34 -0
- package/dist/layout-engine/painters/dom/src/index.d.ts +2 -0
- package/dist/public/ui-react.cjs +1 -1
- package/dist/public/ui-react.es.js +1 -1
- package/dist/public/ui-vue.cjs +1 -1
- package/dist/public/ui-vue.es.js +1 -1
- package/dist/public/ui.cjs +1 -1
- package/dist/public/ui.es.js +1 -1
- package/dist/style.css +596 -80
- package/dist/style.layered.css +597 -81
- package/dist/superdoc/src/components/surfaces/WatermarkSurface.vue.d.ts +16 -0
- package/dist/superdoc/src/components/surfaces/watermark-surface-runtime.d.ts +8 -0
- package/dist/superdoc/src/core/SuperDoc.d.ts +8 -7
- package/dist/superdoc/src/core/types/index.d.ts +36 -18
- package/dist/superdoc/src/internal/toolbar/built-in/OverflowMenu.vue.d.ts +93 -1
- package/dist/superdoc/src/internal/toolbar/built-in/Toolbar.vue.d.ts +3 -1
- package/dist/superdoc/src/internal/toolbar/built-in/ToolbarDropdown.vue.d.ts +1 -0
- package/dist/superdoc/src/internal/toolbar/built-in/toolbarIcons.d.ts +1 -0
- package/dist/superdoc/src/internal/toolbar/built-in/toolbarTexts.d.ts +1 -0
- package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +3 -0
- package/dist/superdoc/src/public/ui/types.d.ts +10 -1
- package/dist/superdoc/src/public/ui/watermark-controller.d.ts +32 -0
- package/dist/superdoc/src/public/ui/watermark-dialog-state.d.ts +66 -0
- package/dist/superdoc/src/public/ui/watermark-draft.d.ts +6 -0
- package/dist/superdoc/src/public/ui.d.cts +12 -0
- package/dist/superdoc/src/public/ui.d.ts +1 -1
- package/dist/superdoc.cjs +110 -174
- package/dist/superdoc.es.js +108 -172
- package/dist-cdn/style.layered.css +1 -1
- package/dist-cdn/superdoc.min.css +1 -1
- package/dist-cdn/superdoc.min.js +38 -37
- package/package.json +2 -2
package/dist/superdoc.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as __toESM$2 } from "./chunks/rolldown-runtime-0pSA04fp.es.js";
|
|
2
2
|
import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
|
|
3
|
-
import { a as applyV2CommentInvalidationFromMutation, c as
|
|
3
|
+
import { a as applyV2CommentInvalidationFromMutation, c as resolveImageSrc, d as closeInteractionHistory, f as createInteractionHistory, n as executeFirstPartyCommandAsync, o as getV2TrackedChangeMutationImpact, p as recordInteraction, r as registerFirstPartyCommandMutation, s as createImageFilePicker, t as createSuperDocUI, u as DOM_CLASS_NAMES } from "./chunks/create-super-doc-ui-Dfw1b6h_.es.js";
|
|
4
4
|
import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
|
|
5
5
|
import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
|
|
6
6
|
import { a as init_dist$1, i as global, n as init_dist$2, o as Buffer, r as process$1, s as init_dist, t as require_jszip_min } from "./chunks/jszip-BzJ3CyxR.es.js";
|
|
@@ -315,7 +315,7 @@ var shuffleArray = (array) => {
|
|
|
315
315
|
var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
|
|
316
316
|
function getSuperdocVersion() {
|
|
317
317
|
try {
|
|
318
|
-
return "2.
|
|
318
|
+
return "2.19.0-next.2";
|
|
319
319
|
} catch {
|
|
320
320
|
return "unknown";
|
|
321
321
|
}
|
|
@@ -5455,13 +5455,13 @@ function resolveProviderExtension(candidate) {
|
|
|
5455
5455
|
if (!adapterId) return {
|
|
5456
5456
|
ok: false,
|
|
5457
5457
|
reason: "invalid-adapter-id",
|
|
5458
|
-
message: "SuperDoc v2 provider extensions require a non-empty
|
|
5458
|
+
message: "SuperDoc v2 provider extensions require a non-empty collaboration.adapterId."
|
|
5459
5459
|
};
|
|
5460
5460
|
const documentId = normalizeNonEmptyString(candidate.documentId);
|
|
5461
5461
|
if (!documentId) return {
|
|
5462
5462
|
ok: false,
|
|
5463
5463
|
reason: "invalid-document-id",
|
|
5464
|
-
message: "SuperDoc v2 provider extensions require a non-empty
|
|
5464
|
+
message: "SuperDoc v2 provider extensions require a non-empty collaboration.documentId."
|
|
5465
5465
|
};
|
|
5466
5466
|
const roomMode = normalizeRoomMode(candidate.roomMode);
|
|
5467
5467
|
if (!roomMode) return invalidRoomMode();
|
|
@@ -18712,6 +18712,7 @@ var toolbarIcons = {
|
|
|
18712
18712
|
link: link_solid_default,
|
|
18713
18713
|
image: image_solid_default,
|
|
18714
18714
|
tableOfContents: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"96 96 448 448\"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d=\"M96 160C96 124.7 124.7 96 160 96L480 96C515.3 96 544 124.7 544 160L544 480C544 515.3 515.3 544 480 544L160 544C124.7 544 96 515.3 96 480L96 160zM160 160L160 224L224 224L224 160L160 160zM480 160L288 160L288 224L480 224L480 160zM160 288L160 352L224 352L224 288L160 288zM480 288L288 288L288 352L480 352L480 288zM160 416L160 480L224 480L224 416L160 416zM480 416L288 416L288 480L480 480L480 416z\"></path></svg>\n",
|
|
18715
|
+
watermark: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"16\" viewBox=\"0 0 384 512\"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M0 64C0 28.7 28.7 0 64 0L224 0l0 128c0 17.7 14.3 32 32 32l128 0 0 288c0 35.3-28.7 64-64 64L64 512c-35.3 0-64-28.7-64-64L0 64zm384 64l-128 0L256 0 384 128zM109.2 254.3L150.8 230.3L312.1 349.7L267.0 375.7L236.9 351.5L169.4 390.5L175.2 428.7L130.2 454.7ZM162.6 344.8L200.7 322.8L153.6 285.3Z\"/></svg>\n",
|
|
18715
18716
|
alignLeft: align_left_solid_default,
|
|
18716
18717
|
alignRight: align_right_solid_default,
|
|
18717
18718
|
alignCenter: align_center_solid_default,
|
|
@@ -21423,7 +21424,9 @@ var SurfaceDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21423
21424
|
}
|
|
21424
21425
|
}
|
|
21425
21426
|
function handleBackdropClick(event) {
|
|
21426
|
-
if (event.target
|
|
21427
|
+
if (event.target !== event.currentTarget) return;
|
|
21428
|
+
event.preventDefault();
|
|
21429
|
+
if (props.surface.request.closeOnBackdrop !== false) emit("close");
|
|
21427
21430
|
}
|
|
21428
21431
|
const shellProps = computed(() => ({
|
|
21429
21432
|
surfaceId: props.surface.id,
|
|
@@ -21499,7 +21502,7 @@ var SurfaceDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21499
21502
|
])) : __props.surface.component ? (openBlock(), createBlock(resolveDynamicComponent(__props.surface.component), normalizeProps(mergeProps({ key: 1 }, mergedComponentProps.value)), null, 16)) : createCommentVNode("", true)])], 12, _hoisted_1$18)], 32);
|
|
21500
21503
|
};
|
|
21501
21504
|
}
|
|
21502
|
-
}, [["__scopeId", "data-v-
|
|
21505
|
+
}, [["__scopeId", "data-v-582b6534"]]);
|
|
21503
21506
|
//#endregion
|
|
21504
21507
|
//#region src/components/surfaces/SurfaceFloating.vue
|
|
21505
21508
|
var _hoisted_1$17 = ["aria-labelledby", "aria-label"];
|
|
@@ -21667,10 +21670,9 @@ var SurfaceHost_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21667
21670
|
* Reads the SurfaceManager's reactive state (activeDialog / activeFloating)
|
|
21668
21671
|
* and renders the appropriate surface shell for each slot.
|
|
21669
21672
|
*
|
|
21670
|
-
*
|
|
21671
|
-
* of
|
|
21672
|
-
*
|
|
21673
|
-
* area regardless of document scroll position.
|
|
21673
|
+
* Floating surfaces are clipped to the visible document viewport. Modal
|
|
21674
|
+
* dialogs are siblings of that clipped host so their backdrop covers the
|
|
21675
|
+
* browser viewport, including toolbars and surrounding application content.
|
|
21674
21676
|
*
|
|
21675
21677
|
* Floating Escape and outside-pointer-down handling live here (document-level)
|
|
21676
21678
|
* because floating surfaces are non-modal — focus can be anywhere in the
|
|
@@ -21868,15 +21870,15 @@ var SurfaceHost_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
21868
21870
|
surface: floating.value,
|
|
21869
21871
|
ref_key: "floatingRef",
|
|
21870
21872
|
ref: floatingRef
|
|
21871
|
-
}, null, 8, ["surface"])) : createCommentVNode("", true), dialog.value ? (openBlock(), createBlock(SurfaceDialog_default, {
|
|
21873
|
+
}, null, 8, ["surface"])) : createCommentVNode("", true)], 4)) : createCommentVNode("", true), dialog.value ? (openBlock(), createBlock(SurfaceDialog_default, {
|
|
21872
21874
|
key: dialog.value.id,
|
|
21873
21875
|
surface: dialog.value,
|
|
21874
21876
|
"scroll-lock-target": unref(geometryTarget),
|
|
21875
21877
|
onClose: handleDialogClose
|
|
21876
|
-
}, null, 8, ["surface", "scroll-lock-target"])) : createCommentVNode("", true)]
|
|
21878
|
+
}, null, 8, ["surface", "scroll-lock-target"])) : createCommentVNode("", true)]);
|
|
21877
21879
|
};
|
|
21878
21880
|
}
|
|
21879
|
-
}, [["__scopeId", "data-v-
|
|
21881
|
+
}, [["__scopeId", "data-v-dad99b67"]]);
|
|
21880
21882
|
//#endregion
|
|
21881
21883
|
//#region src/SuperDoc.vue
|
|
21882
21884
|
var _hoisted_1$16 = ["innerHTML"];
|
|
@@ -38169,6 +38171,7 @@ function addCustomItemRegions(regions, customItems) {
|
|
|
38169
38171
|
return result;
|
|
38170
38172
|
}
|
|
38171
38173
|
var TOOLBAR_OPTIONAL_ITEM_REGIONS = Object.freeze({
|
|
38174
|
+
watermark: "center",
|
|
38172
38175
|
"formatting-marks": "right",
|
|
38173
38176
|
"table-of-contents": "center"
|
|
38174
38177
|
});
|
|
@@ -38279,7 +38282,8 @@ function normalizeToolbarOptions(options) {
|
|
|
38279
38282
|
fonts: options.fontOptions === void 0 ? options.fonts : mapToolbarFontOptions(options.fontOptions),
|
|
38280
38283
|
customButtons: options.customItems === void 0 ? options.customButtons : mapToolbarCustomItems(options.customItems),
|
|
38281
38284
|
showFormattingMarksButton: includeItems === null && !itemIds.has("formatting-marks") ? options.showFormattingMarksButton : itemIds.has("formatting-marks") || includeItems?.has("formatting-marks"),
|
|
38282
|
-
showTableOfContentsButton: includeItems === null && !itemIds.has("table-of-contents") ? options.showTableOfContentsButton : itemIds.has("table-of-contents") || includeItems?.has("table-of-contents")
|
|
38285
|
+
showTableOfContentsButton: includeItems === null && !itemIds.has("table-of-contents") ? options.showTableOfContentsButton : itemIds.has("table-of-contents") || includeItems?.has("table-of-contents"),
|
|
38286
|
+
showWatermarkButton: itemIds.has("watermark") || includeItems?.has("watermark") || false
|
|
38283
38287
|
});
|
|
38284
38288
|
}
|
|
38285
38289
|
/**
|
|
@@ -38809,6 +38813,14 @@ var BUILT_IN_TOOLBAR_CATALOG = [
|
|
|
38809
38813
|
disposition: "controller-routed",
|
|
38810
38814
|
group: "center"
|
|
38811
38815
|
},
|
|
38816
|
+
{
|
|
38817
|
+
name: "watermark",
|
|
38818
|
+
commandId: null,
|
|
38819
|
+
instanceMethod: "ui.watermark.open",
|
|
38820
|
+
disposition: "host-routed",
|
|
38821
|
+
group: "center",
|
|
38822
|
+
note: "opens the shared Watermark dialog through superdoc.ui.watermark.open; the workflow owns scope, edit permissions, and apply"
|
|
38823
|
+
},
|
|
38812
38824
|
{
|
|
38813
38825
|
name: "table",
|
|
38814
38826
|
commandId: "table-insert",
|
|
@@ -38934,153 +38946,6 @@ function resolveToolbarCommandId(name) {
|
|
|
38934
38946
|
return entry?.disposition === "controller-routed" ? entry.commandId : null;
|
|
38935
38947
|
}
|
|
38936
38948
|
//#endregion
|
|
38937
|
-
//#region src/internal/toolbar/image-upload.js
|
|
38938
|
-
/**
|
|
38939
|
-
* Interactive image acquisition for the built-in toolbar (SD-3567).
|
|
38940
|
-
*
|
|
38941
|
-
* The toolbar image button routes through the shared controller command
|
|
38942
|
-
* `image` → `create.image`, which requires a base64 PNG/JPEG data-URI `src`.
|
|
38943
|
-
* This module owns the browser file picker and the File → data-URI
|
|
38944
|
-
* conversion; the toolbar dispatches the resulting payload through the
|
|
38945
|
-
* normal controller command path.
|
|
38946
|
-
*/
|
|
38947
|
-
/** Accept filter for the picker: PNG and JPEG only (V1 parity; OOXML-native formats). */
|
|
38948
|
-
var IMAGE_PICKER_ACCEPT = ".png,.jpg,.jpeg,image/png,image/jpeg";
|
|
38949
|
-
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
38950
|
-
"image/png",
|
|
38951
|
-
"image/jpeg",
|
|
38952
|
-
"image/jpg"
|
|
38953
|
-
]);
|
|
38954
|
-
var SUPPORTED_IMAGE_EXTENSIONS = /\.(png|jpe?g)$/i;
|
|
38955
|
-
/**
|
|
38956
|
-
* Whether a picked/dropped file is an insertable image (PNG/JPEG). Falls back
|
|
38957
|
-
* to the file extension when the browser reports no MIME type.
|
|
38958
|
-
* @param {File | null | undefined} file
|
|
38959
|
-
* @returns {boolean}
|
|
38960
|
-
*/
|
|
38961
|
-
function isSupportedImageFile(file) {
|
|
38962
|
-
if (!file) return false;
|
|
38963
|
-
const type = typeof file.type === "string" ? file.type.toLowerCase() : "";
|
|
38964
|
-
if (type) return SUPPORTED_IMAGE_MIME_TYPES.has(type);
|
|
38965
|
-
return SUPPORTED_IMAGE_EXTENSIONS.test(String(file.name ?? ""));
|
|
38966
|
-
}
|
|
38967
|
-
/**
|
|
38968
|
-
* Read a File/Blob into a base64 data URI.
|
|
38969
|
-
*
|
|
38970
|
-
* Some browsers/OSes deliver picked files with an empty `type`; the picker
|
|
38971
|
-
* accepts those by extension, but `readAsDataURL` would then produce an
|
|
38972
|
-
* `application/octet-stream` data URI that `create.image` rejects. Rewrite
|
|
38973
|
-
* the media type from the filename so extension-accepted files still insert.
|
|
38974
|
-
* @param {Blob & { name?: string }} file
|
|
38975
|
-
* @returns {Promise<string>}
|
|
38976
|
-
*/
|
|
38977
|
-
function fileToDataUri(file) {
|
|
38978
|
-
return new Promise((resolve, reject) => {
|
|
38979
|
-
const reader = new FileReader();
|
|
38980
|
-
reader.onload = () => resolve(normalizeImageDataUri(String(reader.result), file));
|
|
38981
|
-
reader.onerror = () => reject(reader.error ?? /* @__PURE__ */ new Error("image-read-failed"));
|
|
38982
|
-
reader.readAsDataURL(file);
|
|
38983
|
-
});
|
|
38984
|
-
}
|
|
38985
|
-
/**
|
|
38986
|
-
* Ensure a data URI read from a supported file carries a PNG/JPEG media type.
|
|
38987
|
-
* Leaves URIs already typed as a supported image (or uninferable ones) alone.
|
|
38988
|
-
* @param {string} dataUri
|
|
38989
|
-
* @param {(Blob & { name?: string }) | null | undefined} file
|
|
38990
|
-
* @returns {string}
|
|
38991
|
-
*/
|
|
38992
|
-
function normalizeImageDataUri(dataUri, file) {
|
|
38993
|
-
const match = /^data:([^;,]*);base64,/.exec(dataUri);
|
|
38994
|
-
if (!match) return dataUri;
|
|
38995
|
-
const mime = match[1].toLowerCase();
|
|
38996
|
-
if (SUPPORTED_IMAGE_MIME_TYPES.has(mime)) return dataUri;
|
|
38997
|
-
const name = String(file?.name ?? "");
|
|
38998
|
-
const inferred = /\.jpe?g$/i.test(name) ? "image/jpeg" : /\.png$/i.test(name) ? "image/png" : null;
|
|
38999
|
-
if (!inferred) return dataUri;
|
|
39000
|
-
return `data:${inferred};base64,${dataUri.slice(match[0].length)}`;
|
|
39001
|
-
}
|
|
39002
|
-
/**
|
|
39003
|
-
* Resolve the `create.image` src for a picked file. Uses the consumer's
|
|
39004
|
-
* `handleImageUpload` callback when configured (V1 contract:
|
|
39005
|
-
* `(file: File) => Promise<string>`). A returned non-data URL is fetched and
|
|
39006
|
-
* embedded, because `create.image` requires an embedded base64 data URI.
|
|
39007
|
-
* @param {File} file
|
|
39008
|
-
* @param {((file: File) => Promise<string>) | null | undefined} handleImageUpload
|
|
39009
|
-
* @returns {Promise<string>}
|
|
39010
|
-
*/
|
|
39011
|
-
async function resolveImageSrc(file, handleImageUpload) {
|
|
39012
|
-
if (typeof handleImageUpload === "function") {
|
|
39013
|
-
const result = await handleImageUpload(file);
|
|
39014
|
-
if (typeof result !== "string" || result.trim() === "") throw new Error("handleImageUpload returned an empty result");
|
|
39015
|
-
if (result.startsWith("data:")) return result;
|
|
39016
|
-
return embedRemoteImage(result, file);
|
|
39017
|
-
}
|
|
39018
|
-
return fileToDataUri(file);
|
|
39019
|
-
}
|
|
39020
|
-
/**
|
|
39021
|
-
* Fetch a remote image URL and embed it as a data URI. Object-store /
|
|
39022
|
-
* presigned URLs often respond `application/octet-stream`, so keep a filename
|
|
39023
|
-
* hint (URL path, falling back to the originally picked file) for the media
|
|
39024
|
-
* type normalization in `fileToDataUri`.
|
|
39025
|
-
* @param {string} url
|
|
39026
|
-
* @param {File | null | undefined} pickedFile
|
|
39027
|
-
* @returns {Promise<string>}
|
|
39028
|
-
*/
|
|
39029
|
-
async function embedRemoteImage(url, pickedFile) {
|
|
39030
|
-
const response = await fetch(url);
|
|
39031
|
-
if (!response.ok) throw new Error(`image fetch failed: ${response.status}`);
|
|
39032
|
-
const blob = await response.blob();
|
|
39033
|
-
const name = (/\.(?:png|jpe?g)(?:$|[?#])/i.test(url) ? url.split(/[?#]/)[0] : "") || pickedFile?.name || "";
|
|
39034
|
-
return fileToDataUri(name ? Object.assign(blob, { name }) : blob);
|
|
39035
|
-
}
|
|
39036
|
-
/**
|
|
39037
|
-
* Hidden `<input type=file>` picker bound to one toolbar instance. The input
|
|
39038
|
-
* stays attached (hidden) so automation and tests can drive it; `destroy()`
|
|
39039
|
-
* removes it. Picking a file calls `onPick(file)`; an unsupported type or a
|
|
39040
|
-
* failed pick routes through `onError(error)`.
|
|
39041
|
-
*
|
|
39042
|
-
* @param {{
|
|
39043
|
-
* ownerDocument?: Document,
|
|
39044
|
-
* onPick?: (file: File) => unknown,
|
|
39045
|
-
* onError?: (error: Error) => void,
|
|
39046
|
-
* }} options
|
|
39047
|
-
* @returns {{ input: HTMLInputElement, open: () => void, destroy: () => void }}
|
|
39048
|
-
*/
|
|
39049
|
-
function createImageFilePicker({ ownerDocument = document, onPick, onError } = {}) {
|
|
39050
|
-
const input = ownerDocument.createElement("input");
|
|
39051
|
-
input.type = "file";
|
|
39052
|
-
input.accept = IMAGE_PICKER_ACCEPT;
|
|
39053
|
-
input.hidden = true;
|
|
39054
|
-
input.tabIndex = -1;
|
|
39055
|
-
input.setAttribute("data-superdoc-image-picker", "true");
|
|
39056
|
-
input.setAttribute("aria-hidden", "true");
|
|
39057
|
-
input.addEventListener("change", () => {
|
|
39058
|
-
const file = input.files && input.files[0];
|
|
39059
|
-
input.value = "";
|
|
39060
|
-
if (!file) return;
|
|
39061
|
-
if (!isSupportedImageFile(file)) {
|
|
39062
|
-
onError?.(/* @__PURE__ */ new Error(`unsupported image type: ${file.type || file.name}`));
|
|
39063
|
-
return;
|
|
39064
|
-
}
|
|
39065
|
-
try {
|
|
39066
|
-
const result = onPick?.(file);
|
|
39067
|
-
if (result && typeof result.then === "function") result.catch((error) => onError?.(error));
|
|
39068
|
-
} catch (error) {
|
|
39069
|
-
onError?.(error);
|
|
39070
|
-
}
|
|
39071
|
-
});
|
|
39072
|
-
ownerDocument.body?.appendChild(input);
|
|
39073
|
-
return {
|
|
39074
|
-
input,
|
|
39075
|
-
open() {
|
|
39076
|
-
input.click();
|
|
39077
|
-
},
|
|
39078
|
-
destroy() {
|
|
39079
|
-
input.remove();
|
|
39080
|
-
}
|
|
39081
|
-
};
|
|
39082
|
-
}
|
|
39083
|
-
//#endregion
|
|
39084
38949
|
//#region src/internal/toolbar/built-in/helpers.js
|
|
39085
38950
|
var sanitizeNumber = (value, defaultNumber) => {
|
|
39086
38951
|
let sanitized = value.replace(/[^0-9.]/g, "");
|
|
@@ -39270,6 +39135,7 @@ var ToolbarButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39270
39135
|
handleClick();
|
|
39271
39136
|
};
|
|
39272
39137
|
const onEnterKeydown = (event) => {
|
|
39138
|
+
event.preventDefault();
|
|
39273
39139
|
if (!props.allowEnterPropagation) event.stopPropagation();
|
|
39274
39140
|
handleOuterEnter(event);
|
|
39275
39141
|
};
|
|
@@ -39461,7 +39327,7 @@ var ToolbarButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39461
39327
|
], 10, _hoisted_2$10)], 46, _hoisted_1$14);
|
|
39462
39328
|
};
|
|
39463
39329
|
}
|
|
39464
|
-
}, [["__scopeId", "data-v-
|
|
39330
|
+
}, [["__scopeId", "data-v-96796456"]]);
|
|
39465
39331
|
//#endregion
|
|
39466
39332
|
//#region src/internal/toolbar/built-in/ToolbarSeparator.vue
|
|
39467
39333
|
var _hoisted_1$13 = {
|
|
@@ -39541,7 +39407,7 @@ var ToolbarDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39541
39407
|
}
|
|
39542
39408
|
},
|
|
39543
39409
|
emits: ["update:show", "select"],
|
|
39544
|
-
setup(__props, { emit: __emit }) {
|
|
39410
|
+
setup(__props, { expose: __expose, emit: __emit }) {
|
|
39545
39411
|
const props = __props;
|
|
39546
39412
|
const emit = __emit;
|
|
39547
39413
|
const slots = useSlots();
|
|
@@ -39776,6 +39642,7 @@ var ToolbarDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39776
39642
|
trigger.setAttribute("tabindex", "-1");
|
|
39777
39643
|
trigger.focus();
|
|
39778
39644
|
};
|
|
39645
|
+
__expose({ focusTrigger });
|
|
39779
39646
|
const handleKeyDown = (event) => {
|
|
39780
39647
|
if (!isOpen.value) return;
|
|
39781
39648
|
const { key } = event;
|
|
@@ -39887,7 +39754,7 @@ var ToolbarDropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39887
39754
|
})], 8, ["to"]))]);
|
|
39888
39755
|
};
|
|
39889
39756
|
}
|
|
39890
|
-
}, [["__scopeId", "data-v-
|
|
39757
|
+
}, [["__scopeId", "data-v-fa3f6b69"]]);
|
|
39891
39758
|
//#endregion
|
|
39892
39759
|
//#region src/internal/toolbar/built-in/toolbar-focus-helpers.js
|
|
39893
39760
|
var preventEditorFocusTransfer = (event) => {
|
|
@@ -39933,6 +39800,7 @@ var OverflowMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39933
39800
|
setup(__props, { emit: __emit }) {
|
|
39934
39801
|
const emit = __emit;
|
|
39935
39802
|
const props = __props;
|
|
39803
|
+
const dropdown = ref(null);
|
|
39936
39804
|
const isOverflowMenuOpened = computed(() => props.toolbarItem.expand.value);
|
|
39937
39805
|
const hasOpenDropdown = computed(() => props.overflowItems.some((item) => item.type === "dropdown" && unref(item.expand)));
|
|
39938
39806
|
const overflowToolbarItem = computed(() => ({
|
|
@@ -39948,6 +39816,10 @@ var OverflowMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39948
39816
|
emit("close");
|
|
39949
39817
|
};
|
|
39950
39818
|
const handleCommand = ({ item, argument, option }) => {
|
|
39819
|
+
if (item.name.value === "watermark") {
|
|
39820
|
+
emit("close");
|
|
39821
|
+
dropdown.value?.focusTrigger();
|
|
39822
|
+
}
|
|
39951
39823
|
emit("command", {
|
|
39952
39824
|
item,
|
|
39953
39825
|
argument,
|
|
@@ -39956,6 +39828,8 @@ var OverflowMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39956
39828
|
};
|
|
39957
39829
|
return (_ctx, _cache) => {
|
|
39958
39830
|
return openBlock(), createBlock(ToolbarDropdown_default, {
|
|
39831
|
+
ref_key: "dropdown",
|
|
39832
|
+
ref: dropdown,
|
|
39959
39833
|
class: "overflow-menu",
|
|
39960
39834
|
"close-on-escape": !hasOpenDropdown.value,
|
|
39961
39835
|
"has-open-child": hasOpenDropdown.value,
|
|
@@ -39973,7 +39847,10 @@ var OverflowMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39973
39847
|
class: ["overflow-menu_items", "sd-toolbar-overflow-menu"]
|
|
39974
39848
|
})
|
|
39975
39849
|
}, {
|
|
39976
|
-
trigger: withCtx(() => [createVNode(ToolbarButton_default, {
|
|
39850
|
+
trigger: withCtx(() => [createVNode(ToolbarButton_default, {
|
|
39851
|
+
"toolbar-item": overflowToolbarItem.value,
|
|
39852
|
+
"allow-enter-propagation": true
|
|
39853
|
+
}, null, 8, ["toolbar-item"])]),
|
|
39977
39854
|
menu: withCtx(() => [createVNode(ButtonGroup_default, {
|
|
39978
39855
|
class: "superdoc-toolbar-overflow",
|
|
39979
39856
|
"toolbar-items": __props.overflowItems,
|
|
@@ -39995,7 +39872,7 @@ var OverflowMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
39995
39872
|
]);
|
|
39996
39873
|
};
|
|
39997
39874
|
}
|
|
39998
|
-
}, [["__scopeId", "data-v-
|
|
39875
|
+
}, [["__scopeId", "data-v-1227fcf9"]]);
|
|
39999
39876
|
//#endregion
|
|
40000
39877
|
//#region src/internal/toolbar/built-in/font-typeahead.js
|
|
40001
39878
|
/**
|
|
@@ -41630,10 +41507,12 @@ var Toolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
41630
41507
|
setup(__props, { emit: __emit }) {
|
|
41631
41508
|
const { proxy } = getCurrentInstance();
|
|
41632
41509
|
let toolbarKey = ref(1);
|
|
41510
|
+
const toolbarRoot = ref(null);
|
|
41633
41511
|
const toolbarStateVersion = ref(0);
|
|
41634
41512
|
const compactSideGroups = ref(false);
|
|
41635
41513
|
let containerResizeObserver = null;
|
|
41636
41514
|
let pendingSelectionCapture = null;
|
|
41515
|
+
let renderedWidth = proxy.$toolbar.getAvailableWidth();
|
|
41637
41516
|
/**
|
|
41638
41517
|
* Computed property that determines the font-family to use for toolbar UI surfaces.
|
|
41639
41518
|
* Retrieves the configured font from the toolbar instance's config and validates it.
|
|
@@ -41654,10 +41533,41 @@ var Toolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
41654
41533
|
const updateCompactSideGroups = () => {
|
|
41655
41534
|
compactSideGroups.value = proxy.$toolbar.getAvailableWidth() <= RESPONSIVE_BREAKPOINTS.lg;
|
|
41656
41535
|
};
|
|
41536
|
+
const captureFocusedControl = () => {
|
|
41537
|
+
const root = toolbarRoot.value;
|
|
41538
|
+
const ownerDocument = root?.ownerDocument;
|
|
41539
|
+
const focused = ownerDocument?.activeElement;
|
|
41540
|
+
if (!root?.contains(focused)) return null;
|
|
41541
|
+
const control = focused.closest("[data-sd-part=\"toolbar-item\"]") ?? focused.querySelector("[data-sd-part=\"toolbar-item\"]");
|
|
41542
|
+
if (!control || focused !== control && !focused.contains(control)) return null;
|
|
41543
|
+
const itemId = control.querySelector("[data-item]")?.getAttribute("data-item");
|
|
41544
|
+
if (!itemId) return null;
|
|
41545
|
+
return () => {
|
|
41546
|
+
const currentRoot = toolbarRoot.value;
|
|
41547
|
+
if (!currentRoot?.isConnected || focused.isConnected || ownerDocument.activeElement !== ownerDocument.body) return;
|
|
41548
|
+
const markers = [...currentRoot.querySelectorAll("[data-item]")];
|
|
41549
|
+
for (const id of [itemId, "btn-overflow"]) {
|
|
41550
|
+
const target = markers.find((marker) => marker.getAttribute("data-item") === id)?.closest("[data-sd-part=\"toolbar-item\"]");
|
|
41551
|
+
if (target && target.getAttribute("aria-disabled") !== "true") {
|
|
41552
|
+
target.focus({ preventScroll: true });
|
|
41553
|
+
return;
|
|
41554
|
+
}
|
|
41555
|
+
}
|
|
41556
|
+
};
|
|
41557
|
+
};
|
|
41558
|
+
const renderToolbar = async (restoreFocus) => {
|
|
41559
|
+
toolbarKey.value += 1;
|
|
41560
|
+
await nextTick();
|
|
41561
|
+
restoreFocus?.();
|
|
41562
|
+
};
|
|
41657
41563
|
const onWindowResized = async () => {
|
|
41564
|
+
const width = proxy.$toolbar.getAvailableWidth();
|
|
41565
|
+
if (width === renderedWidth) return;
|
|
41566
|
+
renderedWidth = width;
|
|
41567
|
+
const restoreFocus = captureFocusedControl();
|
|
41658
41568
|
await proxy.$toolbar.onToolbarResize();
|
|
41659
41569
|
updateCompactSideGroups();
|
|
41660
|
-
|
|
41570
|
+
await renderToolbar(restoreFocus);
|
|
41661
41571
|
};
|
|
41662
41572
|
const onResizeThrottled = throttle(onWindowResized, 300);
|
|
41663
41573
|
/**
|
|
@@ -41667,12 +41577,16 @@ var Toolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
41667
41577
|
* SuperToolbar emits `toolbar-items-changed` on rebuild; bumping the key re-reads the new items into the DOM.
|
|
41668
41578
|
*/
|
|
41669
41579
|
const onToolbarItemsChanged = () => {
|
|
41670
|
-
|
|
41580
|
+
const restoreFocus = captureFocusedControl();
|
|
41581
|
+
renderedWidth = proxy.$toolbar.getAvailableWidth();
|
|
41582
|
+
updateCompactSideGroups();
|
|
41583
|
+
renderToolbar(restoreFocus);
|
|
41671
41584
|
};
|
|
41672
41585
|
const onToolbarStateChanged = () => {
|
|
41673
41586
|
toolbarStateVersion.value += 1;
|
|
41674
41587
|
};
|
|
41675
41588
|
function teardownListeners() {
|
|
41589
|
+
onResizeThrottled.cancel();
|
|
41676
41590
|
window.removeEventListener("resize", onResizeThrottled);
|
|
41677
41591
|
proxy.$toolbar.off?.("toolbar-items-changed", onToolbarItemsChanged);
|
|
41678
41592
|
proxy.$toolbar.off?.("toolbar-state-change", onToolbarStateChanged);
|
|
@@ -41730,6 +41644,8 @@ var Toolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
41730
41644
|
return (_ctx, _cache) => {
|
|
41731
41645
|
return openBlock(), createElementBlock("div", {
|
|
41732
41646
|
class: "superdoc-toolbar",
|
|
41647
|
+
ref_key: "toolbarRoot",
|
|
41648
|
+
ref: toolbarRoot,
|
|
41733
41649
|
key: unref(toolbarKey),
|
|
41734
41650
|
role: "toolbar",
|
|
41735
41651
|
"aria-label": "Toolbar",
|
|
@@ -41786,7 +41702,7 @@ var Toolbar_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
|
|
|
41786
41702
|
], 32);
|
|
41787
41703
|
};
|
|
41788
41704
|
}
|
|
41789
|
-
}, [["__scopeId", "data-v-
|
|
41705
|
+
}, [["__scopeId", "data-v-9418cc7d"]]);
|
|
41790
41706
|
//#endregion
|
|
41791
41707
|
//#region src/internal/toolbar/built-in/font-options.js
|
|
41792
41708
|
/**
|
|
@@ -43383,6 +43299,15 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons, toolbarTexts, toolbarFonts
|
|
|
43383
43299
|
disabled: false,
|
|
43384
43300
|
attributes: { ariaLabel: "Table of contents" }
|
|
43385
43301
|
});
|
|
43302
|
+
const watermark = useToolbarItem({
|
|
43303
|
+
type: "button",
|
|
43304
|
+
name: "watermark",
|
|
43305
|
+
icon: toolbarIcons.watermark,
|
|
43306
|
+
tooltip: toolbarTexts.watermark,
|
|
43307
|
+
allowWithoutEditor: true,
|
|
43308
|
+
disabled: true,
|
|
43309
|
+
attributes: { ariaLabel: toolbarTexts.watermark }
|
|
43310
|
+
});
|
|
43386
43311
|
const tableItem = useToolbarItem({
|
|
43387
43312
|
type: "dropdown",
|
|
43388
43313
|
name: "table",
|
|
@@ -44088,6 +44013,7 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons, toolbarTexts, toolbarFonts
|
|
|
44088
44013
|
link,
|
|
44089
44014
|
image,
|
|
44090
44015
|
...shouldIncludeTableOfContents ? [tableOfContents] : [],
|
|
44016
|
+
...superToolbar.config?.showWatermarkButton || configuredItemNames?.has("watermark") ? [watermark] : [],
|
|
44091
44017
|
tableItem,
|
|
44092
44018
|
tableActionsItem,
|
|
44093
44019
|
makeSeparator(),
|
|
@@ -44194,6 +44120,7 @@ var toolbarTexts = {
|
|
|
44194
44120
|
link: "Link",
|
|
44195
44121
|
image: "Image",
|
|
44196
44122
|
tableOfContents: "Table of contents",
|
|
44123
|
+
watermark: "Watermark",
|
|
44197
44124
|
table: "Insert table",
|
|
44198
44125
|
tableActions: "Table options",
|
|
44199
44126
|
addRowBefore: "Insert row above",
|
|
@@ -44393,7 +44320,8 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
|
|
|
44393
44320
|
groups: null,
|
|
44394
44321
|
customButtons: [],
|
|
44395
44322
|
showFormattingMarksButton: false,
|
|
44396
|
-
showTableOfContentsButton: false
|
|
44323
|
+
showTableOfContentsButton: false,
|
|
44324
|
+
showWatermarkButton: false
|
|
44397
44325
|
};
|
|
44398
44326
|
toolbarItems = [];
|
|
44399
44327
|
overflowItems = [];
|
|
@@ -44727,6 +44655,7 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
|
|
|
44727
44655
|
return false;
|
|
44728
44656
|
}
|
|
44729
44657
|
#canRunHostAction(name) {
|
|
44658
|
+
if (name === "watermark") return this.ui?.document?.getSnapshot?.().ready === true && typeof this.ui?.watermark?.open === "function";
|
|
44730
44659
|
if (name === "ruler") return typeof this.superdoc?.toggleRuler === "function";
|
|
44731
44660
|
if (name === "formattingMarks") return typeof this.superdoc?.toggleFormattingMarks === "function" || typeof this.superdoc?.setShowFormattingMarks === "function";
|
|
44732
44661
|
return false;
|
|
@@ -44905,6 +44834,7 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
|
|
|
44905
44834
|
item.resetDisabled();
|
|
44906
44835
|
this.#applyHeadlessState(item);
|
|
44907
44836
|
});
|
|
44837
|
+
this.getToolbarItemByName("overflow")?.setDisabled(!this.overflowItems.some((item) => item.type !== "separator" && !item.disabled.value));
|
|
44908
44838
|
const copyFormatItem = this.getToolbarItemByName("copyFormat");
|
|
44909
44839
|
if (copyFormatItem) if (this.snapshot?.copyFormatActive) copyFormatItem.activate();
|
|
44910
44840
|
else copyFormatItem.deactivate();
|
|
@@ -44919,6 +44849,12 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
|
|
|
44919
44849
|
}
|
|
44920
44850
|
#runHostAction(name, argument) {
|
|
44921
44851
|
const superdoc = this.superdoc;
|
|
44852
|
+
if (name === "watermark") {
|
|
44853
|
+
if (!this.#canRunHostAction(name)) return false;
|
|
44854
|
+
const result = this.ui.watermark.open();
|
|
44855
|
+
if (!result.ok) throw new Error(`[superdoc toolbar] Watermark dialog unavailable: ${result.reason}`);
|
|
44856
|
+
return true;
|
|
44857
|
+
}
|
|
44922
44858
|
if (name === "ruler") {
|
|
44923
44859
|
if (typeof superdoc?.toggleRuler === "function") {
|
|
44924
44860
|
superdoc.toggleRuler();
|
|
@@ -45681,7 +45617,7 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
45681
45617
|
this.config.colors = shuffleArray(this.config.colors);
|
|
45682
45618
|
this.userColorMap = /* @__PURE__ */ new Map();
|
|
45683
45619
|
this.colorIndex = 0;
|
|
45684
|
-
this.version = "2.
|
|
45620
|
+
this.version = "2.19.0-next.2";
|
|
45685
45621
|
this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
|
|
45686
45622
|
this.superdocId = config.superdocId || v4();
|
|
45687
45623
|
this.colors = this.config.colors ?? [];
|
|
@@ -47073,7 +47009,7 @@ var SuperDoc = class extends import_eventemitter3.default {
|
|
|
47073
47009
|
{
|
|
47074
47010
|
feature: "shell.collaboration",
|
|
47075
47011
|
status: "supported",
|
|
47076
|
-
reason: "v2 single-doc y-websocket
|
|
47012
|
+
reason: "v2 single-doc collaboration (hocuspocus, y-websocket, liveblocks, and registered provider extensions) is wired through document.collaboration, including collaboration-ready, awareness-update, and locked event bridges; external { ydoc, provider } instances remain unsupported"
|
|
47077
47013
|
},
|
|
47078
47014
|
{
|
|
47079
47015
|
feature: "shell.context-menu",
|