@univerjs/docs-hyper-link-ui 1.0.0-insiders.20260809-70eefdd → 1.0.0-rc.0

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.
Files changed (88) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +0 -1
  3. package/lib/cjs/index.js +211 -97
  4. package/lib/cjs/locale/ar-SA.js +0 -2
  5. package/lib/cjs/locale/ca-ES.js +0 -2
  6. package/lib/cjs/locale/de-DE.js +0 -2
  7. package/lib/cjs/locale/en-US.js +0 -2
  8. package/lib/cjs/locale/es-ES.js +0 -2
  9. package/lib/cjs/locale/fa-IR.js +0 -2
  10. package/lib/cjs/locale/fr-FR.js +0 -2
  11. package/lib/cjs/locale/id-ID.js +0 -2
  12. package/lib/cjs/locale/it-IT.js +0 -2
  13. package/lib/cjs/locale/ja-JP.js +0 -2
  14. package/lib/cjs/locale/ko-KR.js +0 -2
  15. package/lib/cjs/locale/pl-PL.js +0 -2
  16. package/lib/cjs/locale/pt-BR.js +0 -2
  17. package/lib/cjs/locale/ru-RU.js +0 -2
  18. package/lib/cjs/locale/sk-SK.js +0 -2
  19. package/lib/cjs/locale/vi-VN.js +0 -2
  20. package/lib/cjs/locale/zh-CN.js +0 -2
  21. package/lib/cjs/locale/zh-HK.js +0 -2
  22. package/lib/cjs/locale/zh-TW.js +0 -2
  23. package/lib/es/index.js +216 -102
  24. package/lib/es/locale/ar-SA.js +0 -2
  25. package/lib/es/locale/ca-ES.js +0 -2
  26. package/lib/es/locale/de-DE.js +0 -2
  27. package/lib/es/locale/en-US.js +0 -2
  28. package/lib/es/locale/es-ES.js +0 -2
  29. package/lib/es/locale/fa-IR.js +0 -2
  30. package/lib/es/locale/fr-FR.js +0 -2
  31. package/lib/es/locale/id-ID.js +0 -2
  32. package/lib/es/locale/it-IT.js +0 -2
  33. package/lib/es/locale/ja-JP.js +0 -2
  34. package/lib/es/locale/ko-KR.js +0 -2
  35. package/lib/es/locale/pl-PL.js +0 -2
  36. package/lib/es/locale/pt-BR.js +0 -2
  37. package/lib/es/locale/ru-RU.js +0 -2
  38. package/lib/es/locale/sk-SK.js +0 -2
  39. package/lib/es/locale/vi-VN.js +0 -2
  40. package/lib/es/locale/zh-CN.js +0 -2
  41. package/lib/es/locale/zh-HK.js +0 -2
  42. package/lib/es/locale/zh-TW.js +0 -2
  43. package/lib/index.css +51 -4
  44. package/lib/index.js +216 -102
  45. package/lib/locale/ar-SA.js +0 -2
  46. package/lib/locale/ca-ES.js +0 -2
  47. package/lib/locale/de-DE.js +0 -2
  48. package/lib/locale/en-US.js +0 -2
  49. package/lib/locale/es-ES.js +0 -2
  50. package/lib/locale/fa-IR.js +0 -2
  51. package/lib/locale/fr-FR.js +0 -2
  52. package/lib/locale/id-ID.js +0 -2
  53. package/lib/locale/it-IT.js +0 -2
  54. package/lib/locale/ja-JP.js +0 -2
  55. package/lib/locale/ko-KR.js +0 -2
  56. package/lib/locale/pl-PL.js +0 -2
  57. package/lib/locale/pt-BR.js +0 -2
  58. package/lib/locale/ru-RU.js +0 -2
  59. package/lib/locale/sk-SK.js +0 -2
  60. package/lib/locale/vi-VN.js +0 -2
  61. package/lib/locale/zh-CN.js +0 -2
  62. package/lib/locale/zh-HK.js +0 -2
  63. package/lib/locale/zh-TW.js +0 -2
  64. package/lib/types/controllers/render-controllers/hyper-link-event.render-controller.d.ts +1 -0
  65. package/lib/types/controllers/render-controllers/render.controller.d.ts +1 -5
  66. package/lib/types/locale/en-US.d.ts +0 -2
  67. package/lib/types/services/hyper-link-popup.service.d.ts +26 -9
  68. package/lib/umd/index.js +1 -1
  69. package/lib/umd/locale/ar-SA.js +1 -1
  70. package/lib/umd/locale/ca-ES.js +1 -1
  71. package/lib/umd/locale/de-DE.js +1 -1
  72. package/lib/umd/locale/en-US.js +1 -1
  73. package/lib/umd/locale/es-ES.js +1 -1
  74. package/lib/umd/locale/fa-IR.js +1 -1
  75. package/lib/umd/locale/fr-FR.js +1 -1
  76. package/lib/umd/locale/id-ID.js +1 -1
  77. package/lib/umd/locale/it-IT.js +1 -1
  78. package/lib/umd/locale/ja-JP.js +1 -1
  79. package/lib/umd/locale/ko-KR.js +1 -1
  80. package/lib/umd/locale/pl-PL.js +1 -1
  81. package/lib/umd/locale/pt-BR.js +1 -1
  82. package/lib/umd/locale/ru-RU.js +1 -1
  83. package/lib/umd/locale/sk-SK.js +1 -1
  84. package/lib/umd/locale/vi-VN.js +1 -1
  85. package/lib/umd/locale/zh-CN.js +1 -1
  86. package/lib/umd/locale/zh-HK.js +1 -1
  87. package/lib/umd/locale/zh-TW.js +1 -1
  88. package/package.json +13 -12
