@rowsncolumns/spreadsheet-state 29.2.0 → 29.3.3

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 (155) hide show
  1. package/dist/cjs/api/border.d.ts +1 -1
  2. package/dist/cjs/api/border.d.ts.map +1 -1
  3. package/dist/cjs/api/paste-special.d.ts +33 -2
  4. package/dist/cjs/api/paste-special.d.ts.map +1 -1
  5. package/dist/cjs/api/paste-special.js +62 -19
  6. package/dist/cjs/commands.d.ts +208 -3
  7. package/dist/cjs/commands.d.ts.map +1 -1
  8. package/dist/cjs/components/editors/cell-format/alignment-tab.d.ts +27 -0
  9. package/dist/cjs/components/editors/cell-format/alignment-tab.d.ts.map +1 -0
  10. package/dist/cjs/components/editors/cell-format/alignment-tab.js +83 -0
  11. package/dist/cjs/components/editors/cell-format/border-edges.d.ts +42 -0
  12. package/dist/cjs/components/editors/cell-format/border-edges.d.ts.map +1 -0
  13. package/dist/cjs/components/editors/cell-format/border-edges.js +118 -0
  14. package/dist/cjs/components/editors/cell-format/border-tab.d.ts +21 -0
  15. package/dist/cjs/components/editors/cell-format/border-tab.d.ts.map +1 -0
  16. package/dist/cjs/components/editors/cell-format/border-tab.js +123 -0
  17. package/dist/cjs/components/editors/cell-format/fill-tab.d.ts +14 -0
  18. package/dist/cjs/components/editors/cell-format/fill-tab.d.ts.map +1 -0
  19. package/dist/cjs/components/editors/cell-format/fill-tab.js +54 -0
  20. package/dist/cjs/components/editors/cell-format/font-tab.d.ts +18 -0
  21. package/dist/cjs/components/editors/cell-format/font-tab.d.ts.map +1 -0
  22. package/dist/cjs/components/editors/cell-format/font-tab.js +99 -0
  23. package/dist/cjs/components/editors/cell-format/list-box.d.ts +35 -0
  24. package/dist/cjs/components/editors/cell-format/list-box.d.ts.map +1 -0
  25. package/dist/cjs/components/editors/cell-format/list-box.js +37 -0
  26. package/dist/cjs/components/editors/cell-format/number-formats.d.ts +90 -0
  27. package/dist/cjs/components/editors/cell-format/number-formats.d.ts.map +1 -0
  28. package/dist/cjs/components/editors/cell-format/number-formats.js +403 -0
  29. package/dist/cjs/components/editors/cell-format/number-tab.d.ts +12 -0
  30. package/dist/cjs/components/editors/cell-format/number-tab.d.ts.map +1 -0
  31. package/dist/cjs/components/editors/cell-format/number-tab.js +194 -0
  32. package/dist/cjs/components/editors/cell-format/protection-tab.d.ts +13 -0
  33. package/dist/cjs/components/editors/cell-format/protection-tab.d.ts.map +1 -0
  34. package/dist/cjs/components/editors/cell-format/protection-tab.js +13 -0
  35. package/dist/cjs/components/editors/cell-format-editor.d.ts +31 -3
  36. package/dist/cjs/components/editors/cell-format-editor.d.ts.map +1 -1
  37. package/dist/cjs/components/editors/cell-format-editor.js +182 -636
  38. package/dist/cjs/components/editors/conditional-format-data-bar-options.d.ts +16 -0
  39. package/dist/cjs/components/editors/conditional-format-data-bar-options.d.ts.map +1 -0
  40. package/dist/cjs/components/editors/conditional-format-data-bar-options.js +166 -0
  41. package/dist/cjs/components/editors/conditional-format-editor.d.ts +7 -1
  42. package/dist/cjs/components/editors/conditional-format-editor.d.ts.map +1 -1
  43. package/dist/cjs/components/editors/conditional-format-editor.js +51 -9
  44. package/dist/cjs/components/editors/conditional-format-icon-set-options.d.ts +17 -0
  45. package/dist/cjs/components/editors/conditional-format-icon-set-options.d.ts.map +1 -0
  46. package/dist/cjs/components/editors/conditional-format-icon-set-options.js +163 -0
  47. package/dist/cjs/components/editors/conditional-format-rule-editor.d.ts +9 -0
  48. package/dist/cjs/components/editors/conditional-format-rule-editor.d.ts.map +1 -1
  49. package/dist/cjs/components/editors/conditional-format-rule-editor.js +97 -125
  50. package/dist/cjs/components/editors/sheet-filter.d.ts +20 -9
  51. package/dist/cjs/components/editors/sheet-filter.d.ts.map +1 -1
  52. package/dist/cjs/components/editors/sheet-filter.js +44 -12
  53. package/dist/cjs/constants.d.ts +3 -1
  54. package/dist/cjs/constants.d.ts.map +1 -1
  55. package/dist/cjs/constants.js +3 -0
  56. package/dist/cjs/hooks/use-conditional-formatting-rules.d.ts +2 -0
  57. package/dist/cjs/hooks/use-conditional-formatting-rules.d.ts.map +1 -1
  58. package/dist/cjs/hooks/use-conditional-formatting-rules.js +22 -1
  59. package/dist/cjs/hooks/use-on-paste.d.ts.map +1 -1
  60. package/dist/cjs/hooks/use-on-paste.js +8 -1
  61. package/dist/cjs/hooks/use-sparkline-groups.d.ts +1 -0
  62. package/dist/cjs/hooks/use-sparkline-groups.d.ts.map +1 -1
  63. package/dist/cjs/hooks/use-sparkline-groups.js +28 -1
  64. package/dist/cjs/hooks/use-spreadsheet-state.d.ts +3 -0
  65. package/dist/cjs/hooks/use-spreadsheet-state.d.ts.map +1 -1
  66. package/dist/cjs/hooks/use-spreadsheet-state.js +11 -6
  67. package/dist/cjs/index.d.ts +1 -1
  68. package/dist/cjs/index.d.ts.map +1 -1
  69. package/dist/cjs/index.js +1 -1
  70. package/dist/cjs/interface/change-border.d.ts.map +1 -1
  71. package/dist/cjs/interface/change-border.js +8 -1
  72. package/dist/cjs/interface/conditional-formatting-rules.d.ts +11 -1
  73. package/dist/cjs/interface/conditional-formatting-rules.d.ts.map +1 -1
  74. package/dist/cjs/interface/conditional-formatting-rules.js +44 -1
  75. package/dist/cjs/sheet-cell.d.ts +8 -0
  76. package/dist/cjs/sheet-cell.d.ts.map +1 -1
  77. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  78. package/dist/esm/api/border.d.ts +1 -1
  79. package/dist/esm/api/border.d.ts.map +1 -1
  80. package/dist/esm/api/paste-special.d.ts +33 -2
  81. package/dist/esm/api/paste-special.d.ts.map +1 -1
  82. package/dist/esm/api/paste-special.js +62 -13
  83. package/dist/esm/commands.d.ts +208 -3
  84. package/dist/esm/commands.d.ts.map +1 -1
  85. package/dist/esm/components/editors/cell-format/alignment-tab.d.ts +27 -0
  86. package/dist/esm/components/editors/cell-format/alignment-tab.d.ts.map +1 -0
  87. package/dist/esm/components/editors/cell-format/alignment-tab.js +81 -0
  88. package/dist/esm/components/editors/cell-format/border-edges.d.ts +42 -0
  89. package/dist/esm/components/editors/cell-format/border-edges.d.ts.map +1 -0
  90. package/dist/esm/components/editors/cell-format/border-edges.js +79 -0
  91. package/dist/esm/components/editors/cell-format/border-tab.d.ts +21 -0
  92. package/dist/esm/components/editors/cell-format/border-tab.d.ts.map +1 -0
  93. package/dist/esm/components/editors/cell-format/border-tab.js +103 -0
  94. package/dist/esm/components/editors/cell-format/fill-tab.d.ts +14 -0
  95. package/dist/esm/components/editors/cell-format/fill-tab.d.ts.map +1 -0
  96. package/dist/esm/components/editors/cell-format/fill-tab.js +49 -0
  97. package/dist/esm/components/editors/cell-format/font-tab.d.ts +18 -0
  98. package/dist/esm/components/editors/cell-format/font-tab.d.ts.map +1 -0
  99. package/dist/esm/components/editors/cell-format/font-tab.js +88 -0
  100. package/dist/esm/components/editors/cell-format/list-box.d.ts +35 -0
  101. package/dist/esm/components/editors/cell-format/list-box.d.ts.map +1 -0
  102. package/dist/esm/components/editors/cell-format/list-box.js +30 -0
  103. package/dist/esm/components/editors/cell-format/number-formats.d.ts +90 -0
  104. package/dist/esm/components/editors/cell-format/number-formats.d.ts.map +1 -0
  105. package/dist/esm/components/editors/cell-format/number-formats.js +383 -0
  106. package/dist/esm/components/editors/cell-format/number-tab.d.ts +12 -0
  107. package/dist/esm/components/editors/cell-format/number-tab.d.ts.map +1 -0
  108. package/dist/esm/components/editors/cell-format/number-tab.js +165 -0
  109. package/dist/esm/components/editors/cell-format/protection-tab.d.ts +13 -0
  110. package/dist/esm/components/editors/cell-format/protection-tab.d.ts.map +1 -0
  111. package/dist/esm/components/editors/cell-format/protection-tab.js +9 -0
  112. package/dist/esm/components/editors/cell-format-editor.d.ts +31 -3
  113. package/dist/esm/components/editors/cell-format-editor.d.ts.map +1 -1
  114. package/dist/esm/components/editors/cell-format-editor.js +148 -615
  115. package/dist/esm/components/editors/conditional-format-data-bar-options.d.ts +16 -0
  116. package/dist/esm/components/editors/conditional-format-data-bar-options.d.ts.map +1 -0
  117. package/dist/esm/components/editors/conditional-format-data-bar-options.js +145 -0
  118. package/dist/esm/components/editors/conditional-format-editor.d.ts +7 -1
  119. package/dist/esm/components/editors/conditional-format-editor.d.ts.map +1 -1
  120. package/dist/esm/components/editors/conditional-format-editor.js +39 -8
  121. package/dist/esm/components/editors/conditional-format-icon-set-options.d.ts +17 -0
  122. package/dist/esm/components/editors/conditional-format-icon-set-options.d.ts.map +1 -0
  123. package/dist/esm/components/editors/conditional-format-icon-set-options.js +139 -0
  124. package/dist/esm/components/editors/conditional-format-rule-editor.d.ts +9 -0
  125. package/dist/esm/components/editors/conditional-format-rule-editor.d.ts.map +1 -1
  126. package/dist/esm/components/editors/conditional-format-rule-editor.js +60 -85
  127. package/dist/esm/components/editors/sheet-filter.d.ts +20 -9
  128. package/dist/esm/components/editors/sheet-filter.d.ts.map +1 -1
  129. package/dist/esm/components/editors/sheet-filter.js +31 -11
  130. package/dist/esm/constants.d.ts +3 -1
  131. package/dist/esm/constants.d.ts.map +1 -1
  132. package/dist/esm/constants.js +3 -0
  133. package/dist/esm/hooks/use-conditional-formatting-rules.d.ts +2 -0
  134. package/dist/esm/hooks/use-conditional-formatting-rules.d.ts.map +1 -1
  135. package/dist/esm/hooks/use-conditional-formatting-rules.js +19 -1
  136. package/dist/esm/hooks/use-on-paste.d.ts.map +1 -1
  137. package/dist/esm/hooks/use-on-paste.js +8 -1
  138. package/dist/esm/hooks/use-sparkline-groups.d.ts +1 -0
  139. package/dist/esm/hooks/use-sparkline-groups.d.ts.map +1 -1
  140. package/dist/esm/hooks/use-sparkline-groups.js +20 -1
  141. package/dist/esm/hooks/use-spreadsheet-state.d.ts +3 -0
  142. package/dist/esm/hooks/use-spreadsheet-state.d.ts.map +1 -1
  143. package/dist/esm/hooks/use-spreadsheet-state.js +11 -4
  144. package/dist/esm/index.d.ts +1 -1
  145. package/dist/esm/index.d.ts.map +1 -1
  146. package/dist/esm/index.js +1 -1
  147. package/dist/esm/interface/change-border.d.ts.map +1 -1
  148. package/dist/esm/interface/change-border.js +8 -1
  149. package/dist/esm/interface/conditional-formatting-rules.d.ts +11 -1
  150. package/dist/esm/interface/conditional-formatting-rules.d.ts.map +1 -1
  151. package/dist/esm/interface/conditional-formatting-rules.js +29 -1
  152. package/dist/esm/sheet-cell.d.ts +8 -0
  153. package/dist/esm/sheet-cell.d.ts.map +1 -1
  154. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  155. package/package.json +7 -7
