@ricsam/react-spreadsheets 0.0.13 → 0.0.14

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/README.md CHANGED
@@ -22,6 +22,22 @@ bun add @ricsam/formula-engine
22
22
 
23
23
  `react`, `react-dom` and `@ricsam/selection-manager` are peer dependencies.
24
24
 
25
+ ## Formula rendering and imported defaults
26
+
27
+ `FormulaSheet` shares engine style reads between its cell container and content,
28
+ with a bounded cache invalidated on **every engine update**, including changes to
29
+ other sheets, styles, metadata, undo and redo. Selection-only changes leave
30
+ unchanged cells alone. Consumer style/render callbacks still receive current
31
+ `isSelected` and `isBeingEdited` values; keep callback identities stable (for
32
+ example with `useCallback`) to avoid invalidating all visible cells unnecessarily.
33
+
34
+ Workbook metadata may contain `defaultCellStyle` (a `CellStyle`, optionally with
35
+ `fontFamily: string`). These imported defaults are applied beneath explicit
36
+ engine cell styles. Font sizes use the engine's CSS-pixel convention. False
37
+ bold/italic/underline values override defaults. Without this metadata the existing
38
+ CSS/application defaults remain unchanged; fonts are never inferred from nearby
39
+ cells. Existing saved imports need reimporting to recover missing source defaults.
40
+
25
41
  ## Usage
26
42
 
27
43
  Import the stylesheet once, near your app root:
package/dist/cjs/lib.cjs CHANGED
@@ -4047,6 +4047,186 @@ function FormulaSheet({
4047
4047
  viewId,
4048
4048
  workbookName
4049
4049
  ]);