package/lib/cjs/index.js CHANGED
@@ -3,18 +3,19 @@ let _univerjs_docs_ui = require("@univerjs/docs-ui");
3
3
  let _univerjs_ui = require("@univerjs/ui");
4
4
  let _univerjs_core = require("@univerjs/core");
5
5
  let _univerjs_docs = require("@univerjs/docs");
6
+ let _univerjs_engine_render = require("@univerjs/engine-render");
6
7
  let rxjs = require("rxjs");
7
8
  let _univerjs_design = require("@univerjs/design");
8
9
  let react = require("react");
10
+ let _univerjs_docs_hyper_link = require("@univerjs/docs-hyper-link");
9
11
  let react_jsx_runtime = require("react/jsx-runtime");
10
12
  let _univerjs_icons = require("@univerjs/icons");
11
- let _univerjs_docs_hyper_link = require("@univerjs/docs-hyper-link");
12
- let _univerjs_engine_render = require("@univerjs/engine-render");
13
+ let _univerjs_protocol = require("@univerjs/protocol");
13
14
 
14
15
  //#region src/commands/commands/add-link.command.ts
15
16
  const AddDocHyperLinkCommand = {
16
17
  type: _univerjs_core.CommandType.COMMAND,
17
- id: "docs.command.add-hyper-link",
18
+ id: _univerjs_docs_hyper_link.DocHyperLinkCommandId.Add,
18
19
  async handler(accessor, params) {
19
20
  if (!params) return false;
20
21
  const { payload, unitId, selections } = params;
@@ -34,7 +35,7 @@ const AddDocHyperLinkCommand = {
34
35
  //#endregion
35
36
  //#region src/commands/commands/update-link.command.ts
36
37
  const UpdateDocHyperLinkCommand = {
37
- id: "docs.command.update-hyper-link",
38
+ id: _univerjs_docs_hyper_link.DocHyperLinkCommandId.Update,
38
39
  type: _univerjs_core.CommandType.COMMAND,
39
40
  handler(accessor, params) {
40
41
  var _doc$getSelfOrHeaderF, _getBodySlice$textRun;
@@ -171,7 +172,7 @@ const DocHyperLinkEdit = () => {
171
172
  };
172
173
  if (!doc) return;
173
174
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
174
- className: (0, _univerjs_design.clsx)("univer-box-border univer-w-[328px] univer-rounded-xl univer-bg-white univer-px-6 univer-py-5 univer-shadow dark:!univer-bg-gray-900", _univerjs_design.borderClassName),
175
+ className: (0, _univerjs_design.clsx)("univer-box-border univer-w-[328px] univer-rounded-xl univer-bg-gray-0 univer-px-6 univer-py-5 univer-shadow dark:!univer-bg-gray-900", _univerjs_design.borderClassName),
175
176
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [editing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.FormLayout, {
176
177
  label: localeService.t("docs-hyper-link-ui.edit.label"),
177
178
  error: showError && isBlankInput(label) ? localeService.t("docs-hyper-link-ui.edit.labelError") : "",
@@ -214,7 +215,7 @@ DocHyperLinkEdit.componentKey = "docs-hyper-link-edit";
214
215
  //#region src/commands/commands/delete-link.command.ts
215
216
  const DeleteDocHyperLinkCommand = {
216
217
  type: _univerjs_core.CommandType.COMMAND,
217
- id: "docs.command.delete-hyper-link",
218
+ id: _univerjs_docs_hyper_link.DocHyperLinkCommandId.Delete,
218
219
  async handler(accessor, params) {
219
220
  if (!params) return false;
220
221
  const { unitId, linkId, segmentId } = params;
@@ -239,15 +240,24 @@ const DocLinkPopup = () => {
239
240
  const localeService = (0, _univerjs_ui.useDependency)(_univerjs_core.LocaleService);
240
241
  const currentPopup = (0, _univerjs_ui.useObservable)(hyperLinkService.showingLink$);
241
242
  const univerInstanceService = (0, _univerjs_ui.useDependency)(_univerjs_core.IUniverInstanceService);
243
+ const permissionService = (0, _univerjs_ui.useDependency)(_univerjs_core.IPermissionService);
242
244
  if (!currentPopup) return null;
243
245
  const { unitId, linkId, segmentId, startIndex, endIndex } = currentPopup;
244
246
  const doc = univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
245
- const body = doc === null || doc === void 0 || (_doc$getSelfOrHeaderF = doc.getSelfOrHeaderFooterModel(segmentId)) === null || _doc$getSelfOrHeaderF === void 0 ? void 0 : _doc$getSelfOrHeaderF.getBody();
247
+ const body = doc instanceof _univerjs_core.DocumentDataModel ? (_doc$getSelfOrHeaderF = doc.getSelfOrHeaderFooterModel(segmentId)) === null || _doc$getSelfOrHeaderF === void 0 ? void 0 : _doc$getSelfOrHeaderF.getBody() : void 0;
246
248
  const link = body === null || body === void 0 || (_body$customRanges = body.customRanges) === null || _body$customRanges === void 0 ? void 0 : _body$customRanges.find((range) => range.rangeId === linkId && range.rangeType === _univerjs_core.CustomRangeType.HYPERLINK && range.startIndex === startIndex && range.endIndex === endIndex);
247
249
  if (!link) return null;
248
250
  const url = (_link$properties = link.properties) === null || _link$properties === void 0 ? void 0 : _link$properties.url;
251
+ const canEdit = hyperLinkService.canEditLink(unitId, currentPopup);
252
+ const canCopy = (0, _univerjs_docs.getDocumentPermissionValue)(permissionService, unitId, unitId, _univerjs_protocol.UnitAction.Copy);
249
253
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
250
- className: (0, _univerjs_design.clsx)("univer-box-border univer-flex univer-max-w-80 univer-items-center univer-justify-between univer-overflow-hidden univer-rounded-lg univer-bg-white univer-p-3 univer-shadow dark:!univer-bg-gray-900", _univerjs_design.borderClassName),
254
+ className: (0, _univerjs_design.clsx)("univer-box-border univer-flex univer-max-w-80 univer-items-center univer-justify-between univer-overflow-hidden univer-rounded-lg univer-bg-gray-0 univer-p-3 univer-shadow dark:!univer-bg-gray-900", _univerjs_design.borderClassName),
255
+ onPointerEnter: () => {
256
+ hyperLinkService.cancelScheduledHideInfoPopup();
257
+ },
258
+ onPointerLeave: () => {
259
+ hyperLinkService.scheduleHideInfoPopup();
260
+ },
251
261
  onClick: () => {
252
262
  hyperLinkService.hideInfoPopup();
253
263
  },
@@ -255,7 +265,7 @@ const DocLinkPopup = () => {
255
265
  className: "univer-flex univer-h-6 univer-flex-1 univer-cursor-pointer univer-items-center univer-truncate univer-text-sm univer-leading-5 univer-text-primary-500",
256
266
  onClick: () => window.open(url, void 0, "noopener noreferrer"),
257
267
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
258
- className: "univer-mr-2 univer-flex univer-size-5 univer-flex-[0_0_auto] univer-items-center univer-justify-center univer-text-base univer-text-gray-900 dark:!univer-text-white",
268
+ className: "univer-mr-2 univer-flex univer-size-5 univer-flex-[0_0_auto] univer-items-center univer-justify-center univer-text-base univer-text-gray-900 dark:!univer-text-gray-0",
259
269
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.LinkIcon, {})
260
270
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
261
271
  showIfEllipsis: true,
@@ -267,49 +277,50 @@ const DocLinkPopup = () => {
267
277
  })]
268
278
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
269
279
  className: "univer-flex univer-h-6 univer-flex-[0_0_auto] univer-items-center univer-justify-center",
270
- children: [
271
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
272
- className: "univer-ml-2 univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded univer-text-base",
273
- onClick: () => {
274
- navigator.clipboard.writeText(url);
275
- messageService.show({
276
- content: localeService.t("docs-hyper-link-ui.info.coped"),
277
- type: _univerjs_design.MessageType.Info
278
- });
279
- },
280
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
281
- placement: "bottom",
282
- title: localeService.t("docs-hyper-link-ui.info.copy"),
283
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.CopyIcon, {})
284
- })
285
- }),
286
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
287
- className: "univer-ml-2 univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded univer-text-base",
288
- onClick: () => {
289
- commandService.executeCommand(ShowDocHyperLinkEditPopupOperation.id, { link: currentPopup });
290
- },
291
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
292
- placement: "bottom",
293
- title: localeService.t("docs-hyper-link-ui.info.edit"),
294
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.WriteIcon, {})
295
- })
296
- }),
297
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
298
- className: "univer-ml-2 univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded univer-text-base",
299
- onClick: () => {
300
- commandService.executeCommand(DeleteDocHyperLinkCommand.id, {
301
- unitId,
302
- linkId: link.rangeId,
303
- segmentId
304
- });
305
- },
306
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
307
- placement: "bottom",
308
- title: localeService.t("docs-hyper-link-ui.info.cancel"),
309
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.UnlinkIcon, {})
310
- })
280
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Button, {
281
+ type: "button",
282
+ variant: "text",
283
+ size: "small",
284
+ "aria-label": localeService.t("docs-hyper-link-ui.info.copy"),
285
+ className: "univer-ml-2 !univer-flex univer-size-6 !univer-rounded !univer-border-0 !univer-bg-transparent !univer-p-0 !univer-text-base !univer-font-normal hover:!univer-bg-transparent active:!univer-bg-transparent disabled:!univer-pointer-events-auto disabled:!univer-opacity-40",
286
+ disabled: !canCopy,
287
+ onClick: () => {
288
+ navigator.clipboard.writeText(url);
289
+ messageService.show({
290
+ content: localeService.t("docs-hyper-link-ui.info.coped"),
291
+ type: _univerjs_design.MessageType.Info
292
+ });
293
+ },
294
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
295
+ placement: "bottom",
296
+ title: localeService.t("docs-hyper-link-ui.info.copy"),
297
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.CopyIcon, {})
298
+ })
299
+ }), canEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
300
+ className: "univer-ml-2 univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded univer-text-base",
301
+ onClick: () => {
302
+ commandService.executeCommand(ShowDocHyperLinkEditPopupOperation.id, { link: currentPopup });
303
+ },
304
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
305
+ placement: "bottom",
306
+ title: localeService.t("docs-hyper-link-ui.info.edit"),
307
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.WriteIcon, {})
308
+ })
309
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
310
+ className: "univer-ml-2 univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded univer-text-base",
311
+ onClick: () => {
312
+ commandService.executeCommand(DeleteDocHyperLinkCommand.id, {
313
+ unitId,
314
+ linkId: link.rangeId,
315
+ segmentId
316
+ });
317
+ },
318
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
319
+ placement: "bottom",
320
+ title: localeService.t("docs-hyper-link-ui.info.cancel"),
321
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.UnlinkIcon, {})
311
322
  })