@@ -0,0 +1,16 @@
1
+ import type { DataBarRule, SpreadsheetTheme } from "@rowsncolumns/spreadsheet";
2
+ import React from "react";
3
+ /**
4
+ * Excel's "New Formatting Rule ▸ Data Bar" defaults: Automatic bounds,
5
+ * gradient fill in blue with a matching solid border, red negative bars,
6
+ * an automatic black axis and full-width (0–100 %) bars.
7
+ */
8
+ export declare const DEFAULT_DATA_BAR_RULE: DataBarRule;
9
+ export type ConditionalFormatDataBarOptionsProps = {
10
+ rule: DataBarRule | null | undefined;
11
+ theme: SpreadsheetTheme;
12
+ onChange(next: DataBarRule): void;
13
+ };
14
+ /** Excel-depth data-bar options: bounds, fill, border, direction, negatives and axis, bar only. */
15
+ export declare const ConditionalFormatDataBarOptions: ({ rule, theme, onChange, }: ConditionalFormatDataBarOptionsProps) => React.JSX.Element;
16
+ //# sourceMappingURL=conditional-format-data-bar-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-format-data-bar-options.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-data-bar-options.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,WAAW,EACX,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAYnC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAanC,CAAC;AAwCF,MAAM,MAAM,oCAAoC,GAAG;IACjD,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,+BAA+B,GAAI,4BAI7C,oCAAoC,sBAuPtC,CAAC"}
@@ -0,0 +1,166 @@
1
+ import { __assign } from "tslib";
2
+ import { getStringifiedColor } from "@rowsncolumns/spreadsheet";
3
+ import { Input, Select, SelectContent, SelectItem, SelectPortal, SelectTrigger, SelectValue, Stack, } from "@rowsncolumns/ui";
4
+ import React from "react";
5
+ /**
6
+ * Excel's "New Formatting Rule ▸ Data Bar" defaults: Automatic bounds,
7
+ * gradient fill in blue with a matching solid border, red negative bars,
8
+ * an automatic black axis and full-width (0–100 %) bars.
9
+ */
10
+ export var DEFAULT_DATA_BAR_RULE = {
11
+ minpoint: { type: "AUTOMATIC" },
12
+ maxpoint: { type: "AUTOMATIC" },
13
+ color: "#638EC6",
14
+ borderColor: "#638EC6",
15
+ gradient: true,
16
+ negativeColor: "#FF0000",
17
+ negativeBorderColor: "#FF0000",
18
+ axisPosition: "automatic",
19
+ axisColor: "#000000",
20
+ direction: "context",
21
+ minLength: 0,
22
+ maxLength: 100,
23
+ };
24
+ var BOUND_TYPES = [
25
+ { value: "AUTOMATIC", min: "Automatic", max: "Automatic" },
26
+ { value: "MIN", min: "Lowest Value", max: "Highest Value" },
27
+ { value: "NUMBER", min: "Number", max: "Number" },
28
+ { value: "PERCENT", min: "Percent", max: "Percent" },
29
+ { value: "FORMULA", min: "Formula", max: "Formula" },
30
+ { value: "PERCENTILE", min: "Percentile", max: "Percentile" },
31
+ ];
32
+ var defaultBoundValue = function (type, bound) {
33
+ return type === "NUMBER" || type === "FORMULA"
34
+ ? bound === "min"
35
+ ? "0"
36
+ : "100"
37
+ : type === "PERCENT" || type === "PERCENTILE"
38
+ ? bound === "min"
39
+ ? "10"
40
+ : "90"
41
+ : undefined;
42
+ };
43
+ var colorInputValue = function (color, theme, fallback) {
44
+ var css = color ? getStringifiedColor(color, theme) : undefined;
45
+ return typeof css === "string" && /^#[0-9a-f]{6}$/i.test(css)
46
+ ? css
47
+ : fallback;
48
+ };
49
+ /** Excel-depth data-bar options: bounds, fill, border, direction, negatives and axis, bar only. */
50
+ export var ConditionalFormatDataBarOptions = function (_a) {
51
+ var _b, _c;
52
+ var rule = _a.rule, theme = _a.theme, onChange = _a.onChange;
53
+ var value = rule !== null && rule !== void 0 ? rule : DEFAULT_DATA_BAR_RULE;
54
+ var update = function (patch) {
55
+ return onChange(__assign(__assign({}, value), patch));
56
+ };
57
+ var boundEditor = function (bound) {
58
+ var _a;
59
+ var key = bound === "min" ? "minpoint" : "maxpoint";
60
+ var threshold = value[key];
61
+ var showValue = threshold.type !== "AUTOMATIC" &&
62
+ threshold.type !== "MIN" &&
63
+ threshold.type !== "MAX";
64
+ return (React.createElement(Stack, { direction: "vertical", className: "gap-1 flex-1" },
65
+ React.createElement("label", { className: "font-system text-sm" }, bound === "min" ? "Minimum" : "Maximum"),
66
+ React.createElement(Select, { value: threshold.type === "MAX" ? "MIN" : threshold.type, onValueChange: function (type) {
67
+ var _a;
68
+ var nextType = type === "MIN" && bound === "max"
69
+ ? "MAX"
70
+ : type;
71
+ update((_a = {},
72
+ _a[key] = {
73
+ type: nextType,
74
+ value: defaultBoundValue(nextType, bound),
75
+ },
76
+ _a));
77
+ } },
78
+ React.createElement(SelectTrigger, { className: "text-sm", "aria-label": bound === "min" ? "Minimum type" : "Maximum type" },
79
+ React.createElement(SelectValue, null)),
80
+ React.createElement(SelectPortal, null,
81
+ React.createElement(SelectContent, null, BOUND_TYPES.map(function (option) { return (React.createElement(SelectItem, { key: option.value, value: option.value }, bound === "min" ? option.min : option.max)); })))),
82
+ showValue ? (React.createElement(Input, { "aria-label": bound === "min" ? "Minimum value" : "Maximum value", className: "text-xs", value: String((_a = threshold.value) !== null && _a !== void 0 ? _a : ""), onChange: function (e) {
83
+ var _a;
84
+ return update((_a = {}, _a[key] = __assign(__assign({}, threshold), { value: e.target.value }), _a));
85
+ } })) : null));
86
+ };
87
+ var negativeSameFill = !value.negativeColor;
88
+ var negativeSameBorder = !value.negativeBorderColor;
89
+ var hasBorder = !!value.borderColor;
90
+ return (React.createElement(Stack, { direction: "vertical", className: "gap-2 pb-1" },
91
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2" },
92
+ boundEditor("min"),
93
+ boundEditor("max")),
94
+ React.createElement("label", { className: "font-system text-sm" }, "Bar appearance"),
95
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
96
+ React.createElement(Select, { value: value.gradient === false ? "solid" : "gradient", onValueChange: function (fill) { return update({ gradient: fill === "gradient" }); } },
97
+ React.createElement(SelectTrigger, { className: "text-sm w-36", "aria-label": "Fill" },
98
+ React.createElement(SelectValue, null)),
99
+ React.createElement(SelectPortal, null,
100
+ React.createElement(SelectContent, null,
101
+ React.createElement(SelectItem, { value: "solid" }, "Solid Fill"),
102
+ React.createElement(SelectItem, { value: "gradient" }, "Gradient Fill")))),
103
+ React.createElement(Input, { type: "color", "aria-label": "Fill color", className: "w-16 h-8", value: colorInputValue(value.color, theme, "#638ec6"), onChange: function (e) { return update({ color: e.target.value }); } })),
104
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
105
+ React.createElement(Select, { value: hasBorder ? "solid" : "none", onValueChange: function (border) {
106
+ return update(__assign({ borderColor: border === "solid"
107
+ ? colorInputValue(value.color, theme, "#638ec6")
108
+ : undefined }, (border === "none" ? { negativeBorderColor: undefined } : {})));
109
+ } },
110
+ React.createElement(SelectTrigger, { className: "text-sm w-36", "aria-label": "Border" },
111
+ React.createElement(SelectValue, null)),
112
+ React.createElement(SelectPortal, null,
113
+ React.createElement(SelectContent, null,
114
+ React.createElement(SelectItem, { value: "none" }, "No Border"),
115
+ React.createElement(SelectItem, { value: "solid" }, "Solid Border")))),
116
+ hasBorder ? (React.createElement(Input, { type: "color", "aria-label": "Border color", className: "w-16 h-8", value: colorInputValue(value.borderColor, theme, "#638ec6"), onChange: function (e) { return update({ borderColor: e.target.value }); } })) : null),
117
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
118
+ React.createElement("label", { className: "font-system text-sm w-24" }, "Bar direction"),
119
+ React.createElement(Select, { value: (_b = value.direction) !== null && _b !== void 0 ? _b : "context", onValueChange: function (direction) {
120
+ return update({ direction: direction });
121
+ } },
122
+ React.createElement(SelectTrigger, { className: "text-sm w-36", "aria-label": "Bar direction" },
123
+ React.createElement(SelectValue, null)),
124
+ React.createElement(SelectPortal, null,
125
+ React.createElement(SelectContent, null,
126
+ React.createElement(SelectItem, { value: "context" }, "Context"),
127
+ React.createElement(SelectItem, { value: "leftToRight" }, "Left-to-Right"),
128
+ React.createElement(SelectItem, { value: "rightToLeft" }, "Right-to-Left"))))),
129
+ React.createElement("label", { className: "font-system text-sm inline-flex items-center gap-2" },
130
+ React.createElement("input", { type: "checkbox", checked: value.showValue === false, onChange: function (e) {
131
+ return update({ showValue: e.target.checked ? false : undefined });
132
+ } }),
133
+ "Show Bar Only"),
134
+ React.createElement("label", { className: "font-system text-sm mt-1" }, "Negative value and axis"),
135
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
136
+ React.createElement("label", { className: "font-system text-xs inline-flex items-center gap-1" },
137
+ React.createElement("input", { type: "checkbox", checked: negativeSameFill, onChange: function (e) {
138
+ return update({
139
+ negativeColor: e.target.checked ? undefined : "#FF0000",
140
+ });
141
+ } }),
142
+ "Same fill color as positive bar"),
143
+ !negativeSameFill ? (React.createElement(Input, { type: "color", "aria-label": "Negative fill color", className: "w-16 h-8", value: colorInputValue(value.negativeColor, theme, "#ff0000"), onChange: function (e) { return update({ negativeColor: e.target.value }); } })) : null),
144
+ hasBorder ? (React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
145
+ React.createElement("label", { className: "font-system text-xs inline-flex items-center gap-1" },
146
+ React.createElement("input", { type: "checkbox", checked: negativeSameBorder, onChange: function (e) {
147
+ return update({
148
+ negativeBorderColor: e.target.checked ? undefined : "#FF0000",
149
+ });
150
+ } }),
151
+ "Same border color as positive bar"),
152
+ !negativeSameBorder ? (React.createElement(Input, { type: "color", "aria-label": "Negative border color", className: "w-16 h-8", value: colorInputValue(value.negativeBorderColor, theme, "#ff0000"), onChange: function (e) { return update({ negativeBorderColor: e.target.value }); } })) : null)) : null,
153
+ React.createElement(Stack, { direction: "horizontal", className: "gap-2 items-center" },
154
+ React.createElement("label", { className: "font-system text-sm w-24" }, "Axis"),
155
+ React.createElement(Select, { value: (_c = value.axisPosition) !== null && _c !== void 0 ? _c : "none", onValueChange: function (axis) {
156
+ return update({ axisPosition: axis });
157
+ } },
158
+ React.createElement(SelectTrigger, { className: "text-sm w-36", "aria-label": "Axis position" },
159
+ React.createElement(SelectValue, null)),
160
+ React.createElement(SelectPortal, null,
161
+ React.createElement(SelectContent, null,
162
+ React.createElement(SelectItem, { value: "automatic" }, "Automatic"),
163
+ React.createElement(SelectItem, { value: "middle" }, "Cell midpoint"),
164
+ React.createElement(SelectItem, { value: "none" }, "None")))),
165
+ value.axisPosition && value.axisPosition !== "none" ? (React.createElement(Input, { type: "color", "aria-label": "Axis color", className: "w-16 h-8", value: colorInputValue(value.axisColor, theme, "#000000"), onChange: function (e) { return update({ axisColor: e.target.value }); } })) : null)));
166
+ };
@@ -36,12 +36,18 @@ export type ConditionalFormatEditorProps = {
36
36
  * @param rule
37
37
  */
38
38
  onPreviewRule: ReturnType<typeof useSpreadsheetState>["onPreviewConditionalFormattingRule"];
39
+ /**
40
+ * Move Up / Move Down: the `priority` updates that realise the new order, applied as ONE undoable
41
+ * change (`onReorderConditionalFormattingRules`). Without it each update goes through
42
+ * `onUpdateRule`.
43
+ */
44
+ onReorderRules?: ReturnType<typeof useSpreadsheetState>["onReorderConditionalFormattingRules"];
39
45
  /**
40
46
  * Id creation strategy
41
47
  */
42
48
  idCreationStrategy?: UseSpreadsheetProps["idCreationStrategy"];
43
49
  };
