@univerjs/sheets-conditional-formatting 1.0.0-alpha.8 → 1.0.0-beta.1

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/lib/cjs/index.js CHANGED
@@ -557,9 +557,8 @@ let ConditionalFormattingRangeIndexModel = class ConditionalFormattingRangeIndex
557
557
  return new Set(Array.from(ids).map((id) => String(id)));
558
558
  }
559
559
  getRulesByRanges(unitId, subUnitId, ranges) {
560
- var _this$_conditionalFor;
561
560
  const ids = this.getRuleIdsByRanges(unitId, subUnitId, ranges);
562
- return ((_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : []).filter((rule) => ids.has(rule.cfId));
561
+ return (this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? []).filter((rule) => ids.has(rule.cfId));
563
562
  }
564
563
  dispose() {
565
564
  this.clear();
@@ -688,7 +687,7 @@ const ClearRangeCfCommand = {
688
687
  type: _univerjs_core.CommandType.COMMAND,
689
688
  id: "sheet.command.clear-range-conditional-rule",
690
689
  handler(accessor, params) {
691
- var _ref, _params$ranges, _selectionManagerServ;
690
+ var _selectionManagerServ;
692
691
  if (!params) return false;
693
692
  const conditionalFormattingRangeIndexModel = accessor.get(ConditionalFormattingRangeIndexModel);
694
693
  const conditionalFormattingRangeTransformService = accessor.get(ConditionalFormattingRangeTransformService);
@@ -699,7 +698,7 @@ const ClearRangeCfCommand = {
699
698
  const target = (0, _univerjs_sheets.getSheetCommandTarget)(univerInstanceService, params);
700
699
  if (!target) return false;
701
700
  const { unitId, subUnitId } = target;
702
- const ranges = (_ref = (_params$ranges = params.ranges) !== null && _params$ranges !== void 0 ? _params$ranges : (_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) !== null && _ref !== void 0 ? _ref : [];
701
+ const ranges = params.ranges ?? ((_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) ?? [];
703
702
  const allRuleList = conditionalFormattingRangeIndexModel.getRulesByRanges(unitId, subUnitId, ranges).filter((rule) => {
704
703
  var _params$types;
705
704
  return !((_params$types = params.types) === null || _params$types === void 0 ? void 0 : _params$types.length) || params.types.includes(rule.rule.type);
@@ -1204,15 +1203,21 @@ var DataBar = class extends _univerjs_engine_render.SheetExtension {
1204
1203
  super(..._args);
1205
1204
  _defineProperty(this, "_paddingRightAndLeft", 2);
1206
1205
  _defineProperty(this, "_paddingTopAndBottom", 2);
1206
+ _defineProperty(this, "_renderRangeResolver", null);
1207
1207
  _defineProperty(this, "uKey", dataBarUKey);
1208
1208
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX$1);
1209
1209
  _defineProperty(this, "_radius", 1);
1210
1210
  }
1211
+ setRenderRangeResolver(resolver) {
1212
+ this._renderRangeResolver = resolver;
1213
+ }
1211
1214
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
1212
1215
  const { worksheet } = spreadsheetSkeleton;
1213
1216
  if (!worksheet) return false;
1214
1217
  const mergeCellRendered = /* @__PURE__ */ new Set();
1215
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1218
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1219
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
1220
+ if (!renderRanges.length) return;
1216
1221
  ctx.save();
1217
1222
  renderRanges.forEach((range) => {
1218
1223
  _univerjs_core.Range.foreach(range, (row, col) => {
@@ -1267,6 +1272,10 @@ var DataBar = class extends _univerjs_engine_render.SheetExtension {
1267
1272
  });
1268
1273
  ctx.restore();
1269
1274
  }
1275
+ dispose() {
1276
+ this._renderRangeResolver = null;
1277
+ super.dispose();
1278
+ }
1270
1279
  _drawRectWithRoundedCorner(ctx, x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius) {
1271
1280
  const radius = this._radius;
1272
1281
  if (!height || !width) return;
@@ -1478,7 +1487,7 @@ var HighlightCellCalculateUnit = class extends BaseCalculateUnit {
1478
1487
  allValue.sort((a, b) => b - a);
1479
1488
  const configRule = context.rule.rule;
1480
1489
  if (configRule.isPercent) {
1481
- if (configRule.isBottom) allValue = allValue.toReversed();
1490
+ if (configRule.isBottom) allValue = allValue.slice().reverse();
1482
1491
  const threshold = _univerjs_core.Tools.clamp(configRule.value, 0, 100) / 100;
1483
1492
  const targetIndex = Math.floor(threshold * allValue.length);
1484
1493
  const safeIndex = _univerjs_core.Tools.clamp(targetIndex - 1, 0, allValue.length - 1);
@@ -1801,7 +1810,9 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1801
1810
  _defineProperty(this, "_calculateUnitManagers", /* @__PURE__ */ new Map());
1802
1811
  _defineProperty(this, "_cellCache", new _univerjs_core.LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
1803
1812
  _defineProperty(this, "_markDirty$", new rxjs.Subject());
1813
+ _defineProperty(this, "_cacheClear$", new rxjs.Subject());
1804
1814
  _defineProperty(this, "markDirty$", this._markDirty$.asObservable());
1815
+ _defineProperty(this, "cacheClear$", this._cacheClear$.asObservable());
1805
1816
  _defineProperty(this, "_markRuleDirtyAtOnce", (unitId, subUnitId, cfId, isNeedResetPreComputingCache = true) => {
1806
1817
  this._cellCache.clear();
1807
1818
  if (isNeedResetPreComputingCache) {
@@ -1863,8 +1874,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1863
1874
  return result;
1864
1875
  }
1865
1876
  _getCellCfs(unitId, subUnitId, row, col) {
1866
- var _this$_conditionalFor;
1867
- const subunitRules = (_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : [];
1877
+ const subunitRules = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? [];
1868
1878
  const _calculateUnitManagers = this._ensureCalculateUnitManager(unitId, subUnitId);
1869
1879
  const list = this._conditionalFormattingRangeIndexModel.getRuleIdsByCell(unitId, subUnitId, row, col);
1870
1880
  const rules = subunitRules.filter((rule) => list.has(rule.cfId));
@@ -1888,6 +1898,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1888
1898
  clearCache() {
1889
1899
  this._calculateUnitManagers.clear();
1890
1900
  this._cellCache.clear();
1901
+ this._cacheClear$.next();
1891
1902
  }
1892
1903
  _handleCustomFormulasSeparately() {
1893
1904
  this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe((e) => {
@@ -2545,7 +2556,7 @@ for (const key in iconMap) {
2545
2556
  //#endregion
2546
2557
  //#region package.json
2547
2558
  var name = "@univerjs/sheets-conditional-formatting";
2548
- var version = "1.0.0-alpha.8";
2559
+ var version = "1.0.0-beta.1";
2549
2560
 
2550
2561
  //#endregion
2551
2562
  //#region src/config/config.ts
@@ -2570,14 +2581,28 @@ const defaultPluginConfig = {};
2570
2581
 
2571
2582
  //#endregion
2572
2583
  //#region src/services/conditional-formatting-style-composer.service.ts
2573
- let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer {
2584
+ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer extends _univerjs_core.Disposable {
2574
2585
  constructor(_conditionalFormattingRuleModel, _conditionalFormattingViewModel) {
2586
+ super();
2575
2587
  this._conditionalFormattingRuleModel = _conditionalFormattingRuleModel;
2576
2588
  this._conditionalFormattingViewModel = _conditionalFormattingViewModel;
2589
+ _defineProperty(this, "_cache", new _univerjs_core.LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
2590
+ this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe(() => this._cache.clear()));
2591
+ this.disposeWithMe(this._conditionalFormattingViewModel.markDirty$.subscribe(() => this._cache.clear()));
2592
+ this.disposeWithMe(this._conditionalFormattingViewModel.cacheClear$.subscribe(() => this._cache.clear()));
2593
+ }
2594
+ dispose() {
2595
+ this._cache.clear();
2596
+ super.dispose();
2577
2597
  }
2578
2598
  composeStyle(unitId, subUnitId, row, col) {
2599
+ const cacheKey = `${unitId}_${subUnitId}_${row}_${col}`;
2600
+ if (this._cache.has(cacheKey)) return this._cache.get(cacheKey) ?? null;
2579
2601
  const cellCfs = this._conditionalFormattingViewModel.getCellCfs(unitId, subUnitId, row, col);
2580
- if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) return null;
2602
+ if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) {
2603
+ this._cache.set(cacheKey, null);
2604
+ return null;
2605
+ }
2581
2606
  const matchedRules = [];
2582
2607
  let stopIfTrueIndex = -1;
2583
2608
  for (const cacheItem of cellCfs) {
@@ -2589,13 +2614,17 @@ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleCompose
2589
2614
  });
2590
2615
  if (stopIfTrueIndex === -1 && rule.stopIfTrue && this._isRuleMatched(rule, cacheItem.result)) stopIfTrueIndex = matchedRules.length - 1;
2591
2616
  }
2592
- if (!matchedRules.length) return null;
2617
+ if (!matchedRules.length) {
2618
+ this._cache.set(cacheKey, null);
2619
+ return null;
2620
+ }
2593
2621
  const effectiveRules = stopIfTrueIndex > -1 ? matchedRules.slice(0, stopIfTrueIndex + 1) : matchedRules;
2594
2622
  const result = {};
2595
2623
  for (let i = effectiveRules.length - 1; i >= 0; i--) {
2596
2624
  const { rule, cacheItem } = effectiveRules[i];
2597
2625
  this._mergeComposeResult(result, rule, cacheItem.result);
2598
2626
  }
2627
+ this._cache.set(cacheKey, result);
2599
2628
  return result;
2600
2629
  }
2601
2630
  _mergeComposeResult(result, rule, ruleResult) {
@@ -2959,16 +2988,22 @@ var ConditionalFormattingIcon = class extends _univerjs_engine_render.SheetExten
2959
2988
  _defineProperty(this, "_paddingRightAndLeft", 2);
2960
2989
  _defineProperty(this, "_width", 15);
2961
2990
  _defineProperty(this, "_imageMap", /* @__PURE__ */ new Map());
2991
+ _defineProperty(this, "_renderRangeResolver", null);
2962
2992
  _defineProperty(this, "uKey", IconUKey);
2963
2993
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX);
2964
2994
  _defineProperty(this, "_radius", 1);
2965
2995
  this._init();
2966
2996
  }
2997
+ setRenderRangeResolver(resolver) {
2998
+ this._renderRangeResolver = resolver;
2999
+ }
2967
3000
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
2968
3001
  const { worksheet } = spreadsheetSkeleton;
2969
3002
  if (!worksheet) return false;
2970
3003
  const mergeCellRendered = /* @__PURE__ */ new Set();
2971
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3004
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3005
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
3006
+ if (!renderRanges.length) return;
2972
3007
  ctx.save();
2973
3008
  renderRanges.forEach((range) => {
2974
3009
  _univerjs_core.Range.foreach(range, (row, col) => {
@@ -2998,6 +3033,10 @@ var ConditionalFormattingIcon = class extends _univerjs_engine_render.SheetExten
2998
3033
  });
2999
3034
  ctx.restore();
3000
3035
  }
3036
+ dispose() {
3037
+ this._renderRangeResolver = null;
3038
+ super.dispose();
3039
+ }
3001
3040
  _init() {
3002
3041
  for (const type in iconMap) iconMap[type].forEach((base64, index) => {
3003
3042
  const key = this._createKey(type, String(index));
package/lib/es/index.js CHANGED
@@ -556,9 +556,8 @@ let ConditionalFormattingRangeIndexModel = class ConditionalFormattingRangeIndex
556
556
  return new Set(Array.from(ids).map((id) => String(id)));
557
557
  }
558
558
  getRulesByRanges(unitId, subUnitId, ranges) {
559
- var _this$_conditionalFor;
560
559
  const ids = this.getRuleIdsByRanges(unitId, subUnitId, ranges);
561
- return ((_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : []).filter((rule) => ids.has(rule.cfId));
560
+ return (this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? []).filter((rule) => ids.has(rule.cfId));
562
561
  }
563
562
  dispose() {
564
563
  this.clear();
@@ -687,7 +686,7 @@ const ClearRangeCfCommand = {
687
686
  type: CommandType.COMMAND,
688
687
  id: "sheet.command.clear-range-conditional-rule",
689
688
  handler(accessor, params) {
690
- var _ref, _params$ranges, _selectionManagerServ;
689
+ var _selectionManagerServ;
691
690
  if (!params) return false;
692
691
  const conditionalFormattingRangeIndexModel = accessor.get(ConditionalFormattingRangeIndexModel);
693
692
  const conditionalFormattingRangeTransformService = accessor.get(ConditionalFormattingRangeTransformService);
@@ -698,7 +697,7 @@ const ClearRangeCfCommand = {
698
697
  const target = getSheetCommandTarget(univerInstanceService, params);
699
698
  if (!target) return false;
700
699
  const { unitId, subUnitId } = target;
701
- const ranges = (_ref = (_params$ranges = params.ranges) !== null && _params$ranges !== void 0 ? _params$ranges : (_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) !== null && _ref !== void 0 ? _ref : [];
700
+ const ranges = params.ranges ?? ((_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) ?? [];
702
701
  const allRuleList = conditionalFormattingRangeIndexModel.getRulesByRanges(unitId, subUnitId, ranges).filter((rule) => {
703
702
  var _params$types;
704
703
  return !((_params$types = params.types) === null || _params$types === void 0 ? void 0 : _params$types.length) || params.types.includes(rule.rule.type);
@@ -1203,15 +1202,21 @@ var DataBar = class extends SheetExtension {
1203
1202
  super(..._args);
1204
1203
  _defineProperty(this, "_paddingRightAndLeft", 2);
1205
1204
  _defineProperty(this, "_paddingTopAndBottom", 2);
1205
+ _defineProperty(this, "_renderRangeResolver", null);
1206
1206
  _defineProperty(this, "uKey", dataBarUKey);
1207
1207
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX$1);
1208
1208
  _defineProperty(this, "_radius", 1);
1209
1209
  }
1210
+ setRenderRangeResolver(resolver) {
1211
+ this._renderRangeResolver = resolver;
1212
+ }
1210
1213
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
1211
1214
  const { worksheet } = spreadsheetSkeleton;
1212
1215
  if (!worksheet) return false;
1213
1216
  const mergeCellRendered = /* @__PURE__ */ new Set();
1214
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1217
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1218
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
1219
+ if (!renderRanges.length) return;
1215
1220
  ctx.save();
1216
1221
  renderRanges.forEach((range) => {
1217
1222
  Range.foreach(range, (row, col) => {
@@ -1266,6 +1271,10 @@ var DataBar = class extends SheetExtension {
1266
1271
  });
1267
1272
  ctx.restore();
1268
1273
  }
1274
+ dispose() {
1275
+ this._renderRangeResolver = null;
1276
+ super.dispose();
1277
+ }
1269
1278
  _drawRectWithRoundedCorner(ctx, x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius) {
1270
1279
  const radius = this._radius;
1271
1280
  if (!height || !width) return;
@@ -1477,7 +1486,7 @@ var HighlightCellCalculateUnit = class extends BaseCalculateUnit {
1477
1486
  allValue.sort((a, b) => b - a);
1478
1487
  const configRule = context.rule.rule;
1479
1488
  if (configRule.isPercent) {
1480
- if (configRule.isBottom) allValue = allValue.toReversed();
1489
+ if (configRule.isBottom) allValue = allValue.slice().reverse();
1481
1490
  const threshold = Tools.clamp(configRule.value, 0, 100) / 100;
1482
1491
  const targetIndex = Math.floor(threshold * allValue.length);
1483
1492
  const safeIndex = Tools.clamp(targetIndex - 1, 0, allValue.length - 1);
@@ -1800,7 +1809,9 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1800
1809
  _defineProperty(this, "_calculateUnitManagers", /* @__PURE__ */ new Map());
1801
1810
  _defineProperty(this, "_cellCache", new LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
1802
1811
  _defineProperty(this, "_markDirty$", new Subject());
1812
+ _defineProperty(this, "_cacheClear$", new Subject());
1803
1813
  _defineProperty(this, "markDirty$", this._markDirty$.asObservable());
1814
+ _defineProperty(this, "cacheClear$", this._cacheClear$.asObservable());
1804
1815
  _defineProperty(this, "_markRuleDirtyAtOnce", (unitId, subUnitId, cfId, isNeedResetPreComputingCache = true) => {
1805
1816
  this._cellCache.clear();
1806
1817
  if (isNeedResetPreComputingCache) {
@@ -1862,8 +1873,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1862
1873
  return result;
1863
1874
  }
1864
1875
  _getCellCfs(unitId, subUnitId, row, col) {
1865
- var _this$_conditionalFor;
1866
- const subunitRules = (_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : [];
1876
+ const subunitRules = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? [];
1867
1877
  const _calculateUnitManagers = this._ensureCalculateUnitManager(unitId, subUnitId);
1868
1878
  const list = this._conditionalFormattingRangeIndexModel.getRuleIdsByCell(unitId, subUnitId, row, col);
1869
1879
  const rules = subunitRules.filter((rule) => list.has(rule.cfId));
@@ -1887,6 +1897,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1887
1897
  clearCache() {
1888
1898
  this._calculateUnitManagers.clear();
1889
1899
  this._cellCache.clear();
1900
+ this._cacheClear$.next();
1890
1901
  }
1891
1902
  _handleCustomFormulasSeparately() {
1892
1903
  this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe((e) => {
@@ -2544,7 +2555,7 @@ for (const key in iconMap) {
2544
2555
  //#endregion
2545
2556
  //#region package.json
2546
2557
  var name = "@univerjs/sheets-conditional-formatting";
2547
- var version = "1.0.0-alpha.8";
2558
+ var version = "1.0.0-beta.1";
2548
2559
 
2549
2560
  //#endregion
2550
2561
  //#region src/config/config.ts
@@ -2569,14 +2580,28 @@ const defaultPluginConfig = {};
2569
2580
 
2570
2581
  //#endregion
2571
2582
  //#region src/services/conditional-formatting-style-composer.service.ts
2572
- let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer {
2583
+ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer extends Disposable {
2573
2584
  constructor(_conditionalFormattingRuleModel, _conditionalFormattingViewModel) {
2585
+ super();
2574
2586
  this._conditionalFormattingRuleModel = _conditionalFormattingRuleModel;
2575
2587
  this._conditionalFormattingViewModel = _conditionalFormattingViewModel;
2588
+ _defineProperty(this, "_cache", new LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
2589
+ this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe(() => this._cache.clear()));
2590
+ this.disposeWithMe(this._conditionalFormattingViewModel.markDirty$.subscribe(() => this._cache.clear()));
2591
+ this.disposeWithMe(this._conditionalFormattingViewModel.cacheClear$.subscribe(() => this._cache.clear()));
2592
+ }
2593
+ dispose() {
2594
+ this._cache.clear();
2595
+ super.dispose();
2576
2596
  }
2577
2597
  composeStyle(unitId, subUnitId, row, col) {
2598
+ const cacheKey = `${unitId}_${subUnitId}_${row}_${col}`;
2599
+ if (this._cache.has(cacheKey)) return this._cache.get(cacheKey) ?? null;
2578
2600
  const cellCfs = this._conditionalFormattingViewModel.getCellCfs(unitId, subUnitId, row, col);
2579
- if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) return null;
2601
+ if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) {
2602
+ this._cache.set(cacheKey, null);
2603
+ return null;
2604
+ }
2580
2605
  const matchedRules = [];
2581
2606
  let stopIfTrueIndex = -1;
2582
2607
  for (const cacheItem of cellCfs) {
@@ -2588,13 +2613,17 @@ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleCompose
2588
2613
  });
2589
2614
  if (stopIfTrueIndex === -1 && rule.stopIfTrue && this._isRuleMatched(rule, cacheItem.result)) stopIfTrueIndex = matchedRules.length - 1;
2590
2615
  }
2591
- if (!matchedRules.length) return null;
2616
+ if (!matchedRules.length) {
2617
+ this._cache.set(cacheKey, null);
2618
+ return null;
2619
+ }
2592
2620
  const effectiveRules = stopIfTrueIndex > -1 ? matchedRules.slice(0, stopIfTrueIndex + 1) : matchedRules;
2593
2621
  const result = {};
2594
2622
  for (let i = effectiveRules.length - 1; i >= 0; i--) {
2595
2623
  const { rule, cacheItem } = effectiveRules[i];
2596
2624
  this._mergeComposeResult(result, rule, cacheItem.result);
2597
2625
  }
2626
+ this._cache.set(cacheKey, result);
2598
2627
  return result;
2599
2628
  }
2600
2629
  _mergeComposeResult(result, rule, ruleResult) {
@@ -2958,16 +2987,22 @@ var ConditionalFormattingIcon = class extends SheetExtension {
2958
2987
  _defineProperty(this, "_paddingRightAndLeft", 2);
2959
2988
  _defineProperty(this, "_width", 15);
2960
2989
  _defineProperty(this, "_imageMap", /* @__PURE__ */ new Map());
2990
+ _defineProperty(this, "_renderRangeResolver", null);
2961
2991
  _defineProperty(this, "uKey", IconUKey);
2962
2992
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX);
2963
2993
  _defineProperty(this, "_radius", 1);
2964
2994
  this._init();
2965
2995
  }
2996
+ setRenderRangeResolver(resolver) {
2997
+ this._renderRangeResolver = resolver;
2998
+ }
2966
2999
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
2967
3000
  const { worksheet } = spreadsheetSkeleton;
2968
3001
  if (!worksheet) return false;
2969
3002
  const mergeCellRendered = /* @__PURE__ */ new Set();
2970
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3003
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3004
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
3005
+ if (!renderRanges.length) return;
2971
3006
  ctx.save();
2972
3007
  renderRanges.forEach((range) => {
2973
3008
  Range.foreach(range, (row, col) => {
@@ -2997,6 +3032,10 @@ var ConditionalFormattingIcon = class extends SheetExtension {
2997
3032
  });
2998
3033
  ctx.restore();
2999
3034
  }
3035
+ dispose() {
3036
+ this._renderRangeResolver = null;
3037
+ super.dispose();
3038
+ }
3000
3039
  _init() {
3001
3040
  for (const type in iconMap) iconMap[type].forEach((base64, index) => {
3002
3041
  const key = this._createKey(type, String(index));
package/lib/index.js CHANGED
@@ -556,9 +556,8 @@ let ConditionalFormattingRangeIndexModel = class ConditionalFormattingRangeIndex
556
556
  return new Set(Array.from(ids).map((id) => String(id)));
557
557
  }
558
558
  getRulesByRanges(unitId, subUnitId, ranges) {
559
- var _this$_conditionalFor;
560
559
  const ids = this.getRuleIdsByRanges(unitId, subUnitId, ranges);
561
- return ((_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : []).filter((rule) => ids.has(rule.cfId));
560
+ return (this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? []).filter((rule) => ids.has(rule.cfId));
562
561
  }
563
562
  dispose() {
564
563
  this.clear();
@@ -687,7 +686,7 @@ const ClearRangeCfCommand = {
687
686
  type: CommandType.COMMAND,
688
687
  id: "sheet.command.clear-range-conditional-rule",
689
688
  handler(accessor, params) {
690
- var _ref, _params$ranges, _selectionManagerServ;
689
+ var _selectionManagerServ;
691
690
  if (!params) return false;
692
691
  const conditionalFormattingRangeIndexModel = accessor.get(ConditionalFormattingRangeIndexModel);
693
692
  const conditionalFormattingRangeTransformService = accessor.get(ConditionalFormattingRangeTransformService);
@@ -698,7 +697,7 @@ const ClearRangeCfCommand = {
698
697
  const target = getSheetCommandTarget(univerInstanceService, params);
699
698
  if (!target) return false;
700
699
  const { unitId, subUnitId } = target;
701
- const ranges = (_ref = (_params$ranges = params.ranges) !== null && _params$ranges !== void 0 ? _params$ranges : (_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) !== null && _ref !== void 0 ? _ref : [];
700
+ const ranges = params.ranges ?? ((_selectionManagerServ = selectionManagerService.getCurrentSelections()) === null || _selectionManagerServ === void 0 ? void 0 : _selectionManagerServ.map((selection) => selection.range)) ?? [];
702
701
  const allRuleList = conditionalFormattingRangeIndexModel.getRulesByRanges(unitId, subUnitId, ranges).filter((rule) => {
703
702
  var _params$types;
704
703
  return !((_params$types = params.types) === null || _params$types === void 0 ? void 0 : _params$types.length) || params.types.includes(rule.rule.type);
@@ -1203,15 +1202,21 @@ var DataBar = class extends SheetExtension {
1203
1202
  super(..._args);
1204
1203
  _defineProperty(this, "_paddingRightAndLeft", 2);
1205
1204
  _defineProperty(this, "_paddingTopAndBottom", 2);
1205
+ _defineProperty(this, "_renderRangeResolver", null);
1206
1206
  _defineProperty(this, "uKey", dataBarUKey);
1207
1207
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX$1);
1208
1208
  _defineProperty(this, "_radius", 1);
1209
1209
  }
1210
+ setRenderRangeResolver(resolver) {
1211
+ this._renderRangeResolver = resolver;
1212
+ }
1210
1213
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
1211
1214
  const { worksheet } = spreadsheetSkeleton;
1212
1215
  if (!worksheet) return false;
1213
1216
  const mergeCellRendered = /* @__PURE__ */ new Set();
1214
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1217
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
1218
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
1219
+ if (!renderRanges.length) return;
1215
1220
  ctx.save();
1216
1221
  renderRanges.forEach((range) => {
1217
1222
  Range.foreach(range, (row, col) => {
@@ -1266,6 +1271,10 @@ var DataBar = class extends SheetExtension {
1266
1271
  });
1267
1272
  ctx.restore();
1268
1273
  }
1274
+ dispose() {
1275
+ this._renderRangeResolver = null;
1276
+ super.dispose();
1277
+ }
1269
1278
  _drawRectWithRoundedCorner(ctx, x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius) {
1270
1279
  const radius = this._radius;
1271
1280
  if (!height || !width) return;
@@ -1477,7 +1486,7 @@ var HighlightCellCalculateUnit = class extends BaseCalculateUnit {
1477
1486
  allValue.sort((a, b) => b - a);
1478
1487
  const configRule = context.rule.rule;
1479
1488
  if (configRule.isPercent) {
1480
- if (configRule.isBottom) allValue = allValue.toReversed();
1489
+ if (configRule.isBottom) allValue = allValue.slice().reverse();
1481
1490
  const threshold = Tools.clamp(configRule.value, 0, 100) / 100;
1482
1491
  const targetIndex = Math.floor(threshold * allValue.length);
1483
1492
  const safeIndex = Tools.clamp(targetIndex - 1, 0, allValue.length - 1);
@@ -1800,7 +1809,9 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1800
1809
  _defineProperty(this, "_calculateUnitManagers", /* @__PURE__ */ new Map());
1801
1810
  _defineProperty(this, "_cellCache", new LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
1802
1811
  _defineProperty(this, "_markDirty$", new Subject());
1812
+ _defineProperty(this, "_cacheClear$", new Subject());
1803
1813
  _defineProperty(this, "markDirty$", this._markDirty$.asObservable());
1814
+ _defineProperty(this, "cacheClear$", this._cacheClear$.asObservable());
1804
1815
  _defineProperty(this, "_markRuleDirtyAtOnce", (unitId, subUnitId, cfId, isNeedResetPreComputingCache = true) => {
1805
1816
  this._cellCache.clear();
1806
1817
  if (isNeedResetPreComputingCache) {
@@ -1862,8 +1873,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1862
1873
  return result;
1863
1874
  }
1864
1875
  _getCellCfs(unitId, subUnitId, row, col) {
1865
- var _this$_conditionalFor;
1866
- const subunitRules = (_this$_conditionalFor = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId)) !== null && _this$_conditionalFor !== void 0 ? _this$_conditionalFor : [];
1876
+ const subunitRules = this._conditionalFormattingRuleModel.getSubunitRules(unitId, subUnitId) ?? [];
1867
1877
  const _calculateUnitManagers = this._ensureCalculateUnitManager(unitId, subUnitId);
1868
1878
  const list = this._conditionalFormattingRangeIndexModel.getRuleIdsByCell(unitId, subUnitId, row, col);
1869
1879
  const rules = subunitRules.filter((rule) => list.has(rule.cfId));
@@ -1887,6 +1897,7 @@ let ConditionalFormattingViewModel = class ConditionalFormattingViewModel extend
1887
1897
  clearCache() {
1888
1898
  this._calculateUnitManagers.clear();
1889
1899
  this._cellCache.clear();
1900
+ this._cacheClear$.next();
1890
1901
  }
1891
1902
  _handleCustomFormulasSeparately() {
1892
1903
  this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe((e) => {
@@ -2544,7 +2555,7 @@ for (const key in iconMap) {
2544
2555
  //#endregion
2545
2556
  //#region package.json
2546
2557
  var name = "@univerjs/sheets-conditional-formatting";
2547
- var version = "1.0.0-alpha.8";
2558
+ var version = "1.0.0-beta.1";
2548
2559
 
2549
2560
  //#endregion
2550
2561
  //#region src/config/config.ts
@@ -2569,14 +2580,28 @@ const defaultPluginConfig = {};
2569
2580
 
2570
2581
  //#endregion
2571
2582
  //#region src/services/conditional-formatting-style-composer.service.ts
2572
- let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer {
2583
+ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleComposer extends Disposable {
2573
2584
  constructor(_conditionalFormattingRuleModel, _conditionalFormattingViewModel) {
2585
+ super();
2574
2586
  this._conditionalFormattingRuleModel = _conditionalFormattingRuleModel;
2575
2587
  this._conditionalFormattingViewModel = _conditionalFormattingViewModel;
2588
+ _defineProperty(this, "_cache", new LRUMap(CONDITIONAL_FORMATTING_VIEWPORT_CACHE_LENGTH));
2589
+ this.disposeWithMe(this._conditionalFormattingRuleModel.$ruleChange.subscribe(() => this._cache.clear()));
2590
+ this.disposeWithMe(this._conditionalFormattingViewModel.markDirty$.subscribe(() => this._cache.clear()));
2591
+ this.disposeWithMe(this._conditionalFormattingViewModel.cacheClear$.subscribe(() => this._cache.clear()));
2592
+ }
2593
+ dispose() {
2594
+ this._cache.clear();
2595
+ super.dispose();
2576
2596
  }
2577
2597
  composeStyle(unitId, subUnitId, row, col) {
2598
+ const cacheKey = `${unitId}_${subUnitId}_${row}_${col}`;
2599
+ if (this._cache.has(cacheKey)) return this._cache.get(cacheKey) ?? null;
2578
2600
  const cellCfs = this._conditionalFormattingViewModel.getCellCfs(unitId, subUnitId, row, col);
2579
- if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) return null;
2601
+ if (!(cellCfs === null || cellCfs === void 0 ? void 0 : cellCfs.length)) {
2602
+ this._cache.set(cacheKey, null);
2603
+ return null;
2604
+ }
2580
2605
  const matchedRules = [];
2581
2606
  let stopIfTrueIndex = -1;
2582
2607
  for (const cacheItem of cellCfs) {
@@ -2588,13 +2613,17 @@ let ConditionalFormattingStyleComposer = class ConditionalFormattingStyleCompose
2588
2613
  });
2589
2614
  if (stopIfTrueIndex === -1 && rule.stopIfTrue && this._isRuleMatched(rule, cacheItem.result)) stopIfTrueIndex = matchedRules.length - 1;
2590
2615
  }
2591
- if (!matchedRules.length) return null;
2616
+ if (!matchedRules.length) {
2617
+ this._cache.set(cacheKey, null);
2618
+ return null;
2619
+ }
2592
2620
  const effectiveRules = stopIfTrueIndex > -1 ? matchedRules.slice(0, stopIfTrueIndex + 1) : matchedRules;
2593
2621
  const result = {};
2594
2622
  for (let i = effectiveRules.length - 1; i >= 0; i--) {
2595
2623
  const { rule, cacheItem } = effectiveRules[i];
2596
2624
  this._mergeComposeResult(result, rule, cacheItem.result);
2597
2625
  }
2626
+ this._cache.set(cacheKey, result);
2598
2627
  return result;
2599
2628
  }
2600
2629
  _mergeComposeResult(result, rule, ruleResult) {
@@ -2958,16 +2987,22 @@ var ConditionalFormattingIcon = class extends SheetExtension {
2958
2987
  _defineProperty(this, "_paddingRightAndLeft", 2);
2959
2988
  _defineProperty(this, "_width", 15);
2960
2989
  _defineProperty(this, "_imageMap", /* @__PURE__ */ new Map());
2990
+ _defineProperty(this, "_renderRangeResolver", null);
2961
2991
  _defineProperty(this, "uKey", IconUKey);
2962
2992
  _defineProperty(this, "Z_INDEX", EXTENSION_Z_INDEX);
2963
2993
  _defineProperty(this, "_radius", 1);
2964
2994
  this._init();
2965
2995
  }
2996
+ setRenderRangeResolver(resolver) {
2997
+ this._renderRangeResolver = resolver;
2998
+ }
2966
2999
  draw(ctx, _parentScale, spreadsheetSkeleton, diffRanges) {
2967
3000
  const { worksheet } = spreadsheetSkeleton;
2968
3001
  if (!worksheet) return false;
2969
3002
  const mergeCellRendered = /* @__PURE__ */ new Set();
2970
- const renderRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3003
+ const sourceRanges = (diffRanges === null || diffRanges === void 0 ? void 0 : diffRanges.length) ? diffRanges : [spreadsheetSkeleton.rowColumnSegment];
3004
+ const renderRanges = this._renderRangeResolver && worksheet.getMergeData().length === 0 ? this._renderRangeResolver(worksheet.getUnitId(), worksheet.getSheetId(), sourceRanges) ?? sourceRanges : sourceRanges;
3005
+ if (!renderRanges.length) return;
2971
3006
  ctx.save();
2972
3007
  renderRanges.forEach((range) => {
2973
3008
  Range.foreach(range, (row, col) => {
@@ -2997,6 +3032,10 @@ var ConditionalFormattingIcon = class extends SheetExtension {
2997
3032
  });
2998
3033
  ctx.restore();
2999
3034
  }
3035
+ dispose() {
3036
+ this._renderRangeResolver = null;
3037
+ super.dispose();
3038
+ }
3000
3039
  _init() {
3001
3040
  for (const type in iconMap) iconMap[type].forEach((base64, index) => {
3002
3041
  const key = this._createKey(type, String(index));
@@ -25,7 +25,7 @@ declare class ConditionalFormatRuleBaseBuilder {
25
25
  protected get _ruleConfig(): IConditionalFormattingRuleConfig | null;
26
26
  protected _getDefaultConfig(type?: CFRuleType): IConditionalFormattingRuleConfig;
27
27
  constructor(initRule?: Partial<IConditionFormattingRule>);
28
- protected _ensureAttr(obj: Record<string, any>, keys: string[]): Record<string, any>;
28
+ protected _ensureAttr<T extends object>(obj: T, keys: string[]): T;
29
29
  /**
30
30
  * Constructs a conditional format rule from the settings applied to the builder.
31
31
  * @returns {IConditionFormattingRule} The conditional format rule.
@@ -30,6 +30,7 @@ export declare class ConditionalFormattingViewModel extends Disposable {
30
30
  */
31
31
  private _cellCache;
32
32
  private _markDirty$;
33
+ private _cacheClear$;
33
34
  /**
34
35
  * The rendering layer listens to this variable to determine whether a reRender is necessary.
35
36
  * @memberof ConditionalFormattingViewModel
@@ -40,6 +41,7 @@ export declare class ConditionalFormattingViewModel extends Disposable {
40
41
  subUnitId: string;
41
42
  isImmediately?: boolean;
42
43
  }>;
44
+ cacheClear$: import("rxjs").Observable<void>;
43
45
  constructor(_injector: Injector, _conditionalFormattingRuleModel: ConditionalFormattingRuleModel, _conditionalFormattingRangeIndexModel: ConditionalFormattingRangeIndexModel, _conditionalFormattingFormulaService: ConditionalFormattingFormulaService, _univerInstanceService: IUniverInstanceService);
44
46
  private _initCFFormulaListener;
45
47
  getCellCfs(unitId: string, subUnitId: string, row: number, col: number): {
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import type { IRange, IScale } from '@univerjs/core';
17
17
  import type { SpreadsheetSkeleton, UniverRenderingContext } from '@univerjs/engine-render';
18
+ import type { IConditionalFormattingRenderRangeResolver } from './type';
18
19
  import { SheetExtension } from '@univerjs/engine-render';
19
20
  export declare const dataBarUKey = "sheet-conditional-rule-data-bar";
20
21
  export declare const defaultDataBarPositiveColor = "#ffbe38";
@@ -23,9 +24,12 @@ export declare const defaultPlaceholderColor = "#000";
23
24
  export declare class DataBar extends SheetExtension {
24
25
  private _paddingRightAndLeft;
25
26
  private _paddingTopAndBottom;
27
+ private _renderRangeResolver;
26
28
  uKey: string;
27
29
  Z_INDEX: number;
28
30
  _radius: number;
31
+ setRenderRangeResolver(resolver: IConditionalFormattingRenderRangeResolver | null): void;
29
32
  draw(ctx: UniverRenderingContext, _parentScale: IScale, spreadsheetSkeleton: SpreadsheetSkeleton, diffRanges: IRange[]): false | undefined;
33
+ dispose(): void;
30
34
  private _drawRectWithRoundedCorner;
31
35
  }
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import type { IRange, IScale } from '@univerjs/core';
17
17
  import type { SpreadsheetSkeleton, UniverRenderingContext } from '@univerjs/engine-render';
18
+ import type { IConditionalFormattingRenderRangeResolver } from './type';
18
19
  import { SheetExtension } from '@univerjs/engine-render';
19
20
  export declare const IconUKey = "sheet-conditional-rule-icon";
20
21
  export declare const DEFAULT_WIDTH = 15;
@@ -23,11 +24,14 @@ export declare class ConditionalFormattingIcon extends SheetExtension {
23
24
  private _paddingRightAndLeft;
24
25
  private _width;
25
26
  private _imageMap;
27
+ private _renderRangeResolver;
26
28
  uKey: string;
27
29
  Z_INDEX: number;
28
30
  _radius: number;
29
31
  constructor();
32
+ setRenderRangeResolver(resolver: IConditionalFormattingRenderRangeResolver | null): void;
30
33
  draw(ctx: UniverRenderingContext, _parentScale: IScale, spreadsheetSkeleton: SpreadsheetSkeleton, diffRanges: IRange[]): false | undefined;
34
+ dispose(): void;
31
35
  private _init;
32
36
  private _createKey;
33
37
  }
@@ -13,8 +13,9 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import type { ICellData } from '@univerjs/core';
16
+ import type { ICellData, IRange } from '@univerjs/core';
17
17
  import type { IIconSetType } from '../models/icon-map';
18
+ export type IConditionalFormattingRenderRangeResolver = (unitId: string, subUnitId: string, ranges: IRange[]) => IRange[] | null;
18
19
  export interface IDataBarRenderParams {
19
20
  color: string;
20
21
  value: number;