312
- ]
323
+ })] })]
313
324
  })]
314
325
  });
315
326
  };
@@ -376,22 +387,66 @@ function __decorate(decorators, target, key, desc) {
376
387
 
377
388
  //#endregion
378
389
  //#region src/services/hyper-link-popup.service.ts
390
+ /**
391
+ * Copyright 2023-present DreamNum Co., Ltd.
392
+ *
393
+ * Licensed under the Apache License, Version 2.0 (the "License");
394
+ * you may not use this file except in compliance with the License.
395
+ * You may obtain a copy of the License at
396
+ *
397
+ * http://www.apache.org/licenses/LICENSE-2.0
398
+ *
399
+ * Unless required by applicable law or agreed to in writing, software
400
+ * distributed under the License is distributed on an "AS IS" BASIS,
401
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
402
+ * See the License for the specific language governing permissions and
403
+ * limitations under the License.
404
+ */
405
+ const INFO_POPUP_HIDE_DELAY = 150;
406
+ function isSameLinkInfo(current, next) {
407
+ return (current === null || current === void 0 ? void 0 : current.linkId) === next.linkId && current.unitId === next.unitId && (current.segmentId ?? "") === (next.segmentId ?? "") && current.segmentPage === next.segmentPage && current.startIndex === next.startIndex && current.endIndex === next.endIndex;
408
+ }
379
409
  let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_core.Disposable {
380
- constructor(_docCanvasPopupManagerService, _textSelectionManagerService, _univerInstanceService) {
410
+ constructor(_docCanvasPopupManagerService, _textSelectionManagerService, _univerInstanceService, _permissionService, _renderManagerService) {
381
411
  super();
382
412
  this._docCanvasPopupManagerService = _docCanvasPopupManagerService;
383
413
  this._textSelectionManagerService = _textSelectionManagerService;
384
414
  this._univerInstanceService = _univerInstanceService;
415
+ this._permissionService = _permissionService;
416
+ this._renderManagerService = _renderManagerService;
385
417
  _defineProperty(this, "_editingLink$", new rxjs.BehaviorSubject(null));
386
418
  _defineProperty(this, "_showingLink$", new rxjs.BehaviorSubject(null));
387
419
  _defineProperty(this, "editingLink$", this._editingLink$.asObservable());
388
420
  _defineProperty(this, "showingLink$", this._showingLink$.asObservable());
389
421
  _defineProperty(this, "_editPopup", null);
422
+ _defineProperty(this, "_editPopupUnitId", null);
390
423
  _defineProperty(this, "_infoPopup", null);
424
+ _defineProperty(this, "_infoPopupPinned", false);
425
+ _defineProperty(this, "_infoPopupHideTimer", null);
426
+ _defineProperty(this, "_infoPopupSuppressed", false);
427
+ _defineProperty(this, "_infoPopupSuppressionTimer", null);
391
428
  this.disposeWithMe(() => {
429
+ this.cancelScheduledHideInfoPopup();
430
+ if (this._infoPopupSuppressionTimer !== null) clearTimeout(this._infoPopupSuppressionTimer);
392
431
  this._editingLink$.complete();
393
432
  this._showingLink$.complete();
394
433
  });
434
+ this.disposeWithMe(this._permissionService.permissionPointUpdate$.subscribe(() => {
435
+ const editing = this.editing;
436
+ if (editing && !this.canEditLink(editing.unitId, editing)) this.hideEditPopup();
437
+ const showing = this.showing;
438
+ if (showing) this._showingLink$.next({ ...showing });
439
+ }));
440
+ this.disposeWithMe(this._renderManagerService.disposed$.subscribe((unitId) => {
441
+ var _this$showing;
442
+ if (this._editPopupUnitId === unitId) this.hideEditPopup();
443
+ if (((_this$showing = this.showing) === null || _this$showing === void 0 ? void 0 : _this$showing.unitId) === unitId) this.hideInfoPopup();
444
+ }));
445
+ }
446
+ dispose() {
447
+ this.hideEditPopup();
448
+ this.hideInfoPopup();
449
+ super.dispose();
395
450
  }
396
451
  get editing() {
397
452
  return this._editingLink$.value;
@@ -399,8 +454,16 @@ let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_
399
454
  get showing() {
400
455
  return this._showingLink$.value;
401
456
  }
457
+ get infoPopupPinned() {
458
+ return this._infoPopupPinned;
459
+ }
402
460
  showEditPopup(unitId, linkInfo) {
403
- if (this._editPopup) this._editPopup.dispose();
461
+ if (!this.canEditLink(unitId, linkInfo)) return null;
462
+ if (this._editPopup) {
463
+ this._editPopup.dispose();
464
+ this._editPopup = null;
465
+ this._editPopupUnitId = null;
466
+ }
404
467
  this._editingLink$.next(linkInfo);
405
468
  const textRanges = this._textSelectionManagerService.getTextRanges({
406
469
  unitId,
@@ -424,8 +487,10 @@ let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_
424
487
  if (activeRange) {
425
488
  this._editPopup = this._docCanvasPopupManagerService.attachPopupToRange(activeRange, {
426
489
  componentKey: DocHyperLinkEdit.componentKey,
427
- direction: "bottom"
490
+ direction: "bottom",
491
+ offset: [0, 10]
428
492
  }, unitId);
493
+ this._editPopupUnitId = unitId;
429
494
  return this._editPopup;
430
495
  }
431
496
  return null;
@@ -434,13 +499,23 @@ let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_
434
499
  var _this$_editPopup;
435
500
  this._editingLink$.next(null);
436
501
  (_this$_editPopup = this._editPopup) === null || _this$_editPopup === void 0 || _this$_editPopup.dispose();
502
+ this._editPopup = null;
503
+ this._editPopupUnitId = null;
437
504
  }
438
- showInfoPopup(info) {
439
- var _this$showing, _this$showing2, _this$showing3, _this$showing4, _this$showing5, _this$showing6;
505
+ showInfoPopup(info, options) {
506
+ this.cancelScheduledHideInfoPopup();
507
+ if (this._infoPopupSuppressed) return;
440
508
  const { linkId, unitId, segmentId, segmentPage, startIndex, endIndex } = info;
441
- if (((_this$showing = this.showing) === null || _this$showing === void 0 ? void 0 : _this$showing.linkId) === linkId && ((_this$showing2 = this.showing) === null || _this$showing2 === void 0 ? void 0 : _this$showing2.unitId) === unitId && ((_this$showing3 = this.showing) === null || _this$showing3 === void 0 ? void 0 : _this$showing3.segmentId) === segmentId && ((_this$showing4 = this.showing) === null || _this$showing4 === void 0 ? void 0 : _this$showing4.segmentPage) === segmentPage && ((_this$showing5 = this.showing) === null || _this$showing5 === void 0 ? void 0 : _this$showing5.startIndex) === startIndex && ((_this$showing6 = this.showing) === null || _this$showing6 === void 0 ? void 0 : _this$showing6.endIndex) === endIndex) return;
442
- if (this._infoPopup) this._infoPopup.dispose();
443
- if (!this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC)) return;
509
+ if (isSameLinkInfo(this.showing, info)) {
510
+ if (options === null || options === void 0 ? void 0 : options.pinned) this._infoPopupPinned = true;
511
+ return;
512
+ }
513
+ if (this._infoPopup) {
514
+ this._infoPopup.dispose();
515
+ this._infoPopup = null;
516
+ }
517
+ if (!(this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC) instanceof _univerjs_core.DocumentDataModel)) return;
518
+ this._infoPopupPinned = (options === null || options === void 0 ? void 0 : options.pinned) ?? false;
444
519
  this._showingLink$.next({
445
520
  unitId,
446
521
  linkId,
@@ -459,6 +534,7 @@ let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_
459
534
  componentKey: DocLinkPopup.componentKey,
460
535
  direction: "top-center",
461
536
  multipleDirection: "top",
537
+ offset: [0, 10],
462
538
  onClickOutside: () => {
463
539
  this.hideInfoPopup();
464
540
  }
@@ -467,14 +543,49 @@ let DocHyperLinkPopupService = class DocHyperLinkPopupService extends _univerjs_
467
543
  }
468
544
  hideInfoPopup() {
469
545
  var _this$_infoPopup;
546
+ this.cancelScheduledHideInfoPopup();
547
+ this._infoPopupPinned = false;
470
548
  this._showingLink$.next(null);
471
549
  (_this$_infoPopup = this._infoPopup) === null || _this$_infoPopup === void 0 || _this$_infoPopup.dispose();
550
+ this._infoPopup = null;
551
+ }
552
+ scheduleHideInfoPopup() {
553
+ if (this._infoPopupPinned || !this.showing) return;
554
+ this.cancelScheduledHideInfoPopup();
555
+ this._infoPopupHideTimer = setTimeout(() => {
556
+ this._infoPopupHideTimer = null;
557
+ if (!this._infoPopupPinned) this.hideInfoPopup();
558
+ }, INFO_POPUP_HIDE_DELAY);
559
+ }
560
+ cancelScheduledHideInfoPopup() {
561
+ if (this._infoPopupHideTimer !== null) {
562
+ clearTimeout(this._infoPopupHideTimer);
563
+ this._infoPopupHideTimer = null;
564
+ }
565
+ }
566
+ hideInfoPopupOnPointerDown() {
567
+ this._infoPopupSuppressed = true;
568
+ if (this._infoPopupSuppressionTimer !== null) clearTimeout(this._infoPopupSuppressionTimer);
569
+ this.hideInfoPopup();
570
+ this._infoPopupSuppressionTimer = setTimeout(() => {
571
+ this._infoPopupSuppressed = false;
572
+ this._infoPopupSuppressionTimer = null;
573
+ }, 0);
574
+ }
575
+ canEditLink(unitId, linkInfo) {
576
+ const document = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
577
+ if (!(document instanceof _univerjs_core.DocumentDataModel)) return false;
578
+ if (!linkInfo) return (0, _univerjs_docs.canEditDocumentTargets)(this._permissionService, unitId, []);
579
+ const segmentId = linkInfo.segmentId ?? "";
580
+ return (0, _univerjs_docs.canEditDocumentTargets)(this._permissionService, unitId, [...(0, _univerjs_docs.getDocumentEntityParentPermissionObjectIds)(document, segmentId, "custom-range", linkInfo.linkId), (0, _univerjs_docs.getDocumentEntityPermissionObjectId)(segmentId, "custom-range", linkInfo.linkId)]);
472
581
  }
473
582
  };
474
583
  DocHyperLinkPopupService = __decorate([
475
584
  __decorateParam(0, (0, _univerjs_core.Inject)(_univerjs_docs_ui.DocCanvasPopManagerService)),
476
585
  __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_docs.DocSelectionManagerService)),
477
- __decorateParam(2, _univerjs_core.IUniverInstanceService)
586
+ __decorateParam(2, _univerjs_core.IUniverInstanceService),
587
+ __decorateParam(3, _univerjs_core.IPermissionService),
588
+ __decorateParam(4, _univerjs_engine_render.IRenderManagerService)
478
589
  ], DocHyperLinkPopupService);
479
590
 
480
591
  //#endregion
@@ -499,7 +610,7 @@ const ShowDocHyperLinkEditPopupOperation = {
499
610
  const hyperLinkService = accessor.get(DocHyperLinkPopupService);
500
611
  const unitId = (linkInfo === null || linkInfo === void 0 ? void 0 : linkInfo.unitId) || ((_univerInstanceServic = univerInstanceService.getCurrentUnitOfType(_univerjs_core.UniverInstanceType.UNIVER_DOC)) === null || _univerInstanceServic === void 0 ? void 0 : _univerInstanceServic.getUnitId());
501
612
  if (!unitId) return false;
502
- hyperLinkService.showEditPopup(unitId, linkInfo);
613
+ hyperLinkService.showEditPopup(unitId, linkInfo ?? null);
503
614
  return true;
504
615
  }
505
616
  };
@@ -589,7 +700,7 @@ const menuSchema = {
589
700
  //#endregion
590
701
  //#region package.json
591
702
  var name = "@univerjs/docs-hyper-link-ui";
592
- var version = "1.0.0-insiders.20260809-70eefdd";
703
+ var version = "1.0.0-rc.0";
593
704
 
594
705
  //#endregion
595
706
  //#region src/config/config.ts
@@ -649,25 +760,23 @@ let DocHyperLinkSelectionController = class DocHyperLinkSelectionController exte
649
760
  const { unitId, ranges, segmentId } = commandInfo.params;
650
761
  const doc = this._univerInstanceService.getUnit(unitId, _univerjs_core.UniverInstanceType.UNIVER_DOC);
651
762
  const primary = ranges[0];
652
- if (primary && doc) {
763
+ if ((primary === null || primary === void 0 ? void 0 : primary.collapsed) && doc) {
653
764
  var _doc$getSelfOrHeaderF;
654
- const { startOffset, endOffset, collapsed, segmentPage } = primary;
765
+ const { startOffset, endOffset, segmentPage } = primary;
655
766
  const customRanges = (_doc$getSelfOrHeaderF = doc.getSelfOrHeaderFooterModel(segmentId)) === null || _doc$getSelfOrHeaderF === void 0 || (_doc$getSelfOrHeaderF = _doc$getSelfOrHeaderF.getBody()) === null || _doc$getSelfOrHeaderF === void 0 ? void 0 : _doc$getSelfOrHeaderF.customRanges;
656
- if (collapsed) {
657
- const index = (customRanges === null || customRanges === void 0 ? void 0 : customRanges.findIndex((value) => value.startIndex < startOffset && value.endIndex > endOffset - 1)) ?? -1;
658
- if (index > -1) {
659
- const customRange = customRanges[index];
660
- this._docHyperLinkService.showInfoPopup({
661
- unitId,
662
- linkId: customRange.rangeId,
663
- segmentId,
664
- segmentPage,
665
- startIndex: customRange.startIndex,
666
- endIndex: customRange.endIndex
667
- });
668
- return;
669
- }
670
- } else if (customRanges === null || customRanges === void 0 ? void 0 : customRanges.find((value) => value.startIndex <= startOffset && value.endIndex >= endOffset - 1)) return;
767
+ const showing = this._docHyperLinkService.showing;
768
+ const customRange = ((showing === null || showing === void 0 ? void 0 : showing.unitId) === unitId && (showing.segmentId ?? "") === segmentId && showing.segmentPage === segmentPage && showing.endIndex === endOffset - 1 ? customRanges === null || customRanges === void 0 ? void 0 : customRanges.find((value) => value.rangeId === showing.linkId && value.rangeType === _univerjs_core.CustomRangeType.HYPERLINK && value.startIndex <= startOffset && value.endIndex === endOffset - 1) : void 0) ?? (customRanges === null || customRanges === void 0 ? void 0 : customRanges.find((value) => value.rangeType === _univerjs_core.CustomRangeType.HYPERLINK && value.startIndex <= startOffset && value.endIndex > endOffset - 1));
769
+ if (customRange) {
770
+ this._docHyperLinkService.showInfoPopup({
771
+ unitId,
772
+ linkId: customRange.rangeId,
773
+ segmentId,
774
+ segmentPage,
775
+ startIndex: customRange.startIndex,
776
+ endIndex: customRange.endIndex
777
+ });
778
+ return;
779
+ }
671
780
  }
672
781
  this._docHyperLinkService.hideInfoPopup();
673
782
  this._docHyperLinkService.hideEditPopup();
@@ -696,11 +805,18 @@ let DocHyperLinkEventRenderController = class DocHyperLinkEventRenderController
696
805
  this._docSkeletonManagerService = _docSkeletonManagerService;
697
806
  this._docSelectionManagerService = _docSelectionManagerService;
698
807
  if (this._context.unitId === _univerjs_core.DOCS_NORMAL_EDITOR_UNIT_ID_KEY) return;
808
+ this._initPointerDown();
699
809
  this._initHover();
700
810
  this._initClick();
701
811
  }
702
812
  _hideInfoPopup() {
703
- if (this._hyperLinkPopupService.showing) this._commandService.executeCommand(ToggleDocHyperLinkInfoPopupOperation.id);
813
+ if (this._hyperLinkPopupService.infoPopupPinned) return;
814
+ if (this._hyperLinkPopupService.showing) this._hyperLinkPopupService.scheduleHideInfoPopup();
815
+ }
816
+ _initPointerDown() {
817
+ this.disposeWithMe(this._docEventManagerService.pointerDownCustomRanges$.subscribe((ranges) => {
818
+ if (!ranges.some((range) => range.range.rangeType === _univerjs_core.CustomRangeType.HYPERLINK)) this._hyperLinkPopupService.hideInfoPopupOnPointerDown();
819
+ }));
704
820
  }
705
821
  _initHover() {
706
822
  this.disposeWithMe(this._docEventManagerService.hoverCustomRanges$.subscribe((ranges) => {
@@ -727,7 +843,19 @@ let DocHyperLinkEventRenderController = class DocHyperLinkEventRenderController
727
843
  _initClick() {
728
844
  this.disposeWithMe(this._docEventManagerService.clickCustomRanges$.subscribe((range) => {
729
845
  const link = range.range;
730
- if (link) this._commandService.executeCommand(ClickDocHyperLinkOperation.id, {
846
+ if (link.rangeType !== _univerjs_core.CustomRangeType.HYPERLINK) return;
847
+ if (!range.ctrlKey && !range.metaKey) {
848
+ this._hyperLinkPopupService.showInfoPopup({
849
+ unitId: this._context.unitId,
850
+ linkId: link.rangeId,
851
+ segmentId: range.segmentId,
852
+ segmentPage: range.segmentPageIndex,
853
+ startIndex: link.startIndex,
854
+ endIndex: link.endIndex
855
+ }, { pinned: true });
856
+ return;
857
+ }
858
+ this._commandService.executeCommand(ClickDocHyperLinkOperation.id, {
731
859
  unitId: this._context.unitId,
732
860
  linkId: link.rangeId,
733
861
  segmentId: range.segmentId
@@ -746,14 +874,11 @@ DocHyperLinkEventRenderController = __decorate([
746
874
  //#endregion
747
875
  //#region src/controllers/render-controllers/render.controller.ts
748
876
  let DocHyperLinkRenderController = class DocHyperLinkRenderController extends _univerjs_core.Disposable {
749
- constructor(_context, _docInterceptorService, _hyperLinkService, _docRenderController) {
877
+ constructor(_context, _docInterceptorService, _hyperLinkService) {
750
878
  super();
751
- this._context = _context;
752
879
  this._docInterceptorService = _docInterceptorService;
753
880
  this._hyperLinkService = _hyperLinkService;
754
- this._docRenderController = _docRenderController;
755
881
  this._init();
756
- this._initReRender();
757
882
  }
758
883
  _init() {
759
884
  this._docInterceptorService.intercept(_univerjs_docs.DOC_INTERCEPTOR_POINT.CUSTOM_RANGE, { handler: (data, pos, next) => {
@@ -772,19 +897,8 @@ let DocHyperLinkRenderController = class DocHyperLinkRenderController extends _u
772
897
  });
773
898
  } });
774
899
  }
775
- _initReRender() {
776
- this.disposeWithMe(this._hyperLinkService.showingLink$.pipe((0, rxjs.distinctUntilChanged)((prev, aft) => (prev === null || prev === void 0 ? void 0 : prev.linkId) === (aft === null || aft === void 0 ? void 0 : aft.linkId) && (prev === null || prev === void 0 ? void 0 : prev.unitId) === (aft === null || aft === void 0 ? void 0 : aft.unitId) && (prev === null || prev === void 0 ? void 0 : prev.startIndex) === (aft === null || aft === void 0 ? void 0 : aft.startIndex)), (0, rxjs.pairwise)()).subscribe(([preLink, link]) => {
777
- if (link) {
778
- if (link.unitId === this._context.unitId) this._docRenderController.reRender(link.unitId);
779
- } else if (preLink && preLink.unitId === this._context.unitId) this._docRenderController.reRender(preLink.unitId);
780
- }));
781
- }
782
900
  };
783
- DocHyperLinkRenderController = __decorate([
784
- __decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_docs.DocInterceptorService)),
785
- __decorateParam(2, (0, _univerjs_core.Inject)(DocHyperLinkPopupService)),
786
- __decorateParam(3, (0, _univerjs_core.Inject)(_univerjs_docs_ui.DocRenderController))
787
- ], DocHyperLinkRenderController);
901
+ DocHyperLinkRenderController = __decorate([__decorateParam(1, (0, _univerjs_core.Inject)(_univerjs_docs.DocInterceptorService)), __decorateParam(2, (0, _univerjs_core.Inject)(DocHyperLinkPopupService))], DocHyperLinkRenderController);
788
902
 
789
903
  //#endregion
790
904
  //#region src/controllers/ui.controller.ts
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "تأكيد",
6
6
  cancel: "إلغاء",
7
- title: "ارتباط",
8
7
  address: "ارتباط",
9
- placeholder: "يُرجى إدخال عنوان URL للارتباط",
10
8
  addressError: "عنوان URL غير قانوني!",
11
9
  label: "تسمية",
12
10
  labelError: "يُرجى إدخال تسمية الارتباط"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Confirma",
6
6
  cancel: "Cancel·la",
7
- title: "Enllaç",
8
7
  address: "Enllaç",
9
- placeholder: "Si us plau, introdueix una URL",
10
8
  addressError: "La URL no és vàlida!",
11
9
  label: "Etiqueta",
12
10
  labelError: "Si us plau, introdueix l'etiqueta de l'enllaç"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Bestätigen",
6
6
  cancel: "Abbrechen",
7
- title: "Link",
8
7
  address: "Link",
9
- placeholder: "Bitte eine Link-URL eingeben",
10
8
  addressError: "URL ist ungültig!",
11
9
  label: "Bezeichnung",
12
10
  labelError: "Bitte die Bezeichnung des Links eingeben"
@@ -19,9 +19,7 @@ const locale = { "docs-hyper-link-ui": {
19
19
  edit: {
20
20
  confirm: "Confirm",
21
21
  cancel: "Cancel",
22
- title: "Link",
23
22
  address: "Link",
24
- placeholder: "Please input a link url",
25
23
  addressError: "Url is illegal!",
26
24
  label: "Label",
27
25
  labelError: "Please input label of link"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Confirmar",
6
6
  cancel: "Cancelar",
7
- title: "Enlace",
8
7
  address: "Enlace",
9
- placeholder: "Por favor, introduce una URL",
10
8
  addressError: "¡La URL no es válida!",
11
9
  label: "Etiqueta",
12
10
  labelError: "Por favor, introduce la etiqueta del enlace"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "تایید",
6
6
  cancel: "انصراف",
7
- title: "لینک",
8
7
  address: "لینک",
9
- placeholder: "لطفا یک آدرس لینک وارد کنید",
10
8
  addressError: "آدرس غیرمجاز است!",
11
9
  label: "برچسب",
12
10
  labelError: "لطفا برچسب لینک را وارد کنید"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Confirmer",
6
6
  cancel: "Annuler",
7
- title: "Lien",
8
7
  address: "Lien",
9
- placeholder: "Veuillez entrer un lien",
10
8
  addressError: "L'url est illégal!",
11
9
  label: "Libellé",
12
10
  labelError: "Veuillez entrer le label du lien"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Konfirmasi",
6
6
  cancel: "Batal",
7
- title: "Tautan",
8
7
  address: "Tautan",
9
- placeholder: "Silakan masukkan URL tautan",
10
8
  addressError: "URL tidak valid!",
11
9
  label: "Label",
12
10
  labelError: "Silakan masukkan label tautan"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Conferma",
6
6
  cancel: "Annulla",
7
- title: "Collegamento",
8
7
  address: "Collegamento",
9
- placeholder: "Inserisci un URL di collegamento",
10
8
  addressError: "URL non valido!",
11
9
  label: "Etichetta",
12
10
  labelError: "Inserisci l'etichetta del collegamento"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "OK",
6
6
  cancel: "キャンセル",
7
- title: "リンク",
8
7
  address: "アドレス",
9
- placeholder: "リンクのURLを入力してください",
10
8
  addressError: "URLが正しくありません!",
11
9
  label: "表示文字列",
12
10
  labelError: "リンクの表示文字列を入力してください"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "확인",
6
6
  cancel: "취소",
7
- title: "링크",
8
7
  address: "링크",
9
- placeholder: "링크 URL을 입력해주세요",
10
8
  addressError: "URL이 올바르지 않습니다!",
11
9
  label: "라벨",
12
10
  labelError: "링크 라벨을 입력해주세요"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Potwierdź",
6
6
  cancel: "Anuluj",
7
- title: "Łącze",
8
7
  address: "Łącze",
9
- placeholder: "Wprowadź adres URL",
10
8
  addressError: "Adres URL jest nieprawidłowy!",
11
9
  label: "Etykieta",
12
10
  labelError: "Wprowadź etykietę łącza"
@@ -4,9 +4,7 @@ const locale = { "docs-hyper-link-ui": {
4
4
  edit: {
5
5
  confirm: "Confirmar",
6
6
  cancel: "Cancelar",
7
- title: "Link",
8
7
  address: "Link",
9
- placeholder: "Insira uma URL de link",
10
8
  addressError: "URL inválida!",
11
9
  label: "Rótulo",
12
10
  labelError: "Insira o rótulo do link"