44
- export declare const ConditionalFormatEditor: ({ sheets, sheetId, theme, conditionalFormats, functionDescriptions, locale, idCreationStrategy, onCreateRule, onDeleteRule, onUpdateRule, onPreviewRule, }: ConditionalFormatEditorProps) => React.JSX.Element;
50
+ export declare const ConditionalFormatEditor: ({ sheets, sheetId, theme, conditionalFormats, functionDescriptions, locale, idCreationStrategy, onCreateRule, onDeleteRule, onUpdateRule, onPreviewRule, onReorderRules, }: ConditionalFormatEditorProps) => React.JSX.Element;
45
51
  export declare const ConditionalFormatDialog: ({ children, }: {
46
52
  children: React.ReactNode;
47
53
  }) => React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"conditional-format-editor.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-editor.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,KAAK,EACL,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAkBnC,OAAO,KAAyC,MAAM,OAAO,CAAC;AAG9D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mCAAmC,CAAC;AAW3C,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAC/D,kBAAkB,EAAE,qBAAqB,EAAE,CAAC;IAC5C;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAC/C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;;OAIG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;OAGG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,UAAU,CACvB,OAAO,mBAAmB,CAC3B,CAAC,oCAAoC,CAAC,CAAC;IACxC;;OAEG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;CAChE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,4JAYrC,4BAA4B,sBAqR9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,eAErC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,sBAyBA,CAAC"}
