@univerjs/sheets-drawing-ui 1.0.3 → 1.0.4

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/lib/cjs/index.js +425 -12
  2. package/lib/cjs/locale/ar-SA.js +1 -0
  3. package/lib/cjs/locale/ca-ES.js +1 -0
  4. package/lib/cjs/locale/de-DE.js +1 -0
  5. package/lib/cjs/locale/en-US.js +1 -0
  6. package/lib/cjs/locale/es-ES.js +1 -0
  7. package/lib/cjs/locale/fa-IR.js +1 -0
  8. package/lib/cjs/locale/fr-FR.js +1 -0
  9. package/lib/cjs/locale/id-ID.js +1 -0
  10. package/lib/cjs/locale/it-IT.js +1 -0
  11. package/lib/cjs/locale/ja-JP.js +1 -0
  12. package/lib/cjs/locale/ko-KR.js +1 -0
  13. package/lib/cjs/locale/pl-PL.js +1 -0
  14. package/lib/cjs/locale/pt-BR.js +1 -0
  15. package/lib/cjs/locale/ru-RU.js +1 -0
  16. package/lib/cjs/locale/sk-SK.js +1 -0
  17. package/lib/cjs/locale/vi-VN.js +1 -0
  18. package/lib/cjs/locale/zh-CN.js +1 -0
  19. package/lib/cjs/locale/zh-HK.js +1 -0
  20. package/lib/cjs/locale/zh-TW.js +1 -0
  21. package/lib/es/index.js +430 -17
  22. package/lib/es/locale/ar-SA.js +1 -0
  23. package/lib/es/locale/ca-ES.js +1 -0
  24. package/lib/es/locale/de-DE.js +1 -0
  25. package/lib/es/locale/en-US.js +1 -0
  26. package/lib/es/locale/es-ES.js +1 -0
  27. package/lib/es/locale/fa-IR.js +1 -0
  28. package/lib/es/locale/fr-FR.js +1 -0
  29. package/lib/es/locale/id-ID.js +1 -0
  30. package/lib/es/locale/it-IT.js +1 -0
  31. package/lib/es/locale/ja-JP.js +1 -0
  32. package/lib/es/locale/ko-KR.js +1 -0
  33. package/lib/es/locale/pl-PL.js +1 -0
  34. package/lib/es/locale/pt-BR.js +1 -0
  35. package/lib/es/locale/ru-RU.js +1 -0
  36. package/lib/es/locale/sk-SK.js +1 -0
  37. package/lib/es/locale/vi-VN.js +1 -0
  38. package/lib/es/locale/zh-CN.js +1 -0
  39. package/lib/es/locale/zh-HK.js +1 -0
  40. package/lib/es/locale/zh-TW.js +1 -0
  41. package/lib/index.css +290 -0
  42. package/lib/index.js +430 -17
  43. package/lib/locale/ar-SA.js +1 -0
  44. package/lib/locale/ca-ES.js +1 -0
  45. package/lib/locale/de-DE.js +1 -0
  46. package/lib/locale/en-US.js +1 -0
  47. package/lib/locale/es-ES.js +1 -0
  48. package/lib/locale/fa-IR.js +1 -0
  49. package/lib/locale/fr-FR.js +1 -0
  50. package/lib/locale/id-ID.js +1 -0
  51. package/lib/locale/it-IT.js +1 -0
  52. package/lib/locale/ja-JP.js +1 -0
  53. package/lib/locale/ko-KR.js +1 -0
  54. package/lib/locale/pl-PL.js +1 -0
  55. package/lib/locale/pt-BR.js +1 -0
  56. package/lib/locale/ru-RU.js +1 -0
  57. package/lib/locale/sk-SK.js +1 -0
  58. package/lib/locale/vi-VN.js +1 -0
  59. package/lib/locale/zh-CN.js +1 -0
  60. package/lib/locale/zh-HK.js +1 -0
  61. package/lib/locale/zh-TW.js +1 -0
  62. package/lib/types/commands/operations/preview-sheet-image-opacity.operation.d.ts +20 -0
  63. package/lib/types/controllers/sheet-drawing-active-render.controller.d.ts +4 -0
  64. package/lib/types/locale/en-US.d.ts +3 -0
  65. package/lib/types/views/sheet-image-panel/SheetImageTransparency.d.ts +20 -0
  66. package/lib/types/views/sheet-image-panel/SheetImageTransparencySlider.d.ts +24 -0
  67. package/lib/types/views/sheet-image-panel/sheet-drawing-panel.util.d.ts +18 -0
  68. package/lib/umd/index.js +2 -2
  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 +14 -14
package/lib/cjs/index.js CHANGED
@@ -3718,7 +3718,7 @@ const menuSchema = {
3718
3718
  //#endregion
3719
3719
  //#region package.json
3720
3720
  var name = "@univerjs/sheets-drawing-ui";
3721
- var version = "1.0.3";
3721
+ var version = "1.0.4";
3722
3722
 
3723
3723
  //#endregion
3724
3724
  //#region src/config/config.ts
@@ -3949,9 +3949,19 @@ function MobileBatchSaveImagesDialog() {
3949
3949
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BatchSaveImagesDialog, { SelectComponent: _univerjs_design.MobileSelect });
3950
3950
  }
