@trebco/treb 31.3.2 → 31.3.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.
package/dist/treb.d.ts CHANGED
@@ -407,6 +407,42 @@ export declare class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
407
407
  */
408
408
  ExternalEditor(config?: Partial<ExternalEditorConfig>): void;
409
409
 
410
+ /**
411
+ * @internalRemarks removing internal flag
412
+ */
413
+ ConditionalFormatDuplicateValues(range: RangeReference | undefined, options: ConditionalFormatDuplicateValuesOptions): ConditionalFormat;
414
+
415
+ /**
416
+ * @internalRemarks removing internal flag
417
+ */
418
+ ConditionalFormatGradient(range: RangeReference | undefined, options: ConditionalFormatGradientOptions | StandardGradient): ConditionalFormat;
419
+
420
+ /**
421
+ * @internalRemarks removing internal flag
422
+ */
423
+ ConditionalFormatCellMatch(range: RangeReference | undefined, options: ConditionalFormatCellMatchOptions): ConditionalFormat;
424
+
425
+ /**
426
+ * @internalRemarks removing internal flag
427
+ */
428
+ ConditionalFormatExpression(range: RangeReference | undefined, options: CondifionalFormatExpressionOptions): ConditionalFormat;
429
+
430
+ /**
431
+ * remove conditional format
432
+ *
433
+ * @internalRemarks removing internal flag
434
+ */
435
+ RemoveConditionalFormat(format: ConditionalFormat): void;
436
+
437
+ /**
438
+ * clear conditional formats from the target range (or currently selected
439
+ * range). we operate on format objects, meaning we'll remove the whole
440
+ * format object rather than clip the area.
441
+ *
442
+ * @internalRemarks removing internal flag
443
+ */
444
+ RemoveConditionalFormats(range?: RangeReference): void;
445
+
410
446
  /** dynamically load language module */
411
447
  LoadLanguage(language?: string): Promise<void>;
412
448
 
@@ -1152,42 +1188,79 @@ export interface FreezePane {
1152
1188
  rows: number;
1153
1189
  columns: number;
1154
1190
  }