1
+ {"version":3,"file":"conditional-format-editor.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-editor.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,KAAK,EACL,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAoBnC,OAAO,KAAyC,MAAM,OAAO,CAAC;AAG9D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mCAAmC,CAAC;AAW3C,MAAM,MAAM,4BAA4B,GAAG;IACzC,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAC/D,kBAAkB,EAAE,qBAAqB,EAAE,CAAC;IAC5C;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAC/C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;;OAIG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;OAGG;IACH,YAAY,EAAE,UAAU,CACtB,OAAO,mBAAmB,CAC3B,CAAC,mCAAmC,CAAC,CAAC;IACvC;;;OAGG;IACH,aAAa,EAAE,UAAU,CACvB,OAAO,mBAAmB,CAC3B,CAAC,oCAAoC,CAAC,CAAC;IACxC;;;;OAIG;IACH,cAAc,CAAC,EAAE,UAAU,CACzB,OAAO,mBAAmB,CAC3B,CAAC,qCAAqC,CAAC,CAAC;IACzC;;OAEG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;CAChE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,4KAarC,4BAA4B,sBA+U9B,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,eAErC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,sBAyBA,CAAC"}
@@ -1,8 +1,8 @@
1
- import { __assign, __read, __spreadArray } from "tslib";
1
+ import { __assign, __read, __rest, __spreadArray, __values } from "tslib";
2
2
  import { selectionFromActiveCell } from "@rowsncolumns/grid";