3951
3951
 
3952
+ //#endregion
3953
+ //#region src/views/sheet-image-panel/sheet-drawing-panel.util.ts
3954
+ function isSheetDrawing(drawing) {
3955
+ return Boolean(drawing && "sheetTransform" in drawing && drawing.sheetTransform);
3956
+ }
3957
+
3952
3958
  //#endregion
3953
3959
  //#region src/views/sheet-image-panel/SheetDrawingAnchor.tsx
3954
3960
  const SheetDrawingAnchor = (props) => {
3961
+ function getAnchorKind(value) {
3962
+ if (value === _univerjs_sheets_drawing.SheetDrawingAnchorType.Position || value === _univerjs_sheets_drawing.SheetDrawingAnchorType.Both || value === _univerjs_sheets_drawing.SheetDrawingAnchorType.None) return value;
3963
+ return null;
3964
+ }
3955
3965
  const commandService = (0, _univerjs_ui.useDependency)(_univerjs_core.ICommandService);
3956
3966
  const localeService = (0, _univerjs_ui.useDependency)(_univerjs_core.LocaleService);
3957
3967
  const drawingManagerService = (0, _univerjs_ui.useDependency)(_univerjs_drawing.IDrawingManagerService);
@@ -4067,12 +4077,389 @@ const SheetDrawingAnchor = (props) => {
4067
4077
  }) })]
4068
4078
  });
4069
4079
  };