1191
+ export interface CondifionalFormatExpressionOptions {
1192
+ style: CellStyle;
1193
+ expression: string;
1194
+ options?: EvaluateOptions;
1195
+ }
1196
+ export interface ConditionalFormatGradientOptions {
1155
1197
 
1156
- /**
1157
- * options for serializing data
1158
- */
1159
- export interface SerializeOptions {
1160
-
1161
- /** optimize for size */
1162
- optimize?: 'size' | 'speed';
1198
+ /** property defaults to fill */
1199
+ property?: 'fill' | 'text';
1163
1200
 
1164
- /** include the rendered/calculated value in export */
1165
- rendered_values?: boolean;
1201
+ /** defaults to RGB */
1202
+ color_space?: 'HSL' | 'RGB';
1166
1203
 
1167
- /** translate colors to xlsx-friendly values */
1168
- export_colors?: boolean;
1204
+ /** gradient stops, required */
1205
+ stops: Array<{
1206
+ value: number;
1207
+ color: Color;
1208
+ }>;
1169
1209
 
1170
- /** export cells that have no value, but have a border or background color */
1171
- decorated_cells?: boolean;
1210
+ /** min and max are optional. if not provided, we use the min/max of the range of data. */
1211
+ min?: number;
1172
1212
 
1173
- /** prune unused rows/columns */
1174
- shrink?: boolean;
1213
+ /** min and max are optional. if not provided, we use the min/max of the range of data. */
1214
+ max?: number;
1215
+ }
1216
+ export type StandardGradient = keyof typeof StandardGradientsList;
1217
+ export interface ConditionalFormatCellMatchOptions {
1218
+ style: CellStyle;
1219
+ expression: string;
1220
+ options?: EvaluateOptions;
1221
+ }
1222
+ export interface ConditionalFormatDuplicateValuesOptions {
1223
+ style: CellStyle;
1175
1224
 
1176
- /**
1177
- * include tables. tables will be serialized in the model, so we can
1178
- * drop them from cells. but you can leave them in if that's useful.
1179
- */
1180
- tables?: boolean;
1225
+ /** true to highlight unique cells, false to highlight duplicates. defaults to false. */
1226
+ unique?: boolean;
1227
+ }
1181
1228
 
1182
- /** share resources (images, for now) to prevent writing data URIs more than once */
1183
- share_resources?: boolean;
1229
+ /**
1230
+ * union, plus we're adding a state used to track application.
1231
+ * that state is serialized if it's true.
1232
+ * we also add an internal field that will be type-specific, and not serialized.
1233
+ *
1234
+ * ...everybody has a vertex now, we could standardize it
1235
+ *
1236
+ * update: adding a priority field, optional
1237
+ *
1238
+ */
1239
+ export type ConditionalFormat = {
1240
+ internal?: unknown;
1241
+ priority?: number;
1242
+ } & (ConditionalFormatDuplicateValues | ConditionalFormatExpression | ConditionalFormatCellMatch | ConditionalFormatGradient);
1184
1243
 
1185
- /**
1186
- * if a function has an export() handler, call that
1187
- */
1188
- export_functions?: boolean;
1244
+ /**
1245
+ * conditional format predicated on an expression. if the expression
1246
+ * evaluates to true, we apply the style. otherwise no.
1247
+ */
1248
+ export interface ConditionalFormatExpression extends CondifionalFormatExpressionOptions {
1249
+ type: 'expression';
1250
+ area: IArea;
1251
+ }
1252
+ export interface ConditionalFormatGradient extends ConditionalFormatGradientOptions {
1253
+ type: 'gradient';
1254
+ area: IArea;
1255
+ }
1256
+ export interface ConditionalFormatCellMatch extends ConditionalFormatCellMatchOptions {
1257
+ type: 'cell-match';
1258
+ area: IArea;
1259
+ }
1260
+ export interface ConditionalFormatDuplicateValues extends ConditionalFormatDuplicateValuesOptions {
1261
+ type: 'duplicate-values';
1262
+ area: IArea;
1189
1263
  }
1190
- export type AnnotationType = 'treb-chart' | 'image' | 'textbox' | 'external';
1191
1264
 
1192
1265
  /**
1193
1266
  * Structure represents a 2d range of cells.
@@ -1196,18 +1269,7 @@ export interface IArea {
1196
1269
  start: ICellAddress;
1197
1270
  end: ICellAddress;
1198
1271
  }
1199
- export interface Point {
1200
- x: number;
1201
- y: number;
1202
- }
1203
-
1204
- /** structure represents rectangle coordinates */
1205
- export interface IRectangle {
1206
- top: number;
1207
- left: number;
1208
- width: number;
1209
- height: number;
1210
- }
1272
+ export type Color = ThemeColor | HTMLColor | NullColor;
1211
1273
 
1212
1274
  /**
1213
1275
  * style properties applied to a single cell, row, column, or sheet.
@@ -1315,11 +1377,78 @@ export interface ThemeColor {
1315
1377
  }
1316
1378
  export interface NullColor {
1317
1379
  }
1318
- export type Color = ThemeColor | HTMLColor | NullColor;
1319
1380
  export declare const ThemeColorIndex: (color: ThemeColor) => number;
1320
1381
  export declare const IsHTMLColor: (color?: Color) => color is HTMLColor;
1321
1382
  export declare const IsThemeColor: (color?: Color) => color is ThemeColor;
1322
1383
  export declare const IsDefinedColor: (color?: Color) => color is (ThemeColor | HTMLColor);
1384
+
1385
+ /**
1386
+ * options for the evaluate function
1387
+ */
1388
+ export interface EvaluateOptions {
1389
+
1390
+ /**
1391
+ * argument separator to use when parsing input. set this option to
1392
+ * use a consistent argument separator independent of current locale.
1393
+ */
1394
+ argument_separator?: ',' | ';';
1395
+
1396
+ /**
1397
+ * allow R1C1-style references. the Evaluate function cannot use
1398
+ * relative references (e.g. R[-1]C[0]), so those will always fail.
1399
+ * however it may be useful to use direct R1C1 references (e.g. R3C4),
1400
+ * so we optionally support that behind this flag.
1401
+ */
1402
+ r1c1?: boolean;
1403
+ }
1404
+
1405
+ /**
1406
+ * options for serializing data
1407
+ */
1408
+ export interface SerializeOptions {
1409
+
1410
+ /** optimize for size */
1411
+ optimize?: 'size' | 'speed';
1412
+
1413
+ /** include the rendered/calculated value in export */
1414
+ rendered_values?: boolean;
1415
+
1416
+ /** translate colors to xlsx-friendly values */
1417
+ export_colors?: boolean;
1418
+
1419
+ /** export cells that have no value, but have a border or background color */
1420
+ decorated_cells?: boolean;
1421
+
1422
+ /** prune unused rows/columns */
1423
+ shrink?: boolean;
1424
+
1425
+ /**
1426
+ * include tables. tables will be serialized in the model, so we can
1427
+ * drop them from cells. but you can leave them in if that's useful.
1428
+ */
1429
+ tables?: boolean;
1430
+
1431
+ /** share resources (images, for now) to prevent writing data URIs more than once */
1432
+ share_resources?: boolean;
1433
+
1434
+ /**
1435
+ * if a function has an export() handler, call that
1436
+ */
1437
+ export_functions?: boolean;
1438
+ }
1439
+ export type AnnotationType = 'treb-chart' | 'image' | 'textbox' | 'external';
1440
+ export interface Point {
1441
+ x: number;
1442
+ y: number;
1443
+ }
1444
+
1445
+ /** structure represents rectangle coordinates */
1446
+ export interface IRectangle {
1447
+ top: number;
1448
+ left: number;
1449
+ width: number;
1450
+ height: number;
1451
+ }
1323
1452
  export type CellValue = undefined | string | number | boolean | Complex | DimensionedQuantity;
1324
1453
 
1325
1454
  /**
@@ -1396,26 +1525,6 @@ export interface TableSortOptions {
1396
1525
  }
1397
1526
  export type TableSortType = 'text' | 'numeric' | 'auto';
1398
1527
 
1399
- /**
1400
- * options for the evaluate function
1401
- */
1402
- export interface EvaluateOptions {
1403
-
1404
- /**
1405
- * argument separator to use when parsing input. set this option to
1406
- * use a consistent argument separator independent of current locale.
1407
- */
1408
- argument_separator?: ',' | ';';
1409
-
1410
- /**
1411
- * allow R1C1-style references. the Evaluate function cannot use
1412
- * relative references (e.g. R[-1]C[0]), so those will always fail.
1413
- * however it may be useful to use direct R1C1 references (e.g. R3C4),
1414
- * so we optionally support that behind this flag.
1415
- */
1416
- r1c1?: boolean;
1417
- }
1418
-
1419
1528
  /** clipboard data is a 2d array */
1420
1529
  export type ClipboardData = ClipboardDataElement[][];
1421
1530
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "31.3.2",
3
+ "version": "31.3.4",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "homepage": "https://treb.app",
6
6
  "repository": {
@@ -1481,7 +1481,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1481
1481
 
1482
1482
  }
1483
1483
 
1484
- /** @internal */
1484
+ /**
1485
+ * @internalRemarks removing internal flag
1486
+ */
1485
1487
  public ConditionalFormatDuplicateValues(range: RangeReference|undefined, options: ConditionalFormatDuplicateValuesOptions): ConditionalFormat {
1486
1488
 
1487
1489
  return this.AddConditionalFormat({
@@ -1493,7 +1495,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1493
1495
  }
1494
1496
 
1495
1497
  /**
1496
- * @internal
1498
+ * @internalRemarks removing internal flag
1497
1499
  */
1498
1500
  public ConditionalFormatGradient(range: RangeReference|undefined, options: ConditionalFormatGradientOptions|StandardGradient): ConditionalFormat {
1499
1501
 
@@ -1512,7 +1514,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1512
1514
 
1513
1515
  }
1514
1516
 
1515
- /** @internal */
1517
+ /**
1518
+ * @internalRemarks removing internal flag
1519
+ */
1516
1520
  public ConditionalFormatCellMatch(range: RangeReference|undefined, options: ConditionalFormatCellMatchOptions): ConditionalFormat {
1517
1521
 
1518
1522
  const format: ConditionalFormatCellMatch = {
@@ -1528,7 +1532,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1528
1532
  }
1529
1533
 
1530
1534
  /**
1531
- * @internal
1535
+ * @internalRemarks removing internal flag
1532
1536
  */
1533
1537
  public ConditionalFormatExpression(range: RangeReference|undefined, options: CondifionalFormatExpressionOptions): ConditionalFormat {
1534
1538
 
@@ -1561,7 +1565,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1561
1565
  /**
1562
1566
  * remove conditional format
1563
1567
  *
1564
- * @internal
1568
+ * @internalRemarks removing internal flag
1565
1569
  */
1566
1570
  public RemoveConditionalFormat(format: ConditionalFormat) {
1567
1571
  this.grid.RemoveConditionalFormat({ format });
@@ -1572,7 +1576,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1572
1576
  * range). we operate on format objects, meaning we'll remove the whole
1573
1577
  * format object rather than clip the area.
1574
1578
  *
1575
- * @internal
1579
+ * @internalRemarks removing internal flag
1576
1580
  */
1577
1581
  public RemoveConditionalFormats(range?: RangeReference) {
1578
1582
  const area = this.RangeOrSelection(range);
@@ -1602,6 +1606,23 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1602
1606
  // only handle a limited set of commands, then
1603
1607
 
1604
1608
  switch (event.command) {
1609
+ case 'adjust-font-scale':
1610
+ {
1611
+ const delta = Number(event.delta || 0);
1612
+ let scale = this.grid.GetAnnotationStyle()?.font_size;
1613
+
1614
+ if (!scale || scale.unit !== 'em') {
1615
+ scale = { unit: 'em', value: 1 };
1616
+ }
1617
+
1618
+ if (scale) {
1619
+ scale.value += delta;
1620
+ updated_style.font_size = scale;
1621
+ this.grid.ApplyAnnotationStyle(updated_style);
1622
+ }
1623
+ }
1624
+ break;
1625
+
1605
1626
  case 'font-scale':
1606
1627
  {
1607
1628
  const scale = Number(event.scale || 1);
@@ -1629,7 +1650,13 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1629
1650
  const selection = this.grid.GetSelection();
1630
1651
  if (selection && !selection.empty) {
1631
1652
  const label = selection.area.spreadsheet_label;
1632
- this.InsertAnnotation(`=${func}(${label},,"${label}")`, undefined, undefined, ',');
1653
+
1654
+ if (func === 'Scatter.Plot' || func === 'Scatter.Line') {
1655
+ this.InsertAnnotation(`=${func}(Series(,,${label}),"${label}")`, undefined, undefined, ',');
1656
+ }
1657
+ else {
1658
+ this.InsertAnnotation(`=${func}(${label},,"${label}")`, undefined, undefined, ',');
1659
+ }
1633
1660
  }
1634
1661
  };
1635
1662
 
@@ -1682,6 +1709,41 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1682
1709
  }
1683
1710
  break;
1684
1711
 
1712
+ case 'adjust-font-scale':
1713
+ {
1714
+ let scale = this.selection_state.style?.font_size;
1715
+ const selection = this.grid.GetSelection();
1716
+ const area = this.grid.active_sheet.RealArea(selection.area);
1717
+ const delta = Number(event.delta || 0);
1718
+
1719
+ if (!scale || scale.unit !== 'em') {
1720
+ scale = { unit: 'em', value: 1 };
1721
+ }
1722
+
1723
+ // console.info({scale, delta});
1724
+
1725
+ if (scale && delta && !isNaN(delta)) {
1726
+ scale.value += delta;
1727
+ this.grid.ApplyStyle(undefined, {
1728
+ font_size: scale,
1729
+ }, true);
1730
+ const rows: number[] = [];
1731
+ for (let row = area.start.row; row <= area.end.row; row++) {
1732
+ rows.push(row);
1733
+ }
1734
+
1735
+ // tweak: don't resize row if merged, even if the merged
1736
+ // area is too small
1737
+
1738
+ if (!this.selection_state?.merge) {
1739
+ this.grid.SetRowHeight(rows, undefined, false);
1740
+ }
1741
+
1742
+ }
1743
+
1744
+ }
1745
+ break;
1746
+
1685
1747
  case 'font-scale':
1686
1748
 
1687
1749
  // above we handle 'font-size' events; this comes from a dropdown,
@@ -1695,6 +1757,9 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1695
1757
  const scale = Number(event.scale || 1);
1696
1758
 
1697
1759
  if (scale && !isNaN(scale)) {
1760
+
1761
+ console.info("FS", scale);
1762
+
1698
1763
  this.grid.ApplyStyle(undefined, {
1699
1764
  //font_size_unit: 'em', font_size_value: scale
1700
1765
  font_size: {
@@ -1709,6 +1774,10 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1709
1774
  // tweak: don't resize row if merged, even if the merged
1710
1775
  // area is too small
1711
1776
 
1777
+ // this should wait, because apply style is async.
1778
+ // actually shouldn't it do that automatically because
1779
+ // this is _also_ async? TODO: check that
1780
+
1712
1781
  if (!this.selection_state?.merge) {
1713
1782
  this.grid.SetRowHeight(rows, undefined, false);
1714
1783
  }
@@ -1773,6 +1842,7 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
1773
1842
  case 'insert-column-chart': insert_annotation('Column.Chart'); break;
1774
1843
  case 'insert-bar-chart': insert_annotation('Bar.Chart'); break;
1775
1844
  case 'insert-line-chart': insert_annotation('Line.Chart'); break;
1845
+ case 'insert-scatter-plot': insert_annotation('Scatter.Plot'); break;
1776
1846
 
1777
1847
  case 'increase-precision':
1778
1848
  case 'decrease-precision':
@@ -23,7 +23,7 @@ export interface BorderToolbarMessage {
23
23
  }
24
24
 
25
25
  export interface AnnotationToolbarMessage {
26
- command: 'insert-image'|'insert-donut-chart'|'insert-line-chart'|'insert-column-chart'|'insert-bar-chart';
26
+ command: 'insert-image'|'insert-donut-chart'|'insert-line-chart'|'insert-column-chart'|'insert-bar-chart'|'insert-scatter-plot';
27
27
  }
28
28
 
29
29
  export interface LayoutToolbarMessage {
@@ -55,6 +55,11 @@ export interface FontScaleToolbarMessage {
55
55
  scale?: number;
56
56
  }
57
57
 
58
+ export interface AdjustFontScaleToolbarMessage {
59
+ command: 'adjust-font-scale';
60
+ delta: number;
61
+ }
62
+
58
63
  export interface FontStackToolbarMessage {
59
64
  command: 'font-stack';
60
65
  font_stack?: string;
@@ -108,5 +113,6 @@ export type ToolbarMessage
108
113
  | IndentMessage
109
114
  | NumberFormatToolbarMessage
110
115
  | FontScaleToolbarMessage
116
+ | AdjustFontScaleToolbarMessage
111
117
  | FontStackToolbarMessage
112
118
  ;
@@ -121,6 +121,10 @@
121
121
  flex-direction: column;
122
122
  justify-content: center;
123
123
 
124
+ & > .treb-editor-shadow {
125
+ opacity: .4;
126
+ }
127
+
124
128
  }
125
129
 
126
130
  &[expanded] {
@@ -67,6 +67,26 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
67
67
 
68
68
  public tolled?: { text: string, substring: string };
69
69
 
70
+ /**
71
+ * if we're showing a spill array and it's not the first cell, show
72
+ * the formula using a shadow style (and it's not editable).
73
+ */
74
+ public shadow_ = false;
75
+
76
+ public get shadow() { return this.shadow_; }
77
+
78
+ public set shadow(shadow: boolean) {
79
+ this.shadow_ = shadow;
80
+ if (this.active_editor?.node) {
81
+ if (shadow) {
82
+ this.active_editor.node.classList.add('treb-editor-shadow');
83
+ }
84
+ else {
85
+ this.active_editor.node.classList.remove('treb-editor-shadow');
86
+ }
87
+ }
88
+ }
89
+
70
90
  /** is the _editor_ currently focused */
71
91
  // tslint:disable-next-line:variable-name
72
92
  public focused_ = false;
@@ -244,6 +264,12 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
244
264
 
245
265
  let text = this.active_editor.node.textContent || '';
246
266
 
267
+ if (this.shadow) {
268
+ this.shadow = false;
269
+ text = '';
270
+ this.active_editor.node.textContent = text;
271
+ this.active_editor.formatted_text = undefined; // why do we clear this here?
272
+ }
247
273
  if (text[0] === '{' && text[text.length - 1] === '}') {
248
274
  text = text.substring(1, text.length - 1);
249
275
  this.active_editor.node.textContent = text;
@@ -555,6 +581,7 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
555
581
  case 'Escape':
556
582
  case 'Esc':
557
583
  // this.selecting_ = false;
584
+ this.committed = true;
558
585
  this.Publish({ type: 'discard' });
559
586
  // this.FlushReference();
560
587
  break;
@@ -1698,6 +1698,19 @@ export class Grid extends GridBase {
1698
1698
 
1699
1699
  }
1700
1700
 
1701
+ /**
1702
+ *
1703
+ */
1704
+ public GetAnnotationStyle(): CellStyle|undefined {
1705
+ if (this.selected_annotation) {
1706
+ if (this.selected_annotation.data?.style) {
1707
+ return JSON.parse(JSON.stringify(this.selected_annotation.data.style));
1708
+ }
1709
+ return {};
1710
+ }
1711
+ return undefined;
1712
+ }
1713
+
1701
1714
  /**
1702
1715
  *
1703
1716
  */
@@ -2612,7 +2625,7 @@ export class Grid extends GridBase {
2612
2625
 
2613
2626
  const current_width = sheet.GetColumnWidth(column);
2614
2627
  let max_width = 0;
2615
- const padding = 12; // 4 * 2; // FIXME: parameterize
2628
+ const padding = 14; // 4 * 2; // FIXME: parameterize
2616
2629
 
2617
2630
  for (let row = 0; row < sheet.cells.rows; row++) {
2618
2631
  const cell = sheet.CellData({ row, column });
@@ -5386,6 +5399,8 @@ export class Grid extends GridBase {
5386
5399
  */
5387
5400
  private SetInferredType(selection: GridSelection, value: string|undefined, array = false, exec = true, apply_style?: CellStyle) {
5388
5401
 
5402
+ console.info("SIT", {apply_style});
5403
+
5389
5404
  // validation: cannot change part of an array without changing the
5390
5405
  // whole array. so check the array. separately, if you are entering
5391
5406
  // an array, make sure that no affected cell is part of an existing
@@ -5464,10 +5479,22 @@ export class Grid extends GridBase {
5464
5479
 
5465
5480
  const commands: Command[] = [];
5466
5481
 
5482
+ /*
5483
+
5484
+ this was here to use the currently selected font stack, but it's broken - it
5485
+ clears backgrounds. temp removed in advance of proper fix.
5486
+
5487
+ ...because it was missing the `delta` parameter. I guess that defaults to false?
5488
+
5489
+ we never specified, and it's a boolean in an interface, so it defaults to false
5490
+
5491
+ */
5492
+
5467
5493
  if (apply_style) {
5468
5494
  commands.push({
5469
5495
  key: CommandKey.UpdateStyle,
5470
5496
  style: apply_style,
5497
+ delta: true,
5471
5498
  area: array ? selection.area : selection.target,
5472
5499
  })
5473
5500
  }
@@ -6692,6 +6719,7 @@ export class Grid extends GridBase {
6692
6719
 
6693
6720
  if (override) {
6694
6721
  if (this.formula_bar) {
6722
+ this.formula_bar.shadow = false;
6695
6723
  this.formula_bar.formula = override;
6696
6724
  }
6697
6725
  return;
@@ -6699,6 +6727,7 @@ export class Grid extends GridBase {
6699
6727
 
6700
6728
  if (this.primary_selection.empty) {
6701
6729
  if (this.formula_bar) {
6730
+ this.formula_bar.shadow = false;
6702
6731
  this.formula_bar.formula = '';
6703
6732
  }
6704
6733
  }
@@ -6708,11 +6737,14 @@ export class Grid extends GridBase {
6708
6737
  // optimally we would do this check prior to this call, but
6709
6738
  // it's the uncommon case... not sure how important that is
6710
6739
 
6711
- const head = data.merge_area || data.area;
6740
+ const head = data.merge_area || data.area || data.spill;
6741
+ let shadow = false;
6742
+
6712
6743
  if (head) {
6713
6744
  if (head.start.column !== this.primary_selection.target.column
6714
6745
  || head.start.row !== this.primary_selection.target.row) {
6715
6746
  data = this.active_sheet.CellData(head.start);
6747
+ if (data.spill) { shadow = true; }
6716
6748
  }
6717
6749
  }
6718
6750
 
@@ -6752,12 +6784,13 @@ export class Grid extends GridBase {
6752
6784
 
6753
6785
  if (this.formula_bar) {
6754
6786
 
6755
- // add braces for area
6787
+ this.formula_bar.shadow = shadow;
6788
+
6756
6789
  if (data.area) {
6757
6790
  this.formula_bar.formula = '{' + (value || '') + '}';
6758
6791
  }
6759
6792
  else {
6760
- this.formula_bar.formula = (typeof value !== 'undefined') ? value.toString() : ''; // value || ''; // what about zero?
6793
+ this.formula_bar.formula = (value ?? '').toString();
6761
6794
  }
6762
6795
 
6763
6796
  }