@rowsncolumns/utils 9.2.35

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 (154) hide show
  1. package/LICENSE.md +100 -0
  2. package/dist/cjs/array.d.ts +3 -0
  3. package/dist/cjs/array.d.ts.map +1 -0
  4. package/dist/cjs/array.js +19 -0
  5. package/dist/cjs/cell-data-helpers.d.ts +19 -0
  6. package/dist/cjs/cell-data-helpers.d.ts.map +1 -0
  7. package/dist/cjs/cell-data-helpers.js +64 -0
  8. package/dist/cjs/color.d.ts +20 -0
  9. package/dist/cjs/color.d.ts.map +1 -0
  10. package/dist/cjs/color.js +168 -0
  11. package/dist/cjs/colors.d.ts +2 -0
  12. package/dist/cjs/colors.d.ts.map +1 -0
  13. package/dist/cjs/colors.js +78 -0
  14. package/dist/cjs/conditional-format.d.ts +49 -0
  15. package/dist/cjs/conditional-format.d.ts.map +1 -0
  16. package/dist/cjs/conditional-format.js +227 -0
  17. package/dist/cjs/content-hash.d.ts +16 -0
  18. package/dist/cjs/content-hash.d.ts.map +1 -0
  19. package/dist/cjs/content-hash.js +72 -0
  20. package/dist/cjs/data-validation.d.ts +54 -0
  21. package/dist/cjs/data-validation.d.ts.map +1 -0
  22. package/dist/cjs/data-validation.js +249 -0
  23. package/dist/cjs/date.d.ts +15 -0
  24. package/dist/cjs/date.d.ts.map +1 -0
  25. package/dist/cjs/date.js +56 -0
  26. package/dist/cjs/dom.d.ts +10 -0
  27. package/dist/cjs/dom.d.ts.map +1 -0
  28. package/dist/cjs/dom.js +97 -0
  29. package/dist/cjs/formatter.d.ts +22 -0
  30. package/dist/cjs/formatter.d.ts.map +1 -0
  31. package/dist/cjs/formatter.js +264 -0
  32. package/dist/cjs/formula-refs.d.ts +7 -0
  33. package/dist/cjs/formula-refs.d.ts.map +1 -0
  34. package/dist/cjs/formula-refs.js +54 -0
  35. package/dist/cjs/formula.d.ts +80 -0
  36. package/dist/cjs/formula.d.ts.map +1 -0
  37. package/dist/cjs/formula.js +401 -0
  38. package/dist/cjs/index.d.ts +24 -0
  39. package/dist/cjs/index.d.ts.map +1 -0
  40. package/dist/cjs/index.js +26 -0
  41. package/dist/cjs/locale.d.ts +34 -0
  42. package/dist/cjs/locale.d.ts.map +1 -0
  43. package/dist/cjs/locale.js +260 -0
  44. package/dist/cjs/log.d.ts +4 -0
  45. package/dist/cjs/log.d.ts.map +1 -0
  46. package/dist/cjs/log.js +28 -0
  47. package/dist/cjs/memoize.d.ts +18 -0
  48. package/dist/cjs/memoize.d.ts.map +1 -0
  49. package/dist/cjs/memoize.js +128 -0
  50. package/dist/cjs/numbers.d.ts +19 -0
  51. package/dist/cjs/numbers.d.ts.map +1 -0
  52. package/dist/cjs/numbers.js +47 -0
  53. package/dist/cjs/selection.d.ts +88 -0
  54. package/dist/cjs/selection.d.ts.map +1 -0
  55. package/dist/cjs/selection.js +368 -0
  56. package/dist/cjs/shared-string-canonical.d.ts +18 -0
  57. package/dist/cjs/shared-string-canonical.d.ts.map +1 -0
  58. package/dist/cjs/shared-string-canonical.js +74 -0
  59. package/dist/cjs/sort.d.ts +15 -0
  60. package/dist/cjs/sort.d.ts.map +1 -0
  61. package/dist/cjs/sort.js +44 -0
  62. package/dist/cjs/string.d.ts +74 -0
  63. package/dist/cjs/string.d.ts.map +1 -0
  64. package/dist/cjs/string.js +237 -0
  65. package/dist/cjs/table-styles.d.ts +56 -0
  66. package/dist/cjs/table-styles.d.ts.map +1 -0
  67. package/dist/cjs/table-styles.js +362 -0
  68. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  69. package/dist/cjs/typeguards.d.ts +4 -0
  70. package/dist/cjs/typeguards.d.ts.map +1 -0
  71. package/dist/cjs/typeguards.js +15 -0
  72. package/dist/cjs/uuid.d.ts +8 -0
  73. package/dist/cjs/uuid.d.ts.map +1 -0
  74. package/dist/cjs/uuid.js +30 -0
  75. package/dist/cjs/vitest.config.d.ts +3 -0
  76. package/dist/cjs/vitest.config.d.ts.map +1 -0
  77. package/dist/cjs/vitest.config.js +9 -0
  78. package/dist/esm/array.d.ts +3 -0
  79. package/dist/esm/array.d.ts.map +1 -0
  80. package/dist/esm/array.js +14 -0
  81. package/dist/esm/cell-data-helpers.d.ts +19 -0
  82. package/dist/esm/cell-data-helpers.d.ts.map +1 -0
  83. package/dist/esm/cell-data-helpers.js +39 -0
  84. package/dist/esm/color.d.ts +20 -0
  85. package/dist/esm/color.d.ts.map +1 -0
  86. package/dist/esm/color.js +152 -0
  87. package/dist/esm/colors.d.ts +2 -0
  88. package/dist/esm/colors.d.ts.map +1 -0
  89. package/dist/esm/colors.js +75 -0
  90. package/dist/esm/conditional-format.d.ts +49 -0
  91. package/dist/esm/conditional-format.d.ts.map +1 -0
  92. package/dist/esm/conditional-format.js +219 -0
  93. package/dist/esm/content-hash.d.ts +16 -0
  94. package/dist/esm/content-hash.d.ts.map +1 -0
  95. package/dist/esm/content-hash.js +68 -0
  96. package/dist/esm/data-validation.d.ts +54 -0
  97. package/dist/esm/data-validation.d.ts.map +1 -0
  98. package/dist/esm/data-validation.js +237 -0
  99. package/dist/esm/date.d.ts +15 -0
  100. package/dist/esm/date.d.ts.map +1 -0
  101. package/dist/esm/date.js +46 -0
  102. package/dist/esm/dom.d.ts +10 -0
  103. package/dist/esm/dom.d.ts.map +1 -0
  104. package/dist/esm/dom.js +90 -0
  105. package/dist/esm/formatter.d.ts +22 -0
  106. package/dist/esm/formatter.d.ts.map +1 -0
  107. package/dist/esm/formatter.js +253 -0
  108. package/dist/esm/formula-refs.d.ts +7 -0
  109. package/dist/esm/formula-refs.d.ts.map +1 -0
  110. package/dist/esm/formula-refs.js +49 -0
  111. package/dist/esm/formula.d.ts +80 -0
  112. package/dist/esm/formula.d.ts.map +1 -0
  113. package/dist/esm/formula.js +298 -0
  114. package/dist/esm/index.d.ts +24 -0
  115. package/dist/esm/index.d.ts.map +1 -0
  116. package/dist/esm/index.js +23 -0
  117. package/dist/esm/locale.d.ts +34 -0
  118. package/dist/esm/locale.d.ts.map +1 -0
  119. package/dist/esm/locale.js +223 -0
  120. package/dist/esm/log.d.ts +4 -0
  121. package/dist/esm/log.d.ts.map +1 -0
  122. package/dist/esm/log.js +3 -0
  123. package/dist/esm/memoize.d.ts +18 -0
  124. package/dist/esm/memoize.d.ts.map +1 -0
  125. package/dist/esm/memoize.js +95 -0
  126. package/dist/esm/numbers.d.ts +19 -0
  127. package/dist/esm/numbers.d.ts.map +1 -0
  128. package/dist/esm/numbers.js +40 -0
  129. package/dist/esm/selection.d.ts +88 -0
  130. package/dist/esm/selection.d.ts.map +1 -0
  131. package/dist/esm/selection.js +311 -0
  132. package/dist/esm/shared-string-canonical.d.ts +18 -0
  133. package/dist/esm/shared-string-canonical.d.ts.map +1 -0
  134. package/dist/esm/shared-string-canonical.js +68 -0
  135. package/dist/esm/sort.d.ts +15 -0
  136. package/dist/esm/sort.d.ts.map +1 -0
  137. package/dist/esm/sort.js +39 -0
  138. package/dist/esm/string.d.ts +74 -0
  139. package/dist/esm/string.d.ts.map +1 -0
  140. package/dist/esm/string.js +213 -0
  141. package/dist/esm/table-styles.d.ts +56 -0
  142. package/dist/esm/table-styles.d.ts.map +1 -0
  143. package/dist/esm/table-styles.js +367 -0
  144. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  145. package/dist/esm/typeguards.d.ts +4 -0
  146. package/dist/esm/typeguards.d.ts.map +1 -0
  147. package/dist/esm/typeguards.js +7 -0
  148. package/dist/esm/uuid.d.ts +8 -0
  149. package/dist/esm/uuid.d.ts.map +1 -0
  150. package/dist/esm/uuid.js +25 -0
  151. package/dist/esm/vitest.config.d.ts +3 -0
  152. package/dist/esm/vitest.config.d.ts.map +1 -0
  153. package/dist/esm/vitest.config.js +7 -0
  154. package/package.json +49 -0
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toDate = exports.toSerial = exports.toSerialWithMode = void 0;
4
+ var DAY_TO_MS = 24 * 60 * 60 * 1000;
5
+ var EXCEL_LEAP_BUG_SERIAL = 60;
6
+ /**
7
+ * Convert date to serial with explicit time zone behavior.
8
+ * - local: interpret date components in local time (UI entry behavior).
9
+ * - excel-utc: treat Date as UTC (formula engine behavior).
10
+ */
11
+ var toSerialWithMode = function (date, use1904, mode) {
12
+ if (use1904 === void 0) { use1904 = false; }
13
+ if (mode === void 0) { mode = "local"; }
14
+ var utcMillis = mode === "excel-utc"
15
+ ? date.getTime()
16
+ : Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
17
+ if (use1904) {
18
+ var baseUtc_1 = Date.UTC(1904, 0, 1);
19
+ return (utcMillis - baseUtc_1) / DAY_TO_MS;
20
+ }
21
+ var baseUtc = Date.UTC(1899, 11, 31);
22
+ var dayCount = (utcMillis - baseUtc) / DAY_TO_MS;
23
+ if (utcMillis >= Date.UTC(1900, 2, 1)) {
24
+ dayCount += 1;
25
+ }
26
+ return dayCount;
27
+ };
28
+ exports.toSerialWithMode = toSerialWithMode;
29
+ var toSerial = function (date, use1904) {
30
+ if (use1904 === void 0) { use1904 = false; }
31
+ return (0, exports.toSerialWithMode)(date, use1904, "local");
32
+ };
33
+ exports.toSerial = toSerial;
34
+ /**
35
+ * Convert serial to date
36
+ * @param serial
37
+ * @returns
38
+ */
39
+ var toDate = function (serial, use1904) {
40
+ if (use1904 === void 0) { use1904 = false; }
41
+ if (use1904) {
42
+ var baseUtc_2 = Date.UTC(1904, 0, 1);
43
+ var utcMillis_1 = baseUtc_2 + serial * DAY_TO_MS;
44
+ var utcDate_1 = new Date(utcMillis_1);
45
+ return new Date(utcDate_1.getUTCFullYear(), utcDate_1.getUTCMonth(), utcDate_1.getUTCDate(), utcDate_1.getUTCHours(), utcDate_1.getUTCMinutes(), utcDate_1.getUTCSeconds(), utcDate_1.getUTCMilliseconds());
46
+ }
47
+ if (serial === EXCEL_LEAP_BUG_SERIAL) {
48
+ return new Date(1900, 1, 28);
49
+ }
50
+ var baseUtc = Date.UTC(1899, 11, 31);
51
+ var dayCount = serial < EXCEL_LEAP_BUG_SERIAL ? serial : serial - 1;
52
+ var utcMillis = baseUtc + dayCount * DAY_TO_MS;
53
+ var utcDate = new Date(utcMillis);
54
+ return new Date(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate(), utcDate.getUTCHours(), utcDate.getUTCMinutes(), utcDate.getUTCSeconds(), utcDate.getUTCMilliseconds());
55
+ };
56
+ exports.toDate = toDate;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Check if its being rendered in Browser or SSR
3
+ */
4
+ export declare const canUseDOM: boolean;
5
+ export declare const moveSelectionToEndOfActiveInput: () => void;
6
+ export declare const moveSelectionToEndOfTextArea: () => void;
7
+ export declare const scheduleAfterPaint: (callback: () => void) => () => void;
8
+ export declare const focusableNodeNames: Set<string>;
9
+ export declare const isFocusable: (el: Element | null) => boolean;
10
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../dom.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,SAAS,SAGkB,CAAC;AAEzC,eAAO,MAAM,+BAA+B,YAsB3C,CAAC;AAEF,eAAO,MAAM,4BAA4B,YAiBxC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,IAAI,eAmCtD,CAAC;AAGF,eAAO,MAAM,kBAAkB,aAA2C,CAAC;AAE3E,eAAO,MAAM,WAAW,GAAI,IAAI,OAAO,GAAG,IAAI,YAQ7C,CAAC"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isFocusable = exports.focusableNodeNames = exports.scheduleAfterPaint = exports.moveSelectionToEndOfTextArea = exports.moveSelectionToEndOfActiveInput = exports.canUseDOM = void 0;
4
+ /**
5
+ * Check if its being rendered in Browser or SSR
6
+ */
7
+ exports.canUseDOM = typeof window !== "undefined" &&
8
+ typeof document !== "undefined" &&
9
+ typeof window.document !== "undefined";
10
+ var moveSelectionToEndOfActiveInput = function () {
11
+ try {
12
+ if (!exports.canUseDOM) {
13
+ return;
14
+ }
15
+ /* Move to end */
16
+ requestAnimationFrame(function () {
17
+ if (document.activeElement) {
18
+ var range = document.createRange();
19
+ range.selectNodeContents(document.activeElement);
20
+ range.collapse(false);
21
+ var selection = typeof window !== "undefined" ? window.getSelection() : undefined;
22
+ if (selection) {
23
+ selection.removeAllRanges();
24
+ selection.addRange(range);
25
+ }
26
+ }
27
+ });
28
+ }
29
+ catch (err) {
30
+ console.log("Failed to collapse selection", err);
31
+ }
32
+ };
33
+ exports.moveSelectionToEndOfActiveInput = moveSelectionToEndOfActiveInput;
34
+ var moveSelectionToEndOfTextArea = function () {
35
+ try {
36
+ if (!exports.canUseDOM) {
37
+ return;
38
+ }
39
+ if (document.activeElement &&
40
+ document.activeElement.tagName === "TEXTAREA") {
41
+ var textarea = document.activeElement;
42
+ var end = textarea.value.length;
43
+ // ✅ Move focus to End of textarea
44
+ textarea.setSelectionRange(end, end);
45
+ textarea.focus();
46
+ }
47
+ }
48
+ catch (err) { }
49
+ };
50
+ exports.moveSelectionToEndOfTextArea = moveSelectionToEndOfTextArea;
51
+ var scheduleAfterPaint = function (callback) {
52
+ if (typeof requestAnimationFrame === "function") {
53
+ if (typeof MessageChannel !== "undefined") {
54
+ var channel_1 = new MessageChannel();
55
+ channel_1.port1.onmessage = function () {
56
+ channel_1.port1.onmessage = null;
57
+ callback();
58
+ };
59
+ requestAnimationFrame(function () {
60
+ channel_1.port2.postMessage(null);
61
+ });
62
+ return function () {
63
+ channel_1.port1.onmessage = null;
64
+ };
65
+ }
66
+ var frameId_1 = requestAnimationFrame(function () { return callback(); });
67
+ return function () {
68
+ if (typeof cancelAnimationFrame === "function") {
69
+ cancelAnimationFrame(frameId_1);
70
+ }
71
+ };
72
+ }
73
+ if (typeof MessageChannel !== "undefined") {
74
+ var channel_2 = new MessageChannel();
75
+ channel_2.port1.onmessage = function () {
76
+ channel_2.port1.onmessage = null;
77
+ callback();
78
+ };
79
+ channel_2.port2.postMessage(null);
80
+ return function () {
81
+ channel_2.port1.onmessage = null;
82
+ };
83
+ }
84
+ callback();
85
+ return function () { };
86
+ };
87
+ exports.scheduleAfterPaint = scheduleAfterPaint;
88
+ /* Focusable node names */
89
+ exports.focusableNodeNames = new Set(["INPUT", "TEXTAREA", "SELECT"]);
90
+ var isFocusable = function (el) {
91
+ if (!el) {
92
+ return false;
93
+ }
94
+ return (Boolean(el.getAttribute("contenteditable")) ||
95
+ exports.focusableNodeNames.has(el.nodeName));
96
+ };
97
+ exports.isFocusable = isFocusable;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Pattern-based type inference (Excel parity). xlsx files routinely carry
3
+ * a `numberFormat.pattern` without an accompanying `type` field — these
4
+ * helpers let callers classify such cells from the pattern alone.
5
+ *
6
+ * Notes:
7
+ * - `isDateFormat` from numfmt returns true for any pattern containing
8
+ * date *or* time tokens. We split that into DATE (date only) vs
9
+ * DATE_TIME (has a time component) using `getFormatDateInfo`, mirroring
10
+ * Excel's `CELL("format")` distinctions.
11
+ * - `isTextFormat` only flags patterns whose entire body is the `@`
12
+ * placeholder. Multi-section formats with an `@` text section
13
+ * (`#,##0;-#,##0;0;[Magenta]@`) are NOT text formats — they're number
14
+ * formats whose text section happens to be reachable for string values.
15
+ */
16
+ export declare const isDatePattern: (pattern: string | undefined | null) => boolean;
17
+ export declare const isDateTimePattern: (pattern: string | undefined | null) => boolean;
18
+ export declare const isTimePattern: (pattern: string | undefined | null) => boolean;
19
+ export declare const isTextPattern: (pattern: string | undefined | null) => boolean;
20
+ export declare const ssfFormat: (pattern: string, value: any, locale?: string) => string;
21
+ export declare const ssfFormatColor: (pattern: string, value: any) => string | undefined;
22
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../formatter.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,OASlE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,GAAG,SAAS,GAAG,IAAI,KACjC,OAWF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,OAWlE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,GAAG,SAAS,GAAG,IAAI,KAAG,OAOlE,CAAC;AAMF,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,EACf,OAAO,GAAG,EACV,SAAS,MAAM,KACd,MAeF,CAAC;AAmLF,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,OAAO,GAAG,KACT,MAAM,GAAG,SAoBX,CAAC"}
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ssfFormatColor = exports.ssfFormat = exports.isTextPattern = exports.isTimePattern = exports.isDateTimePattern = exports.isDatePattern = void 0;
4
+ var numfmt_1 = require("numfmt");
5
+ var colors_1 = require("./colors");
6
+ /**
7
+ * Pattern-based type inference (Excel parity). xlsx files routinely carry
8
+ * a `numberFormat.pattern` without an accompanying `type` field — these
9
+ * helpers let callers classify such cells from the pattern alone.
10
+ *
11
+ * Notes:
12
+ * - `isDateFormat` from numfmt returns true for any pattern containing
13
+ * date *or* time tokens. We split that into DATE (date only) vs
14
+ * DATE_TIME (has a time component) using `getFormatDateInfo`, mirroring
15
+ * Excel's `CELL("format")` distinctions.
16
+ * - `isTextFormat` only flags patterns whose entire body is the `@`
17
+ * placeholder. Multi-section formats with an `@` text section
18
+ * (`#,##0;-#,##0;0;[Magenta]@`) are NOT text formats — they're number
19
+ * formats whose text section happens to be reachable for string values.
20
+ */
21
+ var isDatePattern = function (pattern) {
22
+ if (!pattern)
23
+ return false;
24
+ try {
25
+ if (!(0, numfmt_1.isDateFormat)(pattern))
26
+ return false;
27
+ var info = (0, numfmt_1.getFormatDateInfo)(pattern);
28
+ return info.day || info.month || info.year;
29
+ }
30
+ catch (_a) {
31
+ return false;
32
+ }
33
+ };
34
+ exports.isDatePattern = isDatePattern;
35
+ var isDateTimePattern = function (pattern) {
36
+ if (!pattern)
37
+ return false;
38
+ try {
39
+ if (!(0, numfmt_1.isDateFormat)(pattern))
40
+ return false;
41
+ var info = (0, numfmt_1.getFormatDateInfo)(pattern);
42
+ var hasDate = info.day || info.month || info.year;
43
+ var hasTime = info.hours || info.minutes || info.seconds;
44
+ return hasDate && hasTime;
45
+ }
46
+ catch (_a) {
47
+ return false;
48
+ }
49
+ };
50
+ exports.isDateTimePattern = isDateTimePattern;
51
+ var isTimePattern = function (pattern) {
52
+ if (!pattern)
53
+ return false;
54
+ try {
55
+ if (!(0, numfmt_1.isDateFormat)(pattern))
56
+ return false;
57
+ var info = (0, numfmt_1.getFormatDateInfo)(pattern);
58
+ var hasDate = info.day || info.month || info.year;
59
+ var hasTime = info.hours || info.minutes || info.seconds;
60
+ return hasTime && !hasDate;
61
+ }
62
+ catch (_a) {
63
+ return false;
64
+ }
65
+ };
66
+ exports.isTimePattern = isTimePattern;
67
+ var isTextPattern = function (pattern) {
68
+ if (!pattern)
69
+ return false;
70
+ try {
71
+ return (0, numfmt_1.isTextFormat)(pattern);
72
+ }
73
+ catch (_a) {
74
+ return false;
75
+ }
76
+ };
77
+ exports.isTextPattern = isTextPattern;
78
+ var isSingleSectionElapsedTimePattern = function (pattern) {
79
+ return !pattern.includes(";") &&
80
+ /\[(?:h+|m+|s+)\]/i.test(pattern.replace(/\[\$[^\]]+\]/g, ""));
81
+ };
82
+ var ssfFormat = function (pattern, value, locale) {
83
+ try {
84
+ var isNegativeElapsedTime = typeof value === "number" &&
85
+ value < 0 &&
86
+ isSingleSectionElapsedTimePattern(pattern);
87
+ var formatted = (0, numfmt_1.format)(pattern, isNegativeElapsedTime ? Math.abs(value) : value, { locale: locale });
88
+ return isNegativeElapsedTime ? "-".concat(formatted) : formatted;
89
+ }
90
+ catch (err) {
91
+ return String(value);
92
+ }
93
+ };
94
+ exports.ssfFormat = ssfFormat;
95
+ /**
96
+ * Excel's legacy fixed 56-color palette used by `[ColorN]` directives
97
+ * inside number format patterns (1-indexed). This palette is INDEPENDENT
98
+ * of the workbook's `<indexedColors>` block — `[ColorN]` always refers
99
+ * to Excel's hard-coded legacy palette, even in files that override the
100
+ * indexed colors.
101
+ *
102
+ * Excel's `[ColorN]` (1-56) resolves to indexed-palette entry `N + 7`
103
+ * (indices 8–63 of the 64-entry legacy palette; entries 0–7 are the
104
+ * "EGA duplicate" block that `[ColorN]` never addresses).
105
+ *
106
+ * `numfmt` instead resolves `[ColorN]` as its `indexColors[N - 1]` — a
107
+ * straight off-by-8 against Excel. That happens to agree for N=1..8
108
+ * (the palette's first 8 entries repeat at 8..15) but is wrong for 28
109
+ * of the remaining 48 indices: `[Color11]` (Excel navy `#000080`)
110
+ * renders pure red, as do `[Color17]` and `[Color38]`. We therefore
111
+ * resolve `[ColorN]` ourselves whenever the matched format segment
112
+ * carries one (see `ssfFormatColor`).
113
+ *
114
+ * Source: ECMA-376 §18.8.27 (indexedColors) and Excel's documented
115
+ * legacy palette. Note `[ColorN]` always refers to Excel's hard-coded
116
+ * legacy palette, never a workbook's custom `<indexedColors>` block.
117
+ */
118
+ var LEGACY_COLOR_PALETTE = {};
119
+ for (var n = 1; n <= 56; n++) {
120
+ LEGACY_COLOR_PALETTE[n] = colors_1.IndexedColors[n + 7];
121
+ }
122
+ var COLOR_DIRECTIVE_REGEX = /\[Color(\d+)\]/i;
123
+ var COLOR_OVERRIDE_CACHE = new Map();
124
+ var COLOR_OVERRIDE_CACHE_LIMIT = 256;
125
+ /**
126
+ * Extract a `[ColorN]` directive resolution for each segment of a
127
+ * SpreadsheetML pattern. Returns `null` (cached) if the pattern
128
+ * contains no `[ColorN]` at all — short-circuits any further work
129
+ * for the vast majority of patterns. Walks the pattern once,
130
+ * scanning for `;` separators outside string literals and `[ColorN]`
131
+ * tokens; no `String#split` allocation.
132
+ */
133
+ var PATTERNS_WITHOUT_COLOR = new Set();
134
+ var getPerSegmentColorOverrides = function (pattern) {
135
+ if (PATTERNS_WITHOUT_COLOR.has(pattern))
136
+ return null;
137
+ var cached = COLOR_OVERRIDE_CACHE.get(pattern);
138
+ if (cached)
139
+ return cached;
140
+ // Fast pre-check: no `[Color` substring → no override possible.
141
+ // `indexOf` is far cheaper than a regex when the pattern is long
142
+ // and there's no match. (`[ColorN]` is case-sensitive — Excel
143
+ // accepts `[color10]` too but the standard form is title case.)
144
+ if (pattern.indexOf("[Color") === -1 && pattern.indexOf("[color") === -1) {
145
+ if (PATTERNS_WITHOUT_COLOR.size > COLOR_OVERRIDE_CACHE_LIMIT) {
146
+ PATTERNS_WITHOUT_COLOR.clear();
147
+ }
148
+ PATTERNS_WITHOUT_COLOR.add(pattern);
149
+ return null;
150
+ }
151
+ // Single pass: track current segment, current `[ColorN]` index, and
152
+ // whether we're inside a string literal. When we hit `;` outside a
153
+ // string, advance the segment. When we see `[Color\d+]`, record it
154
+ // for the current segment (only the first occurrence per segment —
155
+ // matches Excel's behaviour).
156
+ var segmentColors = [
157
+ undefined,
158
+ undefined,
159
+ undefined,
160
+ undefined,
161
+ ];
162
+ var seg = 0;
163
+ var inString = false;
164
+ var escape = false;
165
+ for (var i = 0; i < pattern.length; i++) {
166
+ if (seg > 3)
167
+ break;
168
+ var ch = pattern[i];
169
+ if (escape) {
170
+ escape = false;
171
+ continue;
172
+ }
173
+ if (ch === "\\") {
174
+ escape = true;
175
+ continue;
176
+ }
177
+ if (ch === '"') {
178
+ inString = !inString;
179
+ continue;
180
+ }
181
+ if (ch === ";" && !inString) {
182
+ seg++;
183
+ continue;
184
+ }
185
+ if (ch === "[" && !inString && segmentColors[seg] === undefined) {
186
+ // Look ahead for `Color\d+]` — case-insensitive on the prefix.
187
+ var end = pattern.indexOf("]", i + 1);
188
+ if (end === -1)
189
+ continue;
190
+ var inside = pattern.slice(i + 1, end);
191
+ if (/^Color\d+$/i.test(inside)) {
192
+ var idx = Number(inside.slice(5));
193
+ var resolved = LEGACY_COLOR_PALETTE[idx];
194
+ if (resolved)
195
+ segmentColors[seg] = resolved;
196
+ }
197
+ i = end;
198
+ continue;
199
+ }
200
+ }
201
+ var result = [
202
+ segmentColors[0],
203
+ segmentColors[1],
204
+ segmentColors[2],
205
+ segmentColors[3],
206
+ Math.min(seg, 3) + 1,
207
+ ];
208
+ // No `[ColorN]` in any segment after all — treat as "no override".
209
+ if (!result.slice(0, 4).some(function (x) { return x !== undefined; })) {
210
+ if (PATTERNS_WITHOUT_COLOR.size > COLOR_OVERRIDE_CACHE_LIMIT) {
211
+ PATTERNS_WITHOUT_COLOR.clear();
212
+ }
213
+ PATTERNS_WITHOUT_COLOR.add(pattern);
214
+ return null;
215
+ }
216
+ if (COLOR_OVERRIDE_CACHE.size > COLOR_OVERRIDE_CACHE_LIMIT) {
217
+ COLOR_OVERRIDE_CACHE.clear();
218
+ }
219
+ COLOR_OVERRIDE_CACHE.set(pattern, result);
220
+ return result;
221
+ };
222
+ /**
223
+ * Pick the `[ColorN]` override the value's matched segment carries, honoring
224
+ * Excel's section-selection rules for patterns with fewer than 4 sections:
225
+ * one section applies to every numeric value; with two, negatives take the
226
+ * second; zero takes the third only when present; text takes the fourth only
227
+ * when present (a number-only pattern leaves text unformatted — no color).
228
+ */
229
+ var pickSegmentOverride = function (overrides, value) {
230
+ var sections = overrides[4];
231
+ if (typeof value === "string") {
232
+ return sections === 4 ? overrides[3] : undefined;
233
+ }
234
+ var n = typeof value === "number" ? value : Number(value);
235
+ if (!Number.isFinite(n) || n > 0)
236
+ return overrides[0];
237
+ if (n < 0)
238
+ return sections >= 2 ? overrides[1] : overrides[0];
239
+ return sections >= 3 ? overrides[2] : overrides[0];
240
+ };
241
+ var ssfFormatColor = function (pattern, value) {
242
+ // numfmt resolves `[ColorN]` as its `indexColors[N - 1]`, but Excel's
243
+ // `[ColorN]` is legacy-indexed-palette entry `N + 7` — numfmt's answer
244
+ // is wrong for most N ≥ 9 (`[Color11]` navy renders pure red) and
245
+ // `#FFF` for some others. Whenever the matched segment carries a
246
+ // `[ColorN]` directive, prefer our palette resolution over numfmt's
247
+ // raw color. The `PATTERNS_WITHOUT_COLOR` set makes this check free
248
+ // for the common case of patterns with no `[ColorN]`.
249
+ var overrides = getPerSegmentColorOverrides(pattern);
250
+ if (overrides) {
251
+ var resolved = pickSegmentOverride(overrides, value);
252
+ if (resolved)
253
+ return resolved;
254
+ }
255
+ var raw;
256
+ try {
257
+ raw = (0, numfmt_1.formatColor)(pattern, value);
258
+ }
259
+ catch (err) {
260
+ raw = undefined;
261
+ }
262
+ return raw && raw.length > 0 ? raw : undefined;
263
+ };
264
+ exports.ssfFormatColor = ssfFormatColor;
@@ -0,0 +1,7 @@
1
+ import type { CellInterface, GridRange } from "@rowsncolumns/common-types";
2
+ export interface FormulaToRelativeReferenceOptions {
3
+ exclusionRange?: GridRange;
4
+ ignoreCircular?: boolean;
5
+ }
6
+ export declare const formulaToRelativeReference: (formula: string | undefined, sourceCell: CellInterface, destinationCell: CellInterface, options?: FormulaToRelativeReferenceOptions) => string | undefined;
7
+ //# sourceMappingURL=formula-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula-refs.d.ts","sourceRoot":"","sources":["../../formula-refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAsB3E,MAAM,WAAW,iCAAiC;IAChD,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,MAAM,GAAG,SAAS,EAC3B,YAAY,aAAa,EACzB,iBAAiB,aAAa,EAC9B,UAAU,iCAAiC,KAC1C,MAAM,GAAG,SAgCX,CAAC"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formulaToRelativeReference = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var numbers_1 = require("./numbers");
6
+ var CELL_ADDR_RE = /((?:'[^']+'|[^'!,]+)!)?(\$?[A-Z]+\$?\d+)(?::(\$?[A-Z]+\$?\d+))?/g;
7
+ var parseAddr = function (addr) {
8
+ var m = /^(\$?)([A-Z]+)(\$?)(\d+)$/.exec(addr);
9
+ if (!m)
10
+ return null;
11
+ var _a = tslib_1.__read(m, 5), absCol = _a[1], colAlpha = _a[2], absRow = _a[3], rowStr = _a[4];
12
+ return {
13
+ col: (0, numbers_1.alpha2number)(colAlpha),
14
+ row: parseInt(rowStr, 10),
15
+ absCol: absCol === "$",
16
+ absRow: absRow === "$",
17
+ };
18
+ };
19
+ var formatAddr = function (row, col, absCol, absRow) {
20
+ var colAlpha = (0, numbers_1.number2Alpha)(Math.max(0, col - 1));
21
+ var rowNum = Math.max(1, row);
22
+ return "".concat(absCol ? "$" : "").concat(colAlpha).concat(absRow ? "$" : "").concat(rowNum);
23
+ };
24
+ var formulaToRelativeReference = function (formula, sourceCell, destinationCell, options) {
25
+ // Arguments exclusionRange and ignoreCircular were previously unused in this implementation
26
+ // We keep the options signature for compatibility but they remain unused in this regex-based impl?
27
+ // Actually, checking the previous code, they were underscored (_exclusionRange) so likely unused.
28
+ if (!formula)
29
+ return formula;
30
+ if (sourceCell.rowIndex === destinationCell.rowIndex &&
31
+ sourceCell.columnIndex === destinationCell.columnIndex) {
32
+ return formula;
33
+ }
34
+ var dRow = destinationCell.rowIndex - sourceCell.rowIndex;
35
+ var dCol = destinationCell.columnIndex - sourceCell.columnIndex;
36
+ return formula.replace(CELL_ADDR_RE, function (match, sheetPrefix, left, right) {
37
+ var adjustOne = function (addr) {
38
+ var p = parseAddr(addr);
39
+ if (!p)
40
+ return addr;
41
+ var newRow = p.absRow ? p.row : p.row + dRow;
42
+ var newCol = p.absCol ? p.col : p.col + dCol;
43
+ return formatAddr(newRow, newCol, p.absCol, p.absRow);
44
+ };
45
+ if (right) {
46
+ var leftAdjusted = adjustOne(left);
47
+ var rightAdjusted = adjustOne(right);
48
+ return "".concat(sheetPrefix !== null && sheetPrefix !== void 0 ? sheetPrefix : "").concat(leftAdjusted, ":").concat(rightAdjusted);
49
+ }
50
+ var singleAdjusted = adjustOne(left);
51
+ return "".concat(sheetPrefix !== null && sheetPrefix !== void 0 ? sheetPrefix : "").concat(singleAdjusted);
52
+ });
53
+ };
54
+ exports.formulaToRelativeReference = formulaToRelativeReference;
@@ -0,0 +1,80 @@
1
+ import type { AreaStyle, GridRange, SelectionArea } from "@rowsncolumns/common-types";
2
+ /**
3
+ * Add/remove parenthesis in formulas
4
+ * @param str
5
+ * @returns
6
+ */
7
+ export declare const balanceParentheses: (str: string) => string;
8
+ /**
9
+ * Add closing quotes in formulas when a string is unterminated.
10
+ * Handles escaped quotes ("") inside strings.
11
+ */
12
+ export declare const balanceQuotes: (str: string) => string;
13
+ /**
14
+ * Add/remove parenthesis and add closing quotes in formulas.
15
+ */
16
+ export declare const balanceFormula: (str: string) => string;
17
+ /**
18
+ * Check if parenthesis is balanced
19
+ * @param str
20
+ * @returns
21
+ */
22
+ export declare const isBalancedParenthesis: (str: string) => boolean;
23
+ export declare const looksLikeMarkdown: (text: string) => boolean;
24
+ export declare const setDefaultEnableAtFormula: (enable?: boolean) => void;
25
+ /**
26
+ * Check if text is a formula
27
+ * @param text
28
+ * @returns
29
+ */
30
+ export declare const isAFormula: (text: any) => boolean;
31
+ /**
32
+ * Check if text is a formula-shaped expression stored WITHOUT the
33
+ * leading "=". OOXML defined names (`<definedName>` in workbook.xml)
34
+ * store their expressions bare — `OFFSET(Sheet1!$A$1,0,0,10)` rather
35
+ * than `=OFFSET(...)` — so `isAFormula` can't classify them.
36
+ *
37
+ * Returns false for anything that already resolves as a static value
38
+ * or plain reference today: quoted string / numeric / boolean
39
+ * literals, single-area range references (including external-workbook
40
+ * references like `'[1]Revenue'!$A$17`), and broken `#REF!`
41
+ * expressions. Returns true only for expressions that need the
42
+ * calculator: function calls and operator expressions.
43
+ * @param text
44
+ * @returns
45
+ */
46
+ export declare const isBareFormulaExpression: (text: unknown) => boolean;
47
+ export declare const isAlternateFormula: (text: string) => boolean;
48
+ export declare const isValidFormula: (text: any) => boolean;
49
+ /**
50
+ * Check if a key is an Arrow key
51
+ * @param code
52
+ * @returns
53
+ */
54
+ export declare const isAnArrowKey: (code: string) => boolean;
55
+ /**
56
+ * Iterate over all cells in a bound
57
+ * @param bounds
58
+ * @param callback
59
+ */
60
+ export declare const iterateCells: (top: number, right: number | ((rowIndex: number) => number), bottom: number, left: number) => Generator<[number, number]>;
61
+ export declare function combineIterators<T>(...generators: (Generator<T> | undefined)[]): Generator<T>;
62
+ /**
63
+ * Iterate cells in range
64
+ * @param range
65
+ * @returns
66
+ */
67
+ export type GridRangeIterator = GridRange | {
68
+ startRowIndex: number;
69
+ endColumnIndex: number | ((rowIndex: number) => number);
70
+ endRowIndex: number;
71
+ startColumnIndex: number;
72
+ };
73
+ export declare const iterateCellsInRange: (range: GridRangeIterator) => Generator<[number, number], any, any>;
74
+ /**
75
+ * Iterate all cells in multiple selections
76
+ * @param selections
77
+ * @returns
78
+ */
79
+ export declare const iterateSelections: <T extends AreaStyle>(selections: SelectionArea<T>[]) => Generator<Generator<[number, number], any, any>, void, unknown>;
80
+ //# sourceMappingURL=formula.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula.d.ts","sourceRoot":"","sources":["../../formula.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACd,MAAM,4BAA4B,CAAC;AAgBpC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,WAc7C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,WAkDxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,WAEzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,KAAK,MAAM,YAEhD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,OAsChD,CAAC;AAIF,eAAO,MAAM,yBAAyB,GAAI,SAAS,OAAO,SAEzD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,GAAG,YAcnC,CAAC;AAYF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,OAAO,KAAG,OAgCvD,CAAC;AAgBF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,YAwC9C,CAAC;AAGF,eAAO,MAAM,cAAc,GAAI,MAAM,GAAG,YAGvC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,YAA6B,CAAC;AAEvE;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,MAAM,EACX,OAAO,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,EAC9C,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,SAAS,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAO5B,CAAC;AAEF,wBAAiB,gBAAgB,CAAC,CAAC,EACjC,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,GAC1C,SAAS,CAAC,CAAC,CAAC,CAId;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT;IACE,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AACN,eAAO,MAAM,mBAAmB,GAAI,OAAO,iBAAiB,0CAO3D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAc,CAAC,SAAS,SAAS,EAC7D,YAAY,aAAa,CAAC,CAAC,CAAC,EAAE,oEAK/B,CAAC"}