4070
- function isSheetDrawing(drawing) {
4071
- return Boolean(drawing && "sheetTransform" in drawing && "axisAlignSheetTransform" in drawing);
4080
+
4081
+ //#endregion
4082
+ //#region src/commands/operations/preview-sheet-image-opacity.operation.ts
4083
+ const PreviewSheetImageOpacityOperation = {
4084
+ id: "sheet.operation.preview-image-opacity",
4085
+ type: _univerjs_core.CommandType.OPERATION,
4086
+ handler: (accessor, params) => {
4087
+ var _renderManagerService;
4088
+ if (!params || !Number.isFinite(params.opacity)) return false;
4089
+ const scene = (_renderManagerService = accessor.get(_univerjs_engine_render.IRenderManagerService).getRenderUnitById(params.unitId)) === null || _renderManagerService === void 0 ? void 0 : _renderManagerService.scene;
4090
+ const image = scene === null || scene === void 0 ? void 0 : scene.getObject((0, _univerjs_drawing.getDrawingShapeKeyByDrawingSearch)(params));
4091
+ if (!(image instanceof _univerjs_engine_render.Image)) return false;
4092
+ image.setOpacity(Math.min(Math.max(params.opacity, 0), 1));
4093
+ return true;
4094
+ }
4095
+ };
4096
+
4097
+ //#endregion
4098
+ //#region src/views/sheet-image-panel/SheetImageTransparencySlider.tsx
4099
+ const MIN_TRANSPARENCY = 0;
4100
+ const MAX_TRANSPARENCY = 100;
4101
+ const TRANSPARENCY_STEP = 1;
4102
+ const TRANSPARENCY_PAGE_STEP = 10;
4103
+ const DRAG_PREVIEW_INTERVAL = 50;
4104
+ function SheetImageTransparencySlider(props) {
4105
+ const { value, shortcuts, ariaLabel, disabled = false, onChange, onChangeComplete } = props;
4106
+ const localeService = (0, _univerjs_ui.useDependency)(_univerjs_core.LocaleService);
4107
+ const isRtl = (0, _univerjs_ui.useObservable)(localeService.direction$, localeService.getDirection()) === "rtl";
4108
+ const sliderRailRef = (0, react.useRef)(null);
4109
+ const dragValueRef = (0, react.useRef)(value);
4110
+ const pendingDragValueRef = (0, react.useRef)(null);
4111
+ const lastPreviewedDragValueRef = (0, react.useRef)(value);
4112
+ const dragPreviewTimerRef = (0, react.useRef)(null);
4113
+ const dragCleanupRef = (0, react.useRef)(null);
4114
+ const [isDragging, setIsDragging] = (0, react.useState)(false);
4115
+ const [dragValue, setDragValue] = (0, react.useState)(value);
4116
+ (0, react.useEffect)(() => () => {
4117
+ var _dragCleanupRef$curre;
4118
+ (_dragCleanupRef$curre = dragCleanupRef.current) === null || _dragCleanupRef$curre === void 0 || _dragCleanupRef$curre.call(dragCleanupRef);
4119
+ clearDragPreviewTimer();
4120
+ }, []);
4121
+ function getValueByClientX(clientX) {
4122
+ const rail = sliderRailRef.current;
4123
+ if (!rail) return value;
4124
+ const railRect = rail.getBoundingClientRect();
4125
+ if (railRect.width <= 0) return value;
4126
+ let ratio = (clientX - railRect.left) / railRect.width;
4127
+ ratio = Math.min(Math.max(ratio, 0), 1);
4128
+ if (isRtl) ratio = 1 - ratio;
4129
+ return normalizeTransparency$1(MIN_TRANSPARENCY + ratio * 100);
4130
+ }
4131
+ function clearDragPreviewTimer() {
4132
+ if (dragPreviewTimerRef.current != null) {
4133
+ window.clearTimeout(dragPreviewTimerRef.current);
4134
+ dragPreviewTimerRef.current = null;
4135
+ }
4136
+ }
4137
+ function previewDragValue(nextValue) {
4138
+ if (nextValue === lastPreviewedDragValueRef.current) return;
4139
+ lastPreviewedDragValueRef.current = nextValue;
4140
+ onChange === null || onChange === void 0 || onChange(nextValue);
4141
+ }
4142
+ function flushDragPreview() {
4143
+ clearDragPreviewTimer();
4144
+ const nextValue = pendingDragValueRef.current;
4145
+ pendingDragValueRef.current = null;
4146
+ if (nextValue != null) previewDragValue(nextValue);
4147
+ }
4148
+ function scheduleDragPreview(nextValue) {
4149
+ pendingDragValueRef.current = nextValue;
4150
+ if (dragPreviewTimerRef.current != null) return;
4151
+ dragPreviewTimerRef.current = window.setTimeout(() => {
4152
+ dragPreviewTimerRef.current = null;
4153
+ const pendingValue = pendingDragValueRef.current;
4154
+ pendingDragValueRef.current = null;
4155
+ if (pendingValue != null) previewDragValue(pendingValue);
4156
+ }, DRAG_PREVIEW_INTERVAL);
4157
+ }
4158
+ function updateDragValue(clientX) {
4159
+ const nextValue = getValueByClientX(clientX);
4160
+ dragValueRef.current = nextValue;
4161
+ setDragValue(nextValue);
4162
+ return nextValue;
4163
+ }
4164
+ function handlePointerDown(e) {
4165
+ var _dragCleanupRef$curre2;
4166
+ if (disabled) return;
4167
+ e.preventDefault();
4168
+ e.stopPropagation();
4169
+ (_dragCleanupRef$curre2 = dragCleanupRef.current) === null || _dragCleanupRef$curre2 === void 0 || _dragCleanupRef$curre2.call(dragCleanupRef);
4170
+ clearDragPreviewTimer();
4171
+ pendingDragValueRef.current = null;
4172
+ lastPreviewedDragValueRef.current = value;
4173
+ setIsDragging(true);
4174
+ scheduleDragPreview(updateDragValue(e.clientX));
4175
+ function cleanup() {
4176
+ window.removeEventListener("pointermove", handlePointerMove);
4177
+ window.removeEventListener("pointerup", handlePointerUp);
4178
+ window.removeEventListener("pointercancel", handlePointerUp);
4179
+ dragCleanupRef.current = null;
4180
+ }
4181
+ function handlePointerMove(event) {
4182
+ scheduleDragPreview(updateDragValue(event.clientX));
4183
+ }
4184
+ function handlePointerUp() {
4185
+ cleanup();
4186
+ flushDragPreview();
4187
+ setIsDragging(false);
4188
+ onChangeComplete === null || onChangeComplete === void 0 || onChangeComplete(dragValueRef.current);
4189
+ }
4190
+ dragCleanupRef.current = cleanup;
4191
+ window.addEventListener("pointermove", handlePointerMove);
4192
+ window.addEventListener("pointerup", handlePointerUp);
4193
+ window.addEventListener("pointercancel", handlePointerUp);
4194
+ }
4195
+ function handleSliderKeyDown(e) {
4196
+ let nextValue = null;
4197
+ if (e.key === "ArrowLeft" || e.key === "ArrowDown") nextValue = value - TRANSPARENCY_STEP;
4198
+ else if (e.key === "ArrowRight" || e.key === "ArrowUp") nextValue = value + TRANSPARENCY_STEP;
4199
+ else if (e.key === "PageDown") nextValue = value - TRANSPARENCY_PAGE_STEP;
4200
+ else if (e.key === "PageUp") nextValue = value + TRANSPARENCY_PAGE_STEP;
4201
+ else if (e.key === "Home") nextValue = MIN_TRANSPARENCY;
4202
+ else if (e.key === "End") nextValue = MAX_TRANSPARENCY;
4203
+ if (nextValue == null || disabled) return;
4204
+ e.preventDefault();
4205
+ e.stopPropagation();
4206
+ const normalizedValue = normalizeTransparency$1(nextValue);
4207
+ onChange === null || onChange === void 0 || onChange(normalizedValue);
4208
+ onChangeComplete === null || onChangeComplete === void 0 || onChangeComplete(normalizedValue);
4209
+ }
4210
+ const visualValue = isDragging ? dragValue : value;
4211
+ const sliderOffset = normalizeTransparency$1(visualValue);
4212
+ const handleOffset = isRtl ? MAX_TRANSPARENCY - sliderOffset : sliderOffset;
4213
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4214
+ className: (0, _univerjs_design.clsx)("univer-flex univer-select-none univer-items-center univer-gap-1.5", { "univer-cursor-not-allowed": disabled }),
4215
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4216
+ className: "univer-flex univer-h-6 univer-min-w-0 univer-flex-1 univer-items-center",
4217
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4218
+ className: (0, _univerjs_design.clsx)("univer-relative univer-h-1.5 univer-w-full univer-rounded-full univer-bg-gray-200 univer-px-1.5 univer-transition-colors dark:!univer-bg-gray-600", { "univer-opacity-60": disabled }),
4219
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4220
+ ref: sliderRailRef,
4221
+ "data-u-comp": "sheet-image-transparency-slider-track",
4222
+ className: "univer-relative univer-h-1.5 univer-bg-gray-200 dark:!univer-bg-gray-600",
4223
+ onPointerDown: handlePointerDown,
4224
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4225
+ className: (0, _univerjs_design.clsx)("univer-bg-primary-500/60 univer-absolute univer-top-0 univer-h-full univer-rounded-full", isRtl ? "univer-right-0" : "univer-left-0"),
4226
+ style: { width: `${sliderOffset}%` }
4227
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4228
+ className: (0, _univerjs_design.clsx)("univer-absolute univer-top-1/2 univer-size-3.5 -univer-translate-x-1/2 -univer-translate-y-1/2 univer-rounded-full univer-bg-gray-0 univer-shadow-sm focus-visible:univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-primary-100 dark:!univer-bg-gray-800", _univerjs_design.borderClassName, {
4229
+ "univer-cursor-pointer hover:univer-border-primary-600 hover:univer-shadow-md": !disabled,
4230
+ "univer-cursor-not-allowed": disabled,
4231
+ "univer-scale-105 univer-border-primary-600 univer-shadow-md": isDragging,
4232
+ "univer-transition-all": !isDragging,
4233
+ "univer-transition-none": isDragging
4234
+ }),
4235
+ role: "slider",
4236
+ "aria-label": ariaLabel,
4237
+ "aria-valuemin": MIN_TRANSPARENCY,
4238
+ "aria-valuemax": MAX_TRANSPARENCY,
4239
+ "aria-valuenow": visualValue,
4240
+ "aria-valuetext": `${visualValue}%`,
4241
+ disabled,
4242
+ type: "button",
4243
+ style: { left: `${handleOffset}%` },
4244
+ onKeyDown: handleSliderKeyDown
4245
+ })]
4246
+ })
4247
+ })
4248
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetImageTransparencyInput, {
4249
+ value,
4250
+ shortcuts,
4251
+ ariaLabel,
4252
+ disabled,
4253
+ onChange,
4254
+ onChangeComplete
4255
+ })]
4256
+ });
4257
+ }
4258
+ function SheetImageTransparencyInput(props) {
4259
+ const { value, shortcuts, ariaLabel, disabled = false, onChange, onChangeComplete } = props;
4260
+ const iconManager = (0, _univerjs_ui.useDependency)(_univerjs_ui.IconManager);
4261
+ const isEditingRef = (0, react.useRef)(false);
4262
+ const [listVisible, setListVisible] = (0, react.useState)(false);
4263
+ const [inputValue, setInputValue] = (0, react.useState)(() => `${value}%`);
4264
+ (0, react.useEffect)(() => {
4265
+ if (!isEditingRef.current) setInputValue(`${value}%`);
4266
+ }, [value]);
4267
+ function emitValue(nextValue) {
4268
+ const normalizedValue = normalizeTransparency$1(nextValue);
4269
+ onChange === null || onChange === void 0 || onChange(normalizedValue);
4270
+ onChangeComplete === null || onChangeComplete === void 0 || onChangeComplete(normalizedValue);
4271
+ }
4272
+ function handleSelect(nextValue) {
4273
+ if (disabled) return;
4274
+ setListVisible(false);
4275
+ emitValue(nextValue);
4276
+ }
4277
+ function handleFocus() {
4278
+ if (disabled) return;
4279
+ isEditingRef.current = true;
4280
+ setInputValue(String(value));
4281
+ }
4282
+ function commitInput() {
4283
+ if (disabled || !isEditingRef.current) return;
4284
+ const parsedValue = parseTransparency(inputValue);
4285
+ isEditingRef.current = false;
4286
+ if (parsedValue == null) {
4287
+ setInputValue(`${value}%`);
4288
+ return;
4289
+ }
4290
+ if (parsedValue === value) {
4291
+ setInputValue(`${parsedValue}%`);
4292
+ return;
4293
+ }
4294
+ emitValue(parsedValue);
4295
+ }
4296
+ function handleKeyDown(e) {
4297
+ e.stopPropagation();
4298
+ if (e.key === "Enter") {
4299
+ e.preventDefault();
4300
+ commitInput();
4301
+ e.currentTarget.blur();
4302
+ }
4303
+ }
4304
+ const items = [{
4305
+ type: "radio",
4306
+ value: value.toString(),
4307
+ options: shortcuts.map((shortcut) => ({
4308
+ value: shortcut.toString(),
4309
+ label: `${shortcut}%`
4310
+ })),
4311
+ onSelect: (selectedValue) => handleSelect(Number(selectedValue))
4312
+ }];
4313
+ const MoreDownIcon = iconManager.get("MoreDownIcon");
4314
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4315
+ className: (0, _univerjs_design.clsx)("univer-flex univer-h-6 univer-w-[68px] univer-flex-shrink-0 univer-items-center univer-overflow-hidden univer-rounded-md univer-border univer-border-gray-200 univer-bg-gray-0 dark:!univer-border-gray-600 dark:!univer-bg-gray-800", { "univer-opacity-60": disabled }),
4316
+ onClick: (e) => e.stopPropagation(),
4317
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Input, {
4318
+ className: "univer-box-border univer-h-6 univer-min-w-0 univer-flex-1 univer-border-none univer-bg-transparent [&_input:focus]:!univer-ring-0 [&_input]:univer-h-6 [&_input]:univer-w-full [&_input]:univer-border-none [&_input]:!univer-bg-transparent [&_input]:univer-px-1 [&_input]:univer-text-center [&_input]:univer-text-xs [&_input]:univer-tabular-nums",
4319
+ inputClass: "univer-w-full",
4320
+ size: "mini",
4321
+ "aria-label": ariaLabel,
4322
+ value: inputValue,
4323
+ disabled,
4324
+ type: "text",
4325
+ onChange: setInputValue,
4326
+ onFocus: handleFocus,
4327
+ onBlur: commitInput,
4328
+ onKeyDown: handleKeyDown
4329
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.DropdownMenu, {
4330
+ align: "end",
4331
+ items,
4332
+ open: listVisible,
4333
+ disabled,
4334
+ onOpenChange: setListVisible,
4335
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Button, {
4336
+ className: "univer-h-6 univer-w-4 univer-rounded-none univer-p-0",
4337
+ size: "small",
4338
+ variant: "text",
4339
+ "aria-label": ariaLabel,
4340
+ disabled,
4341
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoreDownIcon, { className: "univer-size-3 univer-text-gray-500 dark:!univer-text-gray-300" })
4342
+ })
4343
+ })]
4344
+ });
4072
4345
  }