3
- import { CopyIcon, Pencil2Icon, TrashIcon } from "@rowsncolumns/icons";
3
+ import { ArrowDownIcon, ArrowUpIcon, CopyIcon, Pencil2Icon, TrashIcon, } from "@rowsncolumns/icons";
4
4
  import { BoxIcon, CheckIcon, Cross2Icon, PlusIcon } from "@rowsncolumns/icons";
5
- import { getGradientColors, useFocusSheet, useFormulaRangeHelpers, useSpreadsheetApi, } from "@rowsncolumns/spreadsheet";
5
+ import { getGradientColors, planConditionalFormatMove, sortConditionalFormatRules, useFocusSheet, useFormulaRangeHelpers, useSpreadsheetApi, } from "@rowsncolumns/spreadsheet";
6
6
  import { Button, Dialog, DialogBody, DialogCloseButton, DialogContent, DialogTitle, IconButton, Separator, } from "@rowsncolumns/ui";
7
7
  import { uuid } from "@rowsncolumns/utils";
8
8
  import React, { useCallback, useMemo, useState } from "react";
@@ -10,7 +10,7 @@ import { useConditionalFormatDialogState } from "../../atoms/dialog-state.atom";
10
10
  import { ConditionalFormatRuleEditor, createRulePreviewStyle, } from "./conditional-format-rule-editor";
11
11
  import { SheetFilterEmptyState, SheetFilterSelect, useSheetFilter, } from "./sheet-filter";
12
12
  export var ConditionalFormatEditor = function (_a) {
13
- var sheets = _a.sheets, sheetId = _a.sheetId, theme = _a.theme, conditionalFormats = _a.conditionalFormats, functionDescriptions = _a.functionDescriptions, locale = _a.locale, idCreationStrategy = _a.idCreationStrategy, onCreateRule = _a.onCreateRule, onDeleteRule = _a.onDeleteRule, onUpdateRule = _a.onUpdateRule, onPreviewRule = _a.onPreviewRule;
13
+ var sheets = _a.sheets, sheetId = _a.sheetId, theme = _a.theme, conditionalFormats = _a.conditionalFormats, functionDescriptions = _a.functionDescriptions, locale = _a.locale, idCreationStrategy = _a.idCreationStrategy, onCreateRule = _a.onCreateRule, onDeleteRule = _a.onDeleteRule, onUpdateRule = _a.onUpdateRule, onPreviewRule = _a.onPreviewRule, onReorderRules = _a.onReorderRules;
14
14
  var _b = __read(useState(), 2), editingId = _b[0], setEditingId = _b[1];
15
15
  // Deferred create: "Add another rule" holds the new rule as a local draft and only
16
16
  // persists it on Save — Excel/Google Sheets create the rule on OK/Done, and an
@@ -22,7 +22,43 @@ export var ConditionalFormatEditor = function (_a) {
22
22
  sheetId: sheetId,
23
23
  }).rangeToFormula;
24
24
  var workbookSheetIds = useMemo(function () { return sheets === null || sheets === void 0 ? void 0 : sheets.map(function (sheet) { return sheet.sheetId; }); }, [sheets]);