4050
+ const renderCallbacks = import_react6.useMemo(() => {
4051
+ const metadata = engine.getWorkbookMetadata(workbookName);
4052
+ const defaults = metadata?.defaultCellStyle;
4053
+ const fontStyle = (style) => ({
4054
+ ...style?.fontFamily && { fontFamily: style.fontFamily },
4055
+ ...style?.bold !== undefined && { fontWeight: style.bold ? "bold" : "normal" },
4056
+ ...style?.italic !== undefined && { fontStyle: style.italic ? "italic" : "normal" },
4057
+ ...style?.underline !== undefined && { textDecoration: style.underline ? "underline" : "none" }
4058
+ });
4059
+ const styles = new Map;
4060
+ const getStyle = (cell) => {
4061
+ if (styles.has(cell.id))
4062
+ return styles.get(cell.id);
4063
+ const explicit = engine.getCellStyle({
4064
+ sheetName,
4065
+ workbookName,
4066
+ colIndex: cell.colIndex,
4067
+ rowIndex: cell.rowIndex
4068
+ });
4069
+ const style = defaults ? { ...defaults, ...explicit } : explicit;
4070
+ if (styles.size >= 4096)
4071
+ styles.clear();
4072
+ styles.set(cell.id, style);
4073
+ return style;
4074
+ };
4075
+ return {
4076
+ customCellStyle: (cell) => {
4077
+ const conditionalStyle = getStyle(cell);
4078
+ const tableInfo = engine.isCellInTable({
4079
+ sheetName,
4080
+ colIndex: cell.colIndex,
4081
+ rowIndex: cell.rowIndex,
4082
+ workbookName
4083
+ });
4084
+ if (!tableInfo) {
4085
+ const style = conditionalStyle ? {
4086
+ ...conditionalStyle.backgroundColor && {
4087
+ backgroundColor: conditionalStyle.backgroundColor
4088
+ },
4089
+ ...conditionalStyle.color && {
4090
+ color: conditionalStyle.color
4091
+ },
4092
+ ...conditionalStyle.fontSize && {
4093
+ fontSize: conditionalStyle.fontSize
4094
+ },
4095
+ ...fontStyle(conditionalStyle),
4096
+ ...getBorderCellStyle(conditionalStyle),
4097
+ ...getWrapCellStyle(conditionalStyle)
4098
+ } : {};
4099
+ return customCellStyle ? customCellStyle(cell, style) : style;
4100
+ }
4101
+ const isHeaderRow = cell.rowIndex === tableInfo.start.rowIndex;
4102
+ const isFirstColumn = cell.colIndex === tableInfo.start.colIndex;
4103
+ const isLastColumn = cell.colIndex === tableInfo.start.colIndex + tableInfo.headers.size - 1;
4104
+ const isLastRow = tableInfo.endRow.type === "number" ? cell.rowIndex === tableInfo.endRow.value : false;
4105
+ const style = {
4106
+ border: "1px solid var(--_rsp-table-border-light)"
4107
+ };
4108
+ if (isHeaderRow) {
4109
+ style.backgroundColor = "var(--_rsp-table-header-bg)";
4110
+ style.color = "var(--_rsp-table-header-color)";
4111
+ style.fontWeight = "bold";
4112
+ style.borderBottom = "2px solid var(--_rsp-table-header-border)";
4113
+ } else {
4114
+ const dataRowIndex = cell.rowIndex - tableInfo.start.rowIndex - 1;
4115
+ if (dataRowIndex % 2 === 0) {
4116
+ style.backgroundColor = "var(--_rsp-table-even-row-bg)";
4117
+ } else {
4118
+ style.backgroundColor = "var(--_rsp-table-odd-row-bg)";
4119
+ }
4120
+ }
4121
+ if (isFirstColumn) {
4122
+ style.borderLeft = "2px solid var(--_rsp-table-border-color)";
4123
+ }
4124
+ if (isLastColumn) {
4125
+ style.borderRight = "2px solid var(--_rsp-table-border-color)";
4126
+ }
4127
+ if (isHeaderRow) {
4128
+ style.borderTop = "2px solid var(--_rsp-table-border-color)";
4129
+ }
4130
+ if (isLastRow) {
4131
+ style.borderBottom = "2px solid var(--_rsp-table-border-color)";
4132
+ }
4133
+ if (conditionalStyle?.backgroundColor) {
4134
+ style.backgroundColor = conditionalStyle.backgroundColor;
4135
+ }
4136
+ if (conditionalStyle?.color) {
4137
+ style.color = conditionalStyle.color;
4138
+ }
4139
+ if (conditionalStyle?.fontSize) {
4140
+ style.fontSize = conditionalStyle.fontSize;
4141
+ }
4142
+ Object.assign(style, fontStyle(conditionalStyle));
4143
+ Object.assign(style, getBorderCellStyle(conditionalStyle));
4144
+ Object.assign(style, getWrapCellStyle(conditionalStyle));
4145
+ if (customCellStyle) {
4146
+ return customCellStyle(cell, style);
4147
+ }
4148
+ return style;
4149
+ },
4150
+ customCellRenderer: (cell) => {
4151
+ const cellRef = import_formula_engine2.getCellReference({
4152
+ colIndex: cell.colIndex,
4153
+ rowIndex: cell.rowIndex
4154
+ });
4155
+ const value = showFormulas ? sheet?.content.get(cellRef) : engine.getCellValue({
4156
+ sheetName,
4157
+ workbookName,
4158
+ colIndex: cell.colIndex,
4159
+ rowIndex: cell.rowIndex
4160
+ }, verboseErrors);
4161
+ const conditionalStyle = getStyle(cell);
4162
+ const conditionalStyleProps = {};
4163
+ if (conditionalStyle?.backgroundColor) {
4164
+ conditionalStyleProps.backgroundColor = conditionalStyle.backgroundColor;
4165
+ }
4166
+ if (conditionalStyle?.color) {
4167
+ conditionalStyleProps.color = conditionalStyle.color;
4168
+ }
4169
+ if (conditionalStyle?.fontSize) {
4170
+ conditionalStyleProps.fontSize = conditionalStyle.fontSize;
4171
+ }
4172
+ Object.assign(conditionalStyleProps, fontStyle(conditionalStyle), getWrapContentStyle(conditionalStyle));
4173
+ let defaultElement;
4174
+ if (showFormulas) {
4175
+ defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4176
+ "data-conditional-background": conditionalStyle?.backgroundColor,
4177
+ "data-conditional-text-color": conditionalStyle?.color,
4178
+ style: conditionalStyleProps,
4179
+ children: getCellDisplayText(value)
4180
+ });
4181
+ } else if (typeof value === "boolean") {
4182
+ defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4183
+ "data-conditional-background": conditionalStyle?.backgroundColor,
4184
+ "data-conditional-text-color": conditionalStyle?.color,
4185
+ "data-type": "boolean",
4186
+ style: {
4187
+ ...conditionalStyleProps,
4188
+ width: "100%",
4189
+ textAlign: "center",
4190
+ fontFamily: conditionalStyle?.fontFamily ?? "'Courier New', monospace"
4191
+ },
4192
+ children: value ? "TRUE" : "FALSE"
4193
+ });
4194
+ } else if (typeof value === "number") {
4195
+ defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4196
+ "data-conditional-background": conditionalStyle?.backgroundColor,
4197
+ "data-conditional-text-color": conditionalStyle?.color,
4198
+ "data-type": "number",
4199
+ style: { ...conditionalStyleProps, width: "100%", textAlign: "right" },
4200
+ children: value.toLocaleString("en-US", {
4201
+ minimumFractionDigits: 0,
4202
+ maximumFractionDigits: 10
4203
+ })
4204
+ });
4205
+ } else {
4206
+ defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4207
+ "data-conditional-background": conditionalStyle?.backgroundColor,
4208
+ "data-conditional-text-color": conditionalStyle?.color,
4209
+ style: { ...conditionalStyleProps, width: "100%", textAlign: "left" },
4210
+ children: getCellDisplayText(value)
4211
+ });
4212
+ }
4213
+ if (customCellRenderer) {
4214
+ return customCellRenderer(cell, defaultElement);
4215
+ }
4216
+ return defaultElement;
4217
+ }
4218
+ };
4219
+ }, [
4220
+ engine,
4221
+ state,
4222
+ workbookName,
4223
+ sheetName,
4224
+ sheet,
4225
+ showFormulas,
4226
+ verboseErrors,
4227
+ customCellStyle,
4228
+ customCellRenderer
4229
+ ]);
4050
4230
  if (!sheet) {
4051
4231
  return /* @__PURE__ */ jsx_runtime4.jsxs("div", {
4052
4232
  className: "rsp-root rsp-workbook",
@@ -4088,183 +4268,7 @@ function FormulaSheet({
4088
4268
  containerProps: isSelected && selectedArea ? {
4089
4269
  "data-grid-no-interaction": "true"
4090
4270
  } : {},
4091
- customCellStyle: (cell) => {
4092
- const conditionalStyle = engine.getCellStyle({
4093
- sheetName,
4094
- colIndex: cell.colIndex,
4095
- rowIndex: cell.rowIndex,
4096
- workbookName
4097
- });
4098
- const tableInfo = engine.isCellInTable({
4099
- sheetName,
4100
- colIndex: cell.colIndex,
4101
- rowIndex: cell.rowIndex,
4102
- workbookName
4103
- });
4104
- if (!tableInfo) {
4105
- const style = conditionalStyle ? {
4106
- ...conditionalStyle.backgroundColor && {
4107
- backgroundColor: conditionalStyle.backgroundColor
4108
- },
4109
- ...conditionalStyle.color && {
4110
- color: conditionalStyle.color
4111
- },
4112
- ...conditionalStyle.fontSize && {
4113
- fontSize: conditionalStyle.fontSize
4114
- },
4115
- ...conditionalStyle.bold && {
4116
- fontWeight: "bold"
4117
- },
4118
- ...conditionalStyle.italic && {
4119
- fontStyle: "italic"
4120
- },
4121
- ...conditionalStyle.underline && {
4122
- textDecoration: "underline"
4123
- },
4124
- ...getBorderCellStyle(conditionalStyle),
4125
- ...getWrapCellStyle(conditionalStyle)
4126
- } : {};
4127
- return customCellStyle ? customCellStyle(cell, style) : style;
4128
- }
4129
- const isHeaderRow = cell.rowIndex === tableInfo.start.rowIndex;
4130
- const isFirstColumn = cell.colIndex === tableInfo.start.colIndex;
4131
- const isLastColumn = cell.colIndex === tableInfo.start.colIndex + tableInfo.headers.size - 1;
4132
- const isLastRow = tableInfo.endRow.type === "number" ? cell.rowIndex === tableInfo.endRow.value : false;
4133
- const style = {
4134
- border: "1px solid var(--_rsp-table-border-light)"
4135
- };
4136
- if (isHeaderRow) {
4137
- style.backgroundColor = "var(--_rsp-table-header-bg)";
4138
- style.color = "var(--_rsp-table-header-color)";
4139
- style.fontWeight = "bold";
4140
- style.borderBottom = "2px solid var(--_rsp-table-header-border)";
4141
- } else {
4142
- const dataRowIndex = cell.rowIndex - tableInfo.start.rowIndex - 1;
4143
- if (dataRowIndex % 2 === 0) {
4144
- style.backgroundColor = "var(--_rsp-table-even-row-bg)";
4145
- } else {
4146
- style.backgroundColor = "var(--_rsp-table-odd-row-bg)";
4147
- }
4148
- }
4149
- if (isFirstColumn) {
4150
- style.borderLeft = "2px solid var(--_rsp-table-border-color)";
4151
- }
4152
- if (isLastColumn) {
4153
- style.borderRight = "2px solid var(--_rsp-table-border-color)";
4154
- }
4155
- if (isHeaderRow) {
4156
- style.borderTop = "2px solid var(--_rsp-table-border-color)";
4157
- }
4158
- if (isLastRow) {
4159
- style.borderBottom = "2px solid var(--_rsp-table-border-color)";
4160
- }
4161
- if (conditionalStyle?.backgroundColor) {
4162
- style.backgroundColor = conditionalStyle.backgroundColor;
4163
- }
4164
- if (conditionalStyle?.color) {
4165
- style.color = conditionalStyle.color;
4166
- }
4167
- if (conditionalStyle?.fontSize) {
4168
- style.fontSize = conditionalStyle.fontSize;
4169
- }
4170
- if (conditionalStyle?.bold) {
4171
- style.fontWeight = "bold";
4172
- }
4173
- if (conditionalStyle?.italic) {
4174
- style.fontStyle = "italic";
4175
- }
4176
- if (conditionalStyle?.underline) {
4177
- style.textDecoration = "underline";
4178
- }
4179
- Object.assign(style, getBorderCellStyle(conditionalStyle));
4180
- Object.assign(style, getWrapCellStyle(conditionalStyle));
4181
- if (customCellStyle) {
4182
- return customCellStyle(cell, style);
4183
- }
4184
- return style;
4185
- },
4186
- customCellRenderer: (cell) => {
4187
- const cellRef = import_formula_engine2.getCellReference({
4188
- colIndex: cell.colIndex,
4189
- rowIndex: cell.rowIndex
4190
- });
4191
- const value = showFormulas ? sheet?.content.get(cellRef) : engine.getCellValue({
4192
- sheetName,
4193
- workbookName,
4194
- colIndex: cell.colIndex,
4195
- rowIndex: cell.rowIndex
4196
- }, verboseErrors);
4197
- const conditionalStyle = engine.getCellStyle({
4198
- sheetName,
4199
- colIndex: cell.colIndex,
4200
- rowIndex: cell.rowIndex,
4201
- workbookName
4202
- });
4203
- const conditionalStyleProps = {};
4204
- if (conditionalStyle?.backgroundColor) {
4205
- conditionalStyleProps.backgroundColor = conditionalStyle.backgroundColor;
4206
- }
4207
- if (conditionalStyle?.color) {
4208
- conditionalStyleProps.color = conditionalStyle.color;
4209
- }
4210
- if (conditionalStyle?.fontSize) {
4211
- conditionalStyleProps.fontSize = conditionalStyle.fontSize;
4212
- }
4213
- if (conditionalStyle?.bold) {
4214
- conditionalStyleProps.fontWeight = "bold";
4215
- }
4216
- if (conditionalStyle?.italic) {
4217
- conditionalStyleProps.fontStyle = "italic";
4218
- }
4219
- if (conditionalStyle?.underline) {
4220
- conditionalStyleProps.textDecoration = "underline";
4221
- }
4222
- Object.assign(conditionalStyleProps, getWrapContentStyle(conditionalStyle));
4223
- let defaultElement;
4224
- if (showFormulas) {
4225
- defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4226
- "data-conditional-background": conditionalStyle?.backgroundColor,
4227
- "data-conditional-text-color": conditionalStyle?.color,
4228
- style: conditionalStyleProps,
4229
- children: getCellDisplayText(value)
4230
- });
4231
- } else if (typeof value === "boolean") {
4232
- defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4233
- "data-conditional-background": conditionalStyle?.backgroundColor,
4234
- "data-conditional-text-color": conditionalStyle?.color,
4235
- "data-type": "boolean",
4236
- style: {
4237
- ...conditionalStyleProps,
4238
- width: "100%",
4239
- textAlign: "center",
4240
- fontFamily: "'Courier New', monospace"
4241
- },
4242
- children: value ? "TRUE" : "FALSE"
4243
- });
4244
- } else if (typeof value === "number") {
4245
- defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4246
- "data-conditional-background": conditionalStyle?.backgroundColor,
4247
- "data-conditional-text-color": conditionalStyle?.color,
4248
- "data-type": "number",
4249
- style: { ...conditionalStyleProps, width: "100%", textAlign: "right" },
4250
- children: value.toLocaleString("en-US", {
4251
- minimumFractionDigits: 0,
4252
- maximumFractionDigits: 10
4253
- })
4254
- });
4255
- } else {
4256
- defaultElement = /* @__PURE__ */ jsx_runtime4.jsx("div", {
4257
- "data-conditional-background": conditionalStyle?.backgroundColor,
4258
- "data-conditional-text-color": conditionalStyle?.color,
4259
- style: { ...conditionalStyleProps, width: "100%", textAlign: "left" },
4260
- children: getCellDisplayText(value)
4261
- });
4262
- }
4263
- if (customCellRenderer) {
4264
- return customCellRenderer(cell, defaultElement);
4265
- }
4266
- return defaultElement;
4267
- }
4271
+ ...renderCallbacks
4268
4272
  })
4269
4273
  })
4270
4274
  ]
@@ -4623,4 +4627,4 @@ var useClickAway = (ref, callback) => {
4623
4627
  }, [ref, callback]);
4624
4628
  };
4625
4629
 
4626
- //# debugId=422BCC484554257364756E2164756E21
4630
+ //# debugId=07CD4F6A4866444B64756E2164756E21