4073
- function getAnchorKind(value) {
4074
- if (value === _univerjs_sheets_drawing.SheetDrawingAnchorType.Position || value === _univerjs_sheets_drawing.SheetDrawingAnchorType.Both || value === _univerjs_sheets_drawing.SheetDrawingAnchorType.None) return value;
4075
- return null;
4346
+ function parseTransparency(rawValue) {
4347
+ const normalizedValue = rawValue.trim().replace(/%$/, "").trim();
4348
+ if (normalizedValue === "") return null;
4349
+ const parsedValue = Number(normalizedValue);
4350
+ return Number.isFinite(parsedValue) ? normalizeTransparency$1(parsedValue) : null;
4351
+ }
4352
+ function normalizeTransparency$1(value) {
4353
+ return Math.min(Math.max(Math.round(value), MIN_TRANSPARENCY), MAX_TRANSPARENCY);
4354
+ }
4355
+
4356
+ //#endregion
4357
+ //#region src/views/sheet-image-panel/SheetImageTransparency.tsx
4358
+ const IMAGE_TRANSPARENCY_PRESETS = [
4359
+ 0,
4360
+ 15,
4361
+ 30,
4362
+ 50,
4363
+ 65,
4364
+ 80
4365
+ ];
4366
+ const SheetImageTransparency = ({ drawings }) => {
4367
+ const commandService = (0, _univerjs_ui.useDependency)(_univerjs_core.ICommandService);
4368
+ const localeService = (0, _univerjs_ui.useDependency)(_univerjs_core.LocaleService);
4369
+ const sheetDrawingService = (0, _univerjs_ui.useDependency)(_univerjs_sheets_drawing.ISheetDrawingService);
4370
+ const drawingParam = isSheetDrawing(drawings[0]) ? drawings[0] : void 0;
4371
+ const currentDrawing = drawingParam ? sheetDrawingService.getDrawingByParam(drawingParam) ?? drawingParam : void 0;
4372
+ const image = (currentDrawing === null || currentDrawing === void 0 ? void 0 : currentDrawing.drawingType) === _univerjs_core.DrawingTypeEnum.DRAWING_IMAGE ? currentDrawing : void 0;
4373
+ const modelOpacity = (0, _univerjs_drawing.normalizeImageOpacity)(image === null || image === void 0 ? void 0 : image.opacity);
4374
+ const modelTransparency = Math.round((1 - modelOpacity) * 100);
4375
+ const [previewState, setPreviewState] = (0, react.useState)(null);
4376
+ const previewPendingRef = (0, react.useRef)(false);
4377
+ const [, setModelRevision] = (0, react.useState)(0);
4378
+ const transparency = image && (previewState === null || previewState === void 0 ? void 0 : previewState.unitId) === image.unitId && previewState.subUnitId === image.subUnitId && previewState.drawingId === image.drawingId ? previewState.transparency : modelTransparency;
4379
+ (0, react.useEffect)(() => {
4380
+ if (!drawingParam) return;
4381
+ const subscription = sheetDrawingService.update$.subscribe((updatedDrawings) => {
4382
+ if (updatedDrawings.some((updatedDrawing) => updatedDrawing.unitId === drawingParam.unitId && updatedDrawing.subUnitId === drawingParam.subUnitId && updatedDrawing.drawingId === drawingParam.drawingId)) setModelRevision((revision) => revision + 1);
4383
+ });
4384
+ return () => subscription.unsubscribe();
4385
+ }, [drawingParam, sheetDrawingService]);
4386
+ (0, react.useEffect)(() => {
4387
+ previewPendingRef.current = false;
4388
+ return () => {
4389
+ if (!previewPendingRef.current || !image) return;
4390
+ commandService.syncExecuteCommand(PreviewSheetImageOpacityOperation.id, {
4391
+ unitId: image.unitId,
4392
+ subUnitId: image.subUnitId,
4393
+ drawingId: image.drawingId,
4394
+ opacity: modelOpacity
4395
+ });
4396
+ };
4397
+ }, [
4398
+ commandService,
4399
+ image,
4400
+ modelOpacity,
4401
+ modelTransparency
4402
+ ]);
4403
+ if (!image) return null;
4404
+ const title = localeService.t("sheets-drawing-ui.image-transparency.title");
4405
+ const { unitId, subUnitId, drawingId } = image;
4406
+ function previewTransparency(nextTransparency) {
4407
+ const normalizedTransparency = normalizeTransparency(nextTransparency);
4408
+ const opacity = transparencyToOpacity(normalizedTransparency);
4409
+ previewPendingRef.current = true;
4410
+ setPreviewState({
4411
+ unitId,
4412
+ subUnitId,
4413
+ drawingId,
4414
+ transparency: normalizedTransparency
4415
+ });
4416
+ commandService.syncExecuteCommand(PreviewSheetImageOpacityOperation.id, {
4417
+ unitId,
4418
+ subUnitId,
4419
+ drawingId,
4420
+ opacity
4421
+ });
4422
+ }
4423
+ function commitTransparency(nextTransparency) {
4424
+ const opacity = transparencyToOpacity(normalizeTransparency(nextTransparency));
4425
+ previewPendingRef.current = false;
4426
+ setPreviewState(null);
4427
+ if (opacity === modelOpacity) return;
4428
+ if (!commandService.syncExecuteCommand(_univerjs_sheets_drawing.SetSheetDrawingCommand.id, {
4429
+ unitId,
4430
+ drawings: [{
4431
+ unitId,
4432
+ subUnitId,
4433
+ drawingId,
4434
+ opacity
4435
+ }]
4436
+ })) commandService.syncExecuteCommand(PreviewSheetImageOpacityOperation.id, {
4437
+ unitId,
4438
+ subUnitId,
4439
+ drawingId,
4440
+ opacity: modelOpacity
4441
+ });
4442
+ }
4443
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4444
+ className: "univer-grid univer-gap-2 univer-py-2 univer-text-gray-400",
4445
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
4446
+ className: "univer-text-gray-600 dark:!univer-text-gray-200",
4447
+ children: title
4448
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetImageTransparencySlider, {
4449
+ value: transparency,
4450
+ shortcuts: IMAGE_TRANSPARENCY_PRESETS,
4451
+ ariaLabel: title,
4452
+ onChange: previewTransparency,
4453
+ onChangeComplete: commitTransparency
4454
+ })]
4455
+ });
4456
+ };
4457
+ function normalizeTransparency(transparency) {
4458
+ if (!Number.isFinite(transparency)) return 0;
4459
+ return Math.min(Math.max(Math.round(transparency), 0), 100);
4460
+ }
4461
+ function transparencyToOpacity(transparency) {
4462
+ return (100 - transparency) / 100;
4076
4463
  }