25
- var _d = useSheetFilter(sheetId, conditionalFormats, workbookSheetIds), sheetFilter = _d.sheetFilter, setSheetFilter = _d.setSheetFilter, filterableSheetIds = _d.filterableSheetIds, visibleRules = _d.visibleRules, showFilter = _d.showFilter;
25
+ // Excel lists rules in precedence order: the first rule wins a conflicting format.
26
+ var rulesInPrecedenceOrder = useMemo(function () { return sortConditionalFormatRules(conditionalFormats); }, [conditionalFormats]);
27
+ var _d = useSheetFilter(sheetId, rulesInPrecedenceOrder, workbookSheetIds, function () {
28
+ var activeSheet = api === null || api === void 0 ? void 0 : api.getActiveSheet();
29
+ var selections = activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.getSelections();
30
+ var activeCell = activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.getActiveCell();
31
+ if (!(selections === null || selections === void 0 ? void 0 : selections.length) && !activeCell)
32
+ return [];
33
+ var ranges = ((selections === null || selections === void 0 ? void 0 : selections.length)
34
+ ? selections
35
+ : selectionFromActiveCell(activeCell)).map(function (selection) { return selection.range; });
36
+ return ranges.map(function (range) { return (__assign(__assign({}, range), { sheetId: sheetId })); });
37
+ }), sheetFilter = _d.sheetFilter, setSheetFilter = _d.setSheetFilter, filterableSheetIds = _d.filterableSheetIds, visibleRules = _d.visibleRules, showFilter = _d.showFilter;
38
+ // Move Up / Move Down among the rules the list shows ("Show formatting rules for" may hide some).
39
+ var moveRule = function (rule, direction) {
40
+ var e_1, _a;
41
+ var updates = planConditionalFormatMove(conditionalFormats, rule.id, direction, visibleRules);
42
+ if (!updates.length)
43
+ return;
44
+ if (onReorderRules) {
45
+ onReorderRules(updates);
46
+ return;
47
+ }
48
+ try {
49
+ for (var updates_1 = __values(updates), updates_1_1 = updates_1.next(); !updates_1_1.done; updates_1_1 = updates_1.next()) {
50
+ var _b = updates_1_1.value, target = _b.rule, priority = _b.priority;
51
+ onUpdateRule === null || onUpdateRule === void 0 ? void 0 : onUpdateRule(__assign(__assign({}, target), { priority: priority }), target);
52
+ }
53
+ }
54
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
55
+ finally {
56
+ try {
57
+ if (updates_1_1 && !updates_1_1.done && (_a = updates_1.return)) _a.call(updates_1);
58
+ }
59
+ finally { if (e_1) throw e_1.error; }
60
+ }
61
+ };
26
62
  var onNewRule = function () {
27
63
  var _a, _b, _c;
28
64
  var activeCell = (_a = api === null || api === void 0 ? void 0 : api.getActiveSheet()) === null || _a === void 0 ? void 0 : _a.getActiveCell();
@@ -60,8 +96,10 @@ export var ConditionalFormatEditor = function (_a) {
60
96
  var onDuplicate = function (rule) {
61
97
  var _a;
62
98
  var id = (_a = idCreationStrategy === null || idCreationStrategy === void 0 ? void 0 : idCreationStrategy("conditional-format")) !== null && _a !== void 0 ? _a : uuid();
63
- // Create a new rule
64
- onCreateRule === null || onCreateRule === void 0 ? void 0 : onCreateRule(__assign(__assign({}, rule), { id: id }));
99
+ // A copy is a new rule: drop the source's priority so it lands at the top of the list, as every
100
+ // new rule does in Excel, instead of tying with the source.
101
+ var _priority = rule.priority, copy = __rest(rule, ["priority"]);
102
+ onCreateRule === null || onCreateRule === void 0 ? void 0 : onCreateRule(__assign(__assign({}, copy), { id: id }));
65
103
  };
66
104
  var toggleEnable = function (id, enabled) {
67
105
  var rule = conditionalFormats.find(function (rule) { return rule.id === id; });
@@ -88,9 +126,9 @@ export var ConditionalFormatEditor = function (_a) {
88
126
  setDraftRule(undefined);
89
127
  setEditingId(undefined);
90
128
  }, onSubmit: onSave, onChange: onPreviewRule, idCreationStrategy: idCreationStrategy })) : (React.createElement("div", { className: "flex flex-col overflow-auto max-h-[600px]" },
91
- showFilter ? (React.createElement(SheetFilterSelect, { value: sheetFilter, sheetIds: filterableSheetIds, onValueChange: setSheetFilter })) : null,
129
+ showFilter ? (React.createElement(SheetFilterSelect, { offerSelection: true, value: sheetFilter, sheetIds: filterableSheetIds, onValueChange: setSheetFilter })) : null,
92
130
  visibleRules.length === 0 ? (React.createElement(SheetFilterEmptyState, { sheetFilter: sheetFilter, label: "conditional format rules" })) : null,
93
- visibleRules.map(function (rule) {
131
+ visibleRules.map(function (rule, ruleIndex) {
94
132
  var _a, _b, _c, _d, _e, _f, _g;
95
133
  var title = rule.gradientRule
96
134
  ? "Color scale"
@@ -139,6 +177,10 @@ export var ConditionalFormatEditor = function (_a) {
139
177
  } }),
140
178
  "Stop if true")),
141
179
  React.createElement("div", null,
180
+ React.createElement(IconButton, { tooltip: "Move up", "aria-label": "Move up", disabled: ruleIndex === 0, onClick: function () { return moveRule(rule, -1); } },
181
+ React.createElement(ArrowUpIcon, null)),
182
+ React.createElement(IconButton, { tooltip: "Move down", "aria-label": "Move down", disabled: ruleIndex === visibleRules.length - 1, onClick: function () { return moveRule(rule, 1); } },
183
+ React.createElement(ArrowDownIcon, null)),
142
184
  React.createElement(IconButton, { tooltip: "".concat(enabled ? "Disable" : "Enable", " this rule"), onClick: function () { return toggleEnable(rule.id, !enabled); }, className: "relative" },
143
185
  React.createElement(BoxIcon, null),
144
186
  enabled ? (React.createElement(CheckIcon, { className: "left-[4px] top-[5px] absolute" })) : null),
@@ -0,0 +1,17 @@
1
+ import type { CfThreshold, IconSetFamily, IconSetRule } from "@rowsncolumns/spreadsheet";
2
+ import React from "react";
3
+ /** Excel's 20 icon styles, in the order of its Icon Style list. */
4
+ export declare const ICON_SET_OPTIONS: Array<[IconSetFamily, string]>;
5
+ /** Excel's default thresholds for an n-icon set: equal percent slices. */
6
+ export declare const defaultIconThresholds: (count: number) => CfThreshold[];
7
+ export type ConditionalFormatIconSetOptionsProps = {
8
+ rule: IconSetRule | null | undefined;
9
+ onChange(next: IconSetRule): void;
10
+ };
11
+ /**
12
+ * Excel-depth icon-set options: icon style, reverse order, icon only, and
13
+ * one row per icon with its own icon (custom mixes), operator (>= / >),
14
+ * value and type.
15
+ */
16
+ export declare const ConditionalFormatIconSetOptions: ({ rule, onChange, }: ConditionalFormatIconSetOptionsProps) => React.JSX.Element;
17
+ //# sourceMappingURL=conditional-format-icon-set-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-format-icon-set-options.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-icon-set-options.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAYnC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAqB3D,CAAC;AAIF,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,KAAG,WAAW,EAI5D,CAAC;AAKN,MAAM,MAAM,oCAAoC,GAAG;IACjD,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,GAAI,qBAG7C,oCAAoC,sBA6MtC,CAAC"}
@@ -0,0 +1,163 @@
1
+ import { __assign, __read } from "tslib";
2
+ import { CF_ICON_SETS, CfIconPreview } from "@rowsncolumns/spreadsheet";
3
+ import { Input, Select, SelectContent, SelectItem, SelectPortal, SelectTrigger, SelectValue, Stack, } from "@rowsncolumns/ui";
4
+ import React from "react";
5
+ /** Excel's 20 icon styles, in the order of its Icon Style list. */
6
+ export var ICON_SET_OPTIONS = [
7
+ ["3Arrows", "3 Arrows (Colored)"],
8
+ ["3ArrowsGray", "3 Arrows (Gray)"],
9
+ ["3Triangles", "3 Triangles"],
10
+ ["4Arrows", "4 Arrows (Colored)"],
11
+ ["4ArrowsGray", "4 Arrows (Gray)"],
12
+ ["5Arrows", "5 Arrows (Colored)"],
13
+ ["5ArrowsGray", "5 Arrows (Gray)"],
14
+ ["3TrafficLights1", "3 Traffic Lights (Unrimmed)"],
15
+ ["3TrafficLights2", "3 Traffic Lights (Rimmed)"],
16
+ ["3Signs", "3 Signs"],
17
+ ["4TrafficLights", "4 Traffic Lights"],
18
+ ["4RedToBlack", "Red To Black"],
19
+ ["3Symbols", "3 Symbols (Circled)"],
20
+ ["3Symbols2", "3 Symbols (Uncircled)"],
21
+ ["3Flags", "3 Flags"],
22
+ ["3Stars", "3 Stars"],
23
+ ["4Rating", "4 Ratings"],
24
+ ["5Quarters", "5 Quarters"],
25
+ ["5Rating", "5 Ratings"],
26
+ ["5Boxes", "5 Boxes"],
27
+ ];
28
+ var NO_ICON = "NoIcons:0";
29
+ /** Excel's default thresholds for an n-icon set: equal percent slices. */
30
+ export var defaultIconThresholds = function (count) {
31
+ return Array.from({ length: count - 1 }, function (_, i) { return ({
32
+ type: "PERCENT",
33
+ value: Math.round(((i + 1) * 100) / count),
34
+ }); });
35
+ };
36
+ var iconCount = function (iconSet) { var _a, _b; return (_b = (_a = CF_ICON_SETS[iconSet]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 3; };
37
+ /**
38
+ * Excel-depth icon-set options: icon style, reverse order, icon only, and
39
+ * one row per icon with its own icon (custom mixes), operator (>= / >),
40
+ * value and type.
41
+ */
42
+ export var ConditionalFormatIconSetOptions = function (_a) {
43
+ var rule = _a.rule, onChange = _a.onChange;
44
+ var value = rule !== null && rule !== void 0 ? rule : {
45
+ iconSet: "3TrafficLights1",
46
+ thresholds: defaultIconThresholds(3),
47
+ };
48
+ var count = iconCount(value.iconSet);
49
+ var update = function (patch) {
50
+ return onChange(__assign(__assign({}, value), patch));
51
+ };
52
+ // The icon each bucket shows, lowest bucket first — the custom list when
53
+ // set, else the style's icons (reversed when asked).
54
+ var bucketIcons = Array.from({ length: count }, function (_, bucket) {
55
+ var _a;
56
+ var custom = (_a = value.icons) === null || _a === void 0 ? void 0 : _a[bucket];
57
+ if (custom)
58
+ return custom;
59
+ var iconId = value.reverse ? count - 1 - bucket : bucket;
60
+ return { iconSet: value.iconSet, iconId: iconId };
61
+ });
62
+ var setBucketIcon = function (bucket, key) {
63
+ var _a = __read(key.split(":"), 2), iconSet = _a[0], id = _a[1];
64
+ var icons = bucketIcons.map(function (icon, i) {
65
+ return i === bucket
66
+ ? { iconSet: iconSet, iconId: Number(id) }
67
+ : icon;
68
+ });
69
+ update({ icons: icons, reverse: undefined });
70
+ };
71
+ var setThreshold = function (index, patch) {
72
+ var thresholds = value.thresholds.slice();
73
+ thresholds[index] = __assign(__assign({}, thresholds[index]), patch);
74
+ update({ thresholds: thresholds });
75
+ };
76
+ // Rows top-down from the highest bucket, like Excel's dialog.
77
+ var rows = Array.from({ length: count }, function (_, i) { return count - 1 - i; });
78
+ return (React.createElement(Stack, { direction: "vertical", className: "gap-2 pb-1" },
79
+ React.createElement("label", { className: "font-system text-sm" }, "Icon style"),
80
+ React.createElement(Select, { value: value.iconSet, onValueChange: function (next) {
81
+ var family = next;
82
+ update({
83
+ iconSet: family,
84
+ icons: undefined,
85
+ thresholds: iconCount(family) === count
86
+ ? value.thresholds
87
+ : defaultIconThresholds(iconCount(family)),
88
+ });
89
+ } },
90
+ React.createElement(SelectTrigger, { className: "text-sm w-72", "aria-label": "Icon style" },
91
+ React.createElement(SelectValue, null)),
92
+ React.createElement(SelectPortal, null,
93
+ React.createElement(SelectContent, null, ICON_SET_OPTIONS.map(function (_a) {
94
+ var _b = __read(_a, 2), family = _b[0], label = _b[1];
95
+ return (React.createElement(SelectItem, { key: family, value: family },
96
+ React.createElement("span", { className: "inline-flex items-center gap-2" },
97
+ React.createElement("span", { className: "inline-flex gap-0.5" }, CF_ICON_SETS[family].map(function (_, iconId) { return (React.createElement(CfIconPreview, { key: iconId, iconSet: family, iconId: iconId })); })),
98
+ React.createElement("span", null, label))));
99
+ })))),
100
+ React.createElement(Stack, { direction: "horizontal", className: "gap-4" },
101
+ React.createElement("label", { className: "font-system text-sm inline-flex items-center gap-2" },
102
+ React.createElement("input", { type: "checkbox", checked: !!value.reverse, onChange: function (e) {
103
+ // Reversing a custom mix reverses the list itself (Excel).
104
+ if (value.icons) {
105
+ update({ icons: value.icons.slice().reverse() });
106
+ }
107
+ else {
108
+ update({ reverse: e.target.checked || undefined });
109
+ }
110
+ } }),
111
+ "Reverse Icon Order"),
112
+ React.createElement("label", { className: "font-system text-sm inline-flex items-center gap-2" },
113
+ React.createElement("input", { type: "checkbox", checked: value.showValue === false, onChange: function (e) {
114
+ return update({ showValue: e.target.checked ? false : undefined });
115
+ } }),
116
+ "Show Icon Only")),
117
+ rows.map(function (bucket) {
118
+ var _a;
119
+ var icon = bucketIcons[bucket];
120
+ var threshold = bucket > 0 ? value.thresholds[bucket - 1] : undefined;
121
+ return (React.createElement(Stack, { key: bucket, direction: "horizontal", className: "gap-1 items-center" },
122
+ React.createElement(Select, { value: "".concat(icon.iconSet, ":").concat(icon.iconId), onValueChange: function (key) { return setBucketIcon(bucket, key); } },
123
+ React.createElement(SelectTrigger, { className: "text-sm w-16", "aria-label": "Icon ".concat(count - bucket) },
124
+ React.createElement(SelectValue, null)),
125
+ React.createElement(SelectPortal, null,
126
+ React.createElement(SelectContent, null,
127
+ React.createElement(SelectItem, { value: NO_ICON }, "No Cell Icon"),
128
+ ICON_SET_OPTIONS.flatMap(function (_a) {
129
+ var _b = __read(_a, 1), family = _b[0];
130
+ return CF_ICON_SETS[family].map(function (_, iconId) { return (React.createElement(SelectItem, { key: "".concat(family, ":").concat(iconId), value: "".concat(family, ":").concat(iconId) },
131
+ React.createElement(CfIconPreview, { iconSet: family, iconId: iconId }))); });
132
+ })))),
133
+ threshold ? (React.createElement(React.Fragment, null,
134
+ React.createElement("span", { className: "font-system text-xs" }, "when value is"),
135
+ React.createElement(Select, { value: threshold.gte === false ? ">" : ">=", onValueChange: function (op) {
136
+ return setThreshold(bucket - 1, {
137
+ gte: op === ">" ? false : undefined,
138
+ });
139
+ } },
140
+ React.createElement(SelectTrigger, { className: "text-sm w-14", "aria-label": "Operator ".concat(count - bucket) },
141
+ React.createElement(SelectValue, null)),
142
+ React.createElement(SelectPortal, null,
143
+ React.createElement(SelectContent, null,
144
+ React.createElement(SelectItem, { value: ">=" }, ">="),
145
+ React.createElement(SelectItem, { value: ">" }, ">")))),
146
+ React.createElement(Input, { className: "text-xs w-20", "aria-label": "Value ".concat(count - bucket), value: String((_a = threshold.value) !== null && _a !== void 0 ? _a : ""), onChange: function (e) {
147
+ return setThreshold(bucket - 1, { value: e.target.value });
148
+ } }),
149
+ React.createElement(Select, { value: threshold.type, onValueChange: function (type) {
150
+ return setThreshold(bucket - 1, {
151
+ type: type,
152
+ });
153
+ } },
154
+ React.createElement(SelectTrigger, { className: "text-sm w-28", "aria-label": "Type ".concat(count - bucket) },
155
+ React.createElement(SelectValue, null)),
156
+ React.createElement(SelectPortal, null,
157
+ React.createElement(SelectContent, null,
158
+ React.createElement(SelectItem, { value: "NUMBER" }, "Number"),
159
+ React.createElement(SelectItem, { value: "PERCENT" }, "Percent"),
160
+ React.createElement(SelectItem, { value: "FORMULA" }, "Formula"),
161
+ React.createElement(SelectItem, { value: "PERCENTILE" }, "Percentile")))))) : (React.createElement("span", { className: "font-system text-xs" }, "otherwise"))));
162
+ })));
163
+ };
@@ -23,5 +23,14 @@ export type ConditionalFormatRuleEditorProps = {
23
23
  };
24
24
  export declare const createBorderCSSFromBorder: (borders: Borders | undefined | null, theme: SpreadsheetTheme) => React.CSSProperties;
25
25
  export declare const createRulePreviewStyle: (format: CellFormat | undefined, theme: SpreadsheetTheme) => React.CSSProperties;
26
+ /** Excel's "Format only values that are above or below average" choices. */
27
+ export declare const AVERAGE_OPTIONS: Array<{
28
+ key: string;
29
+ label: string;
30
+ type: "NUMBER_ABOVE_AVERAGE" | "NUMBER_BELOW_AVERAGE";
31
+ equalAverage?: boolean;
32
+ stdDev?: number;
33
+ }>;
34
+ export declare const averageOptionKey: (rule: ConditionalFormatRule["booleanRule"]) => string;
26
35
  export declare const ConditionalFormatRuleEditor: ({ sheetId, conditionalFormatRule, theme, functionDescriptions, locale, idCreationStrategy, onSubmit, onCancel, onChange, }: ConditionalFormatRuleEditorProps) => React.JSX.Element;
27
36
  //# sourceMappingURL=conditional-format-rule-editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conditional-format-rule-editor.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-rule-editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,4BAA4B,CAAC;AAG5E,OAAO,KAAK,EAEV,OAAO,EACP,eAAe,EACf,qBAAqB,EAGrB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAqCnC,OAAO,KAA+C,MAAM,OAAO,CAAC;AAMpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,MAAM,MAAM,gCAAgC,GAAG;IAC7C,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC/D,QAAQ,CAAC,CACP,qBAAqB,EAAE,qBAAqB,EAC5C,YAAY,EAAE,qBAAqB,GAClC,IAAI,CAAC;IACR,QAAQ,CAAC,CAAC,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC9D,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,OAAO,GAAG,SAAS,GAAG,IAAI,EACnC,OAAO,gBAAgB,KACtB,KAAK,CAAC,aA0BR,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,QAAQ,UAAU,GAAG,SAAS,EAC9B,OAAO,gBAAgB,KACtB,KAAK,CAAC,aAYR,CAAC;AA6CF,eAAO,MAAM,2BAA2B,GAAI,4HAUzC,gCAAgC,sBAsgClC,CAAC"}
1
+ {"version":3,"file":"conditional-format-rule-editor.d.ts","sourceRoot":"","sources":["../../../../components/editors/conditional-format-rule-editor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,4BAA4B,CAAC;AAG5E,OAAO,KAAK,EAEV,OAAO,EACP,eAAe,EACf,qBAAqB,EAGrB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAkCnC,OAAO,KAA+C,MAAM,OAAO,CAAC;AAMpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAU7E,MAAM,MAAM,gCAAgC,GAAG;IAC7C,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC/D,QAAQ,CAAC,CACP,qBAAqB,EAAE,qBAAqB,EAC5C,YAAY,EAAE,qBAAqB,GAClC,IAAI,CAAC;IACR,QAAQ,CAAC,CAAC,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC9D,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,OAAO,GAAG,SAAS,GAAG,IAAI,EACnC,OAAO,gBAAgB,KACtB,KAAK,CAAC,aA0BR,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,QAAQ,UAAU,GAAG,SAAS,EAC9B,OAAO,gBAAgB,KACtB,KAAK,CAAC,aAYR,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,sBAAsB,GAAG,sBAAsB,CAAC;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CA2BA,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,MAAM,qBAAqB,CAAC,aAAa,CAAC,KACzC,MAOF,CAAC;AA6CF,eAAO,MAAM,2BAA2B,GAAI,4HAUzC,gCAAgC,sBAk7BlC,CAAC"}