4077
4464
 
4078
4465
  //#endregion
@@ -4097,7 +4484,11 @@ const SheetDrawingPanel = () => {
4097
4484
  const drawings = (0, _univerjs_ui.useObservable)(() => drawingManagerService.focus$, drawingManagerService.getFocusDrawings(), false, [drawingManagerService]);
4098
4485
  return !!(drawings === null || drawings === void 0 ? void 0 : drawings.length) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4099
4486
  className: "univer-text-sm",
4100
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_drawing_ui.DrawingCommonPanel, { drawings }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetDrawingAnchor, { drawings })]
4487
+ children: [
4488
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_drawing_ui.DrawingCommonPanel, { drawings }),
4489
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetImageTransparency, { drawings }),
4490
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SheetDrawingAnchor, { drawings })
4491
+ ]
4101
4492
  });
4102
4493
  };
4103
4494
 
@@ -4515,8 +4906,26 @@ let SheetDrawingActiveRenderController = class SheetDrawingActiveRenderControlle
4515
4906
  this._sheetSkeletonService = _sheetSkeletonService;
4516
4907
  this._sheetDrawingService = _sheetDrawingService;
4517
4908
  this._drawingManagerService = _drawingManagerService;
4909
+ _defineProperty(this, "_renderTimeout", void 0);
4518
4910
  this._commandListener();
4519
4911
  }
4912
+ dispose() {
4913
+ this._cancelPendingRender();
4914
+ super.dispose();
4915
+ }
4916
+ _cancelPendingRender() {
4917
+ if (this._renderTimeout !== void 0) {
4918
+ clearTimeout(this._renderTimeout);
4919
+ this._renderTimeout = void 0;
4920
+ }
4921
+ }
4922
+ _scheduleRender(callback) {
4923
+ this._cancelPendingRender();
4924
+ this._renderTimeout = setTimeout(() => {
4925
+ this._renderTimeout = void 0;
4926
+ callback();
4927
+ }, 0);
4928
+ }
4520
4929
  _commandListener() {
4521
4930
  this.disposeWithMe(this._commandService.onCommandExecuted((command) => {
4522
4931
  if (command.id === _univerjs_sheets.SetWorksheetActiveOperation.id) {
@@ -4531,7 +4940,7 @@ let SheetDrawingActiveRenderController = class SheetDrawingActiveRenderControlle
4531
4940
  }));
4532
4941
  }
4533
4942
  _clearDrawings(selfUnitId) {
4534
- setTimeout(() => {
4943
+ this._scheduleRender(() => {
4535
4944
  const drawingMap = this._drawingManagerService.drawingManagerData;
4536
4945
  const removeDrawings = [];
4537
4946
  Object.keys(drawingMap ?? {}).forEach((unitId) => {
@@ -4549,10 +4958,11 @@ let SheetDrawingActiveRenderController = class SheetDrawingActiveRenderControlle
4549
4958
  });
4550
4959
  }
4551
4960
  _updateDrawings(showUnitId, showSubunitId) {
4552
- setTimeout(() => {
4961
+ this._scheduleRender(() => {
4553
4962
  const sheetSkeletonParam = this._sheetSkeletonService.getSkeletonParam(showUnitId, showSubunitId);
4554
4963
  const drawingMap = this._drawingManagerService.drawingManagerData;
4555
4964
  const insertDrawings = [];
4965
+ const refreshedDrawings = [];
4556
4966
  const removeDrawings = [];
4557
4967
  Object.keys(drawingMap ?? {}).forEach((unitId) => {
4558
4968
  if (unitId !== showUnitId) return;
@@ -4563,17 +4973,19 @@ let SheetDrawingActiveRenderController = class SheetDrawingActiveRenderControlle
4563
4973
  Object.keys(drawingData).forEach((drawingId) => {
4564
4974
  if (unitId === showUnitId && subUnitId === showSubunitId) {
4565
4975
  const drawing = drawingData[drawingId];
4566
- if (drawing.sheetTransform && drawing.anchorType !== _univerjs_sheets_drawing.SheetDrawingAnchorType.None) drawing.transform = (0, _univerjs_sheets_drawing.drawingPositionToTransform)(drawing.sheetTransform, sheetSkeletonParam);
4976
+ if (sheetSkeletonParam && drawing.sheetTransform && drawing.anchorType !== _univerjs_sheets_drawing.SheetDrawingAnchorType.None) refreshedDrawings.push((0, _univerjs_sheets_drawing.applySheetDrawingPlacement)(drawing, (0, _univerjs_sheets_drawing.getSheetDrawingPlacement)(drawing), sheetSkeletonParam.skeleton));
4567
4977
  insertDrawings.push(drawingData[drawingId]);
4568
4978
  } else removeDrawings.push(drawingData[drawingId]);
4569
4979
  });
4570
4980
  });
4571
4981
  });
4982
+ this._sheetDrawingService.refreshTransform(refreshedDrawings);
4983
+ this._drawingManagerService.refreshTransform(refreshedDrawings);
4572
4984
  this._sheetDrawingService.removeNotification(removeDrawings);
4573
4985
  this._sheetDrawingService.addNotification(insertDrawings);
4574
4986
  this._drawingManagerService.removeNotification(removeDrawings);
4575
4987
  this._drawingManagerService.addNotification(insertDrawings);
4576
- }, 0);
4988
+ });
4577
4989
  }
4578
4990
  };
4579
4991
  SheetDrawingActiveRenderController = __decorate([
@@ -5633,7 +6045,8 @@ let SheetDrawingUIController = class SheetDrawingUIController extends _univerjs_
5633
6045
  MoveDrawingsCommand,
5634
6046
  DeleteDrawingsCommand,
5635
6047
  SaveCellImagesCommand,
5636
- FlipSheetDrawingCommand
6048
+ FlipSheetDrawingCommand,
6049
+ PreviewSheetImageOpacityOperation
5637
6050
  ].forEach((command) => this.disposeWithMe(this._commandService.registerCommand(command)));
5638
6051
  }
5639
6052
  _initShortcuts() {
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "يمكن رفع {0} صور فقط في المرة الواحدة",
40
40
  invalidImage: "صورة غير صالحة"
41
41
  },
42
+ "image-transparency": { title: "الشفافية" },
42
43
  "drawing-anchor": {
43
44
  title: "خصائص المرساة",
44
45
  both: "النقل والتحجيم مع الخلايا",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Només es poden pujar {0} imatges alhora",
40
40
  invalidImage: "Imatge no vàlida"
41
41
  },
42
+ "image-transparency": { title: "Transparència" },
42
43
  "drawing-anchor": {
43
44
  title: "Propietats d’ancoratge",
44
45
  both: "Mou i canvia la mida amb les cel·les",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Es können nur {0} Bilder gleichzeitig hochgeladen werden",
40
40
  invalidImage: "Ungültiges Bild"
41
41
  },
42
+ "image-transparency": { title: "Transparenz" },
42
43
  "drawing-anchor": {
43
44
  title: "Anker-Eigenschaften",
44
45
  both: "Mit Zellen verschieben und skalieren",
@@ -54,6 +54,7 @@ const locale = { "sheets-drawing-ui": {
54
54
  exceedMaxCount: "Only {0} images can be uploaded at a time",
55
55
  invalidImage: "Invalid image"
56
56
  },
57
+ "image-transparency": { title: "Transparency" },
57
58
  "drawing-anchor": {
58
59
  title: "Anchor Properties",
59
60
  both: "Move and size with cells",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Solo se pueden subir {0} imágenes a la vez",
40
40
  invalidImage: "Imagen no válida"
41
41
  },
42
+ "image-transparency": { title: "Transparencia" },
42
43
  "drawing-anchor": {
43
44
  title: "Propiedades de anclaje",
44
45
  both: "Mover y cambiar tamaño con las celdas",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "فقط {0} تصویر می‌توانند همزمان آپلود شوند",
40
40
  invalidImage: "تصویر نامعتبر است"
41
41
  },
42
+ "image-transparency": { title: "شفافیت" },
42
43
  "drawing-anchor": {
43
44
  title: "خواص لنگر",
44
45
  both: "جابه‌جایی و تغییر اندازه با سلول‌ها",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Seulement {0} images peuvent être téléchargées à la fois",
40
40
  invalidImage: "Image invalide"
41
41
  },
42
+ "image-transparency": { title: "Transparence" },
42
43
  "drawing-anchor": {
43
44
  title: "Propriétés de l'ancre",
44
45
  both: "Déplacer et redimensionner avec les cellules",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Hanya {0} gambar yang dapat diunggah dalam satu waktu",
40
40
  invalidImage: "Gambar tidak valid"
41
41
  },
42
+ "image-transparency": { title: "Transparansi" },
42
43
  "drawing-anchor": {
43
44
  title: "Properti Jangkar",
44
45
  both: "Pindah dan ukur bersama sel",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "È possibile caricare solo {0} immagini alla volta",
40
40
  invalidImage: "Immagine non valida"
41
41
  },
42
+ "image-transparency": { title: "Trasparenza" },
42
43
  "drawing-anchor": {
43
44
  title: "Proprietà ancoraggio",
44
45
  both: "Sposta e ridimensiona con le celle",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "一度にアップロードできるのは {0} 個までです",
40
40
  invalidImage: "無効な画像です"
41
41
  },
42
+ "image-transparency": { title: "透明度" },
42
43
  "drawing-anchor": {
43
44
  title: "プロパティ",
44
45
  both: "セルに合わせて移動やサイズ変更をする",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "한 번에 {0}개까지만 업로드할 수 있습니다",
40
40
  invalidImage: "유효하지 않은 이미지입니다"
41
41
  },
42
+ "image-transparency": { title: "투명도" },
42
43
  "drawing-anchor": {
43
44
  title: "고정 위치 설정",
44
45
  both: "셀과 함께 이동 및 크기 조절",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Jednocześnie można przesłać tylko {0} obrazów",
40
40
  invalidImage: "Nieprawidłowy obraz"
41
41
  },
42
+ "image-transparency": { title: "Przezroczystość" },
42
43
  "drawing-anchor": {
43
44
  title: "Właściwości kotwicy",
44
45
  both: "Przesuwaj i zmieniaj rozmiar razem z komórkami",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Apenas {0} imagens podem ser enviadas de cada vez",
40
40
  invalidImage: "Imagem inválida"
41
41
  },
42
+ "image-transparency": { title: "Transparência" },
42
43
  "drawing-anchor": {
43
44
  title: "Propriedades da âncora",
44
45
  both: "Mover e dimensionar com as células",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "За один раз можно загрузить только {0} изображений",
40
40
  invalidImage: "Недопустимое изображение"
41
41
  },
42
+ "image-transparency": { title: "Прозрачность" },
42
43
  "drawing-anchor": {
43
44
  title: "Свойства привязки",
44
45
  both: "Перемещать и изменять размер с ячейками",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Naraz možno nahrať iba {0} obrázkov",
40
40
  invalidImage: "Neplatný obrázok"
41
41
  },
42
+ "image-transparency": { title: "Priehľadnosť" },
42
43
  "drawing-anchor": {
43
44
  title: "Vlastnosti ukotvenia",
44
45
  both: "Presúvať a meniť veľkosť s bunkami",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "Chỉ có thể tải lên {0} hình ảnh một lần",
40
40
  invalidImage: "Hình ảnh không hợp lệ"
41
41
  },
42
+ "image-transparency": { title: "Độ trong suốt" },
42
43
  "drawing-anchor": {
43
44
  title: "Thuộc tính neo",
44
45
  both: "Di chuyển và thay đổi kích thước cùng với ô",
@@ -39,6 +39,7 @@ const locale = { "sheets-drawing-ui": {
39
39
  exceedMaxCount: "图片只能一次上传{0}张",
40
40
  invalidImage: "无效图片"
41
41
  },
42
+ "image-transparency": { title: "透明度" },
42
43
  "drawing-anchor": {
43
44
  title: "锚点属性",
44
45
  both: "与单元格一起移动和调整大小",