@react-fabric/utilities 1.0.0-beta.9 → 1.0.2

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 (168) hide show
  1. package/dist/cjs/css/boundingBox.js +72 -0
  2. package/dist/cjs/css/cn.js +39 -0
  3. package/dist/cjs/css/imageColorset.js +96 -0
  4. package/dist/cjs/data/countries.js +98 -0
  5. package/dist/cjs/{_fileType.js → data/fileType.js} +37 -19
  6. package/dist/cjs/data/format.js +136 -0
  7. package/dist/cjs/helpers/debounce.js +63 -0
  8. package/dist/cjs/{useLogger.js → helpers/getLogger.js} +96 -96
  9. package/dist/cjs/helpers/lonlat.js +99 -0
  10. package/dist/cjs/index.js +99 -76
  11. package/dist/cjs/lists/dedupe.js +54 -0
  12. package/dist/cjs/lists/flatten.js +66 -0
  13. package/dist/cjs/{_getByPath.js → lists/getByPath.js} +58 -37
  14. package/dist/cjs/lists/groupBy.js +49 -0
  15. package/dist/cjs/matchers/compare.js +70 -0
  16. package/dist/cjs/matchers/isEmpty.js +34 -0
  17. package/dist/cjs/matchers/isEqual.js +82 -0
  18. package/dist/cjs/matchers/nullChecks.js +61 -0
  19. package/dist/cjs/matchers/typeChecks.js +127 -0
  20. package/dist/cjs/strings/ascii.js +105 -0
  21. package/dist/cjs/strings/hash.js +75 -0
  22. package/dist/cjs/strings/interpolate.js +47 -0
  23. package/dist/cjs/strings/matchString.js +54 -0
  24. package/dist/cjs/strings/template.js +48 -0
  25. package/dist/cjs/strings/tokenize.js +83 -0
  26. package/dist/cjs/utils/mergeRefs.js +56 -0
  27. package/dist/esm/css/boundingBox.js +71 -0
  28. package/dist/esm/css/cn.js +39 -0
  29. package/dist/esm/css/imageColorset.js +96 -0
  30. package/dist/esm/data/countries.js +98 -0
  31. package/dist/esm/{_fileType.js → data/fileType.js} +37 -19
  32. package/dist/esm/data/format.js +138 -0
  33. package/dist/esm/helpers/debounce.js +63 -0
  34. package/dist/esm/{useLogger.js → helpers/getLogger.js} +96 -96
  35. package/dist/esm/helpers/lonlat.js +97 -0
  36. package/dist/esm/index.js +54 -36
  37. package/dist/esm/lists/dedupe.js +54 -0
  38. package/dist/esm/lists/flatten.js +65 -0
  39. package/dist/esm/{_getByPath.js → lists/getByPath.js} +50 -29
  40. package/dist/esm/lists/groupBy.js +49 -0
  41. package/dist/esm/matchers/compare.js +70 -0
  42. package/dist/esm/matchers/isEmpty.js +34 -0
  43. package/dist/esm/matchers/isEqual.js +82 -0
  44. package/dist/esm/matchers/nullChecks.js +58 -0
  45. package/dist/esm/matchers/typeChecks.js +119 -0
  46. package/dist/esm/strings/ascii.js +105 -0
  47. package/dist/esm/strings/hash.js +73 -0
  48. package/dist/esm/strings/interpolate.js +47 -0
  49. package/dist/esm/strings/matchString.js +54 -0
  50. package/dist/esm/strings/template.js +48 -0
  51. package/dist/esm/strings/tokenize.js +82 -0
  52. package/dist/esm/utils/mergeRefs.js +56 -0
  53. package/dist/types/css/boundingBox.d.ts +46 -0
  54. package/dist/types/css/cn.d.ts +26 -0
  55. package/dist/types/css/imageColorset.d.ts +37 -0
  56. package/dist/types/data/countries.d.ts +136 -0
  57. package/dist/types/{_fileType.d.ts → data/fileType.d.ts} +41 -1
  58. package/dist/types/data/format.d.ts +122 -0
  59. package/dist/types/helpers/debounce.d.ts +38 -0
  60. package/dist/types/helpers/getLogger.d.ts +49 -0
  61. package/dist/types/helpers/lonlat.d.ts +48 -0
  62. package/dist/types/index.d.ts +54 -20
  63. package/dist/types/lists/dedupe.d.ts +36 -0
  64. package/dist/types/lists/flatten.d.ts +47 -0
  65. package/dist/types/lists/getByPath.d.ts +45 -0
  66. package/dist/types/lists/groupBy.d.ts +36 -0
  67. package/dist/types/matchers/compare.d.ts +38 -0
  68. package/dist/types/matchers/isEmpty.d.ts +38 -0
  69. package/dist/types/matchers/isEqual.d.ts +39 -0
  70. package/dist/types/matchers/nullChecks.d.ts +43 -0
  71. package/dist/types/matchers/typeChecks.d.ts +107 -0
  72. package/dist/types/strings/ascii.d.ts +34 -0
  73. package/dist/types/strings/hash.d.ts +46 -0
  74. package/dist/types/strings/interpolate.d.ts +34 -0
  75. package/dist/types/strings/matchString.d.ts +41 -0
  76. package/dist/types/strings/template.d.ts +35 -0
  77. package/dist/types/strings/tokenize.d.ts +44 -0
  78. package/dist/types/utils/mergeRefs.d.ts +36 -0
  79. package/package.json +13 -11
  80. package/src/css/boundingBox.ts +80 -0
  81. package/src/css/cn.ts +32 -0
  82. package/src/css/imageColorset.ts +97 -0
  83. package/src/data/countries.ts +126 -0
  84. package/src/{_fileType.ts → data/fileType.ts} +72 -89
  85. package/src/data/format.ts +192 -0
  86. package/src/helpers/debounce.ts +49 -0
  87. package/src/{useLogger.ts → helpers/getLogger.ts} +52 -101
  88. package/src/helpers/lonlat.ts +124 -0
  89. package/src/index.ts +57 -37
  90. package/src/lists/dedupe.ts +46 -0
  91. package/src/lists/flatten.ts +56 -0
  92. package/src/lists/getByPath.ts +122 -0
  93. package/src/lists/groupBy.ts +47 -0
  94. package/src/matchers/compare.ts +64 -0
  95. package/src/matchers/isEmpty.ts +54 -0
  96. package/src/matchers/isEqual.ts +71 -0
  97. package/src/matchers/nullChecks.ts +55 -0
  98. package/src/matchers/typeChecks.ts +146 -0
  99. package/src/strings/ascii.ts +100 -0
  100. package/src/strings/hash.ts +68 -0
  101. package/src/strings/interpolate.ts +42 -0
  102. package/src/strings/matchString.ts +49 -0
  103. package/src/strings/template.ts +43 -0
  104. package/src/strings/tokenize.ts +77 -0
  105. package/src/utils/mergeRefs.ts +47 -0
  106. package/src/{yup.ts → utils/yup.ts} +3 -3
  107. package/dist/cjs/_ascii.js +0 -76
  108. package/dist/cjs/_boundingBox.js +0 -59
  109. package/dist/cjs/_countries.js +0 -2805
  110. package/dist/cjs/_debounce.js +0 -53
  111. package/dist/cjs/_dedupe.js +0 -63
  112. package/dist/cjs/_fetch.js +0 -128
  113. package/dist/cjs/_format.js +0 -118
  114. package/dist/cjs/_hash.js +0 -67
  115. package/dist/cjs/_interpolate.js +0 -47
  116. package/dist/cjs/_isEqual.js +0 -108
  117. package/dist/cjs/_isType.js +0 -98
  118. package/dist/cjs/_mergeRefs.js +0 -40
  119. package/dist/cjs/_tokenize.js +0 -67
  120. package/dist/cjs/getImageColorset.js +0 -70
  121. package/dist/esm/_ascii.js +0 -76
  122. package/dist/esm/_boundingBox.js +0 -58
  123. package/dist/esm/_countries.js +0 -2805
  124. package/dist/esm/_debounce.js +0 -53
  125. package/dist/esm/_dedupe.js +0 -60
  126. package/dist/esm/_fetch.js +0 -128
  127. package/dist/esm/_format.js +0 -120
  128. package/dist/esm/_hash.js +0 -65
  129. package/dist/esm/_interpolate.js +0 -46
  130. package/dist/esm/_isEqual.js +0 -106
  131. package/dist/esm/_isType.js +0 -85
  132. package/dist/esm/_mergeRefs.js +0 -40
  133. package/dist/esm/_tokenize.js +0 -66
  134. package/dist/esm/getImageColorset.js +0 -70
  135. package/dist/types/_ascii.d.ts +0 -5
  136. package/dist/types/_boundingBox.d.ts +0 -10
  137. package/dist/types/_countries.d.ts +0 -85
  138. package/dist/types/_debounce.d.ts +0 -8
  139. package/dist/types/_dedupe.d.ts +0 -4
  140. package/dist/types/_fetch.d.ts +0 -23
  141. package/dist/types/_format.d.ts +0 -27
  142. package/dist/types/_getByPath.d.ts +0 -10
  143. package/dist/types/_hash.d.ts +0 -16
  144. package/dist/types/_interpolate.d.ts +0 -6
  145. package/dist/types/_isEqual.d.ts +0 -15
  146. package/dist/types/_isType.d.ts +0 -14
  147. package/dist/types/_mergeRefs.d.ts +0 -1
  148. package/dist/types/_tokenize.d.ts +0 -8
  149. package/dist/types/getImageColorset.d.ts +0 -1
  150. package/dist/types/useLogger.d.ts +0 -25
  151. package/src/_ascii.ts +0 -93
  152. package/src/_boundingBox.ts +0 -72
  153. package/src/_countries.ts +0 -3046
  154. package/src/_debounce.ts +0 -42
  155. package/src/_dedupe.ts +0 -56
  156. package/src/_fetch.ts +0 -109
  157. package/src/_format.ts +0 -141
  158. package/src/_getByPath.ts +0 -108
  159. package/src/_hash.ts +0 -62
  160. package/src/_interpolate.ts +0 -42
  161. package/src/_isEqual.ts +0 -102
  162. package/src/_isType.ts +0 -105
  163. package/src/_mergeRefs.ts +0 -33
  164. package/src/_tokenize.ts +0 -69
  165. package/src/getImageColorset.ts +0 -81
  166. /package/dist/cjs/{yup.js → utils/yup.js} +0 -0
  167. /package/dist/esm/{yup.js → utils/yup.js} +0 -0
  168. /package/dist/types/{yup.d.ts → utils/yup.d.ts} +0 -0
@@ -0,0 +1,192 @@
1
+ /**
2
+ * React Fabric
3
+ * @version 1.0.0
4
+ * @license MIT
5
+ * @copyright 2024 Adarsh Pastakia
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+
26
+ import { differenceInDays, format as dtformat, parseISO } from "date-fns";
27
+ import { parsePhoneNumberFromString, type CountryCode } from "libphonenumber-js";
28
+ import numeral from "numeral";
29
+ import Countries from "../data/countries";
30
+ import { isEmpty } from "../matchers/isEmpty";
31
+ import { isNil } from "../matchers/nullChecks";
32
+
33
+ /**
34
+ * Format utility functions for various data types.
35
+ * This namespace provides methods to format phone numbers, numbers, bytes, percentages, dates, and durations.
36
+ */
37
+
38
+ export namespace Format {
39
+ function getPhone(value: string, country: string) {
40
+ const phone = value.match(/^[0+]/) != null ? value.replace(/^00/, "+") : `+${value}`;
41
+ const number = parsePhoneNumberFromString(phone, country as CountryCode);
42
+ /* istanbul ignore next */
43
+ return (
44
+ number ?? {
45
+ country: "",
46
+ formatInternational: () => value,
47
+ }
48
+ );
49
+ }
50
+
51
+ function numberFormat(number?: string | number, format = "0,0[.]00a") {
52
+ if (isNil(number)) {
53
+ return "";
54
+ }
55
+ const prefix = `${number}`.startsWith("+") ? "+" : "";
56
+ return prefix + numeral(number).format(format);
57
+ }
58
+
59
+ function makeDuration(value: number, fmt = "HH:mm:ss.SSS") {
60
+ if (!isNaN(value)) {
61
+ const days = differenceInDays(value, 0);
62
+ const prefix = days > 0 ? `${days}d:` : "";
63
+ let time = dtformat(parseISO(new Date(value).toISOString().replace("Z", "")), fmt);
64
+ if (!prefix) time = time.replace(/^00:/, "");
65
+ return `${prefix}${time}`;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Format phone number with country flag or emoji.
71
+ * It takes a phone number string, a country code, and a boolean to indicate whether to use CSS classes for flags.
72
+ * If the phone number is empty, less than 6 characters, or does not match the regex for valid phone numbers,
73
+ * it returns the original value.
74
+ * If the phone number is valid, it formats the phone number using `libphonenumber-js` and returns it with the country flag or emoji.
75
+ * The country flag is represented as a CSS class, and the emoji is obtained from the `Countries` module.
76
+ *
77
+ * @param {string} value - The phone number to format.
78
+ * @param {string} country - The country code to use for formatting.
79
+ * @param {boolean} useCss - Whether to use CSS classes for flags.
80
+ * @returns {string} The formatted phone number with country flag or emoji.
81
+ */
82
+ export function phone(value?: string, country = "AE", useCss = false) {
83
+ if (isEmpty(value) || value.length < 6 || !/^[\d+\s\-()]+$/.test(value)) return value;
84
+ const phone = getPhone(value, country);
85
+ /* istanbul ignore next */
86
+ return `${useCss ? `<span class="iconify-color circle-flags--${phone.country}"></span>` : Countries.emoji(phone.country ?? "")} ${phone.formatInternational()}`;
87
+ }
88
+ /**
89
+ * Format number using `numeral`.
90
+ * It takes a number or string and a format string, and returns the formatted number.
91
+ * If the number is undefined or null, it returns an empty string.
92
+ * If the number starts with a '+', it retains the '+' sign in the formatted output.
93
+ * This function is useful for displaying numbers in a human-readable format,
94
+ * such as for financial data, statistics, or any numerical representation.
95
+ *
96
+ * @param {string | number} number - number or string to format
97
+ * @param {string} [format] - optional format string, defaults to "0,0[.]00a"
98
+ * @returns {string} formatted number
99
+ */
100
+ export function number(number?: string | number, format?: string) {
101
+ return numberFormat(number, format);
102
+ }
103
+ /**
104
+ * Format bytes using `numeral`.
105
+ * It takes a number or string and returns the formatted bytes.
106
+ * If the number is undefined or null, it returns an empty string.
107
+ * If the number starts with a '+', it retains the '+' sign in the formatted output.
108
+ * This function is useful for displaying file sizes or data transfer amounts in a human-readable format.
109
+ *
110
+ * @param {string | number} number - number or string to format
111
+ * @returns {string} formatted bytes
112
+ */
113
+ export function bytes(number?: string | number) {
114
+ return numberFormat(number, "0,0[.]00b");
115
+ }
116
+ /**
117
+ * Format percentage using `numeral`.
118
+ * It takes a number or string and returns the formatted percentage.
119
+ * If the number is undefined or null, it returns an empty string.
120
+ * If the number starts with a '+', it retains the '+' sign in the formatted output.
121
+ *
122
+ * @param {string | number} number - number or string to format
123
+ * @returns {string} formatted percentage
124
+ */
125
+ export function percent(number?: string | number) {
126
+ return numberFormat(number, "0,0[.]00%");
127
+ }
128
+ /**
129
+ * Format date using `date-fns`.
130
+ * It takes a date (as a Date object, string, or number) and a format string.
131
+ * If the date is undefined or null, it returns an empty string.
132
+ * If the date is a valid date, it formats it using the provided format string.
133
+ * Format defaults to "d-M-y" if not provided.
134
+ *
135
+ * @param {date | string | number} date - Date object, string, or number to format
136
+ * @typedef {string} format - Optional format string, defaults to "d-M-y"
137
+ * @returns {string} - Formatted date string
138
+ */
139
+ export function date(date?: Date | string | number, format = "d-M-y") {
140
+ return date ? dtformat(new Date(date), format) : "";
141
+ }
142
+ /** ***************** format time duration from total seconds/milliseconds *******************/
143
+ /**
144
+ * Format time duration with milliseconds
145
+ * This function takes a number or string representing a duration in seconds or milliseconds,
146
+ * and returns a formatted string in the format "HH:mm:ss.SSS".
147
+ * If the input is undefined or null, it returns "00:00.000".
148
+ * If the input is Infinity, it returns "∞".
149
+ * The function also accepts an optional boolean parameter `isFraction` to indicate whether the input is in seconds (true) or milliseconds (false).
150
+ * If `isFraction` is true, the input is multiplied by 1000 to convert seconds to milliseconds.
151
+ * The function uses the `makeDuration` helper function to format the duration.
152
+ *
153
+ * @param {string | number} number - The duration to format, can be a string or number.
154
+ * @param {boolean} isFraction - Optional parameter to indicate if the input is in seconds (true) or milliseconds (false).
155
+ * @returns {string} - The formatted duration string.
156
+ */
157
+ export function duration(number?: string | number, isFraction?: boolean) {
158
+ if (isNil(number)) {
159
+ return "00:00.000";
160
+ }
161
+ if (number === Infinity) {
162
+ return "∞";
163
+ }
164
+ const value = parseFloat(`${number}`) * (isFraction ? 1000 : 1);
165
+ return makeDuration(value) ?? "00:00.000";
166
+ }
167
+ /**
168
+ * Format time duration in seconds
169
+ * This function takes a number or string representing a duration in seconds,
170
+ * and returns a formatted string in the format "HH:mm:ss".
171
+ * If the input is undefined or null, it returns "00:00".
172
+ * If the input is Infinity, it returns "∞".
173
+ * The function also accepts an optional boolean parameter `isFraction` to indicate whether the input is in seconds (true) or milliseconds (false).
174
+ * If `isFraction` is true, the input is multiplied by 1000 to convert seconds to milliseconds.
175
+ * The function uses the `makeDuration` helper function to format the duration.
176
+ * This function is useful for displaying durations in a human-readable format, such as for timers or elapsed time.
177
+ *
178
+ * @param {string | number} number - The duration to format, can be a string or number.
179
+ * @param {boolean} isFraction - Optional parameter to indicate if the input is in seconds (true) or milliseconds (false).
180
+ * @returns {string} - The formatted duration string.
181
+ */
182
+ export function durationSeconds(number?: string | number, isFraction?: boolean) {
183
+ if (isNil(number)) {
184
+ return "00:00";
185
+ }
186
+ if (number === Infinity) {
187
+ return "∞";
188
+ }
189
+ const value = parseFloat(`${number}`) * (isFraction ? 1000 : 1);
190
+ return makeDuration(value, "HH:mm:ss") ?? "00:00";
191
+ }
192
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * React Fabric
3
+ * @version 1.0.0
4
+ * @license MIT
5
+ * @copyright 2024 Adarsh Pastakia
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+
26
+ /* istanbul ignore file */
27
+
28
+ /**
29
+ * Debounce function to limit the rate at which a function can fire.
30
+ * It will delay the execution of the function until after a specified timeout
31
+ * has elapsed since the last time the function was invoked.
32
+ *
33
+ * @param fn - The function to debounce.
34
+ * @param timeout - The number of milliseconds to wait before invoking the function.
35
+ * @returns A debounced version of the function that can be called with any arguments.
36
+ * The debounced function also has a `cancel` method to clear the timeout.
37
+ */
38
+ export function debounce(fn: (...rest: AnyObject[]) => unknown, timeout = 500) {
39
+ /** ***************** create debounce timer id using callback hash *******************/
40
+ let _timer: number;
41
+
42
+ /** ***************** return debounced function *******************/
43
+ const cb = (...args: AnyObject[]) => {
44
+ clearTimeout(_timer);
45
+ if (typeof window !== "undefined") _timer = window.setTimeout(() => fn?.(...(args as unknown[])), timeout);
46
+ };
47
+ cb.cancel = () => clearTimeout(_timer);
48
+ return cb;
49
+ }
@@ -1,24 +1,26 @@
1
- /*
1
+ /**
2
2
  * React Fabric
3
- * @version: 1.0.0
4
- *
3
+ * @version 1.0.0
4
+ * @license MIT
5
+ * @copyright 2024 Adarsh Pastakia
5
6
  *
6
- * The MIT License (MIT)
7
- * Copyright (c) 2024 Adarsh Pastakia
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
8
13
  *
9
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
- * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
- * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
- * subject to the following conditions:
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
14
16
  *
15
- * The above copyright notice and this permission notice shall be included in all copies or substantial
16
- * portions of the Software.
17
- *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
- * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
22
24
  */
23
25
 
24
26
  interface LogDetail {
@@ -28,12 +30,12 @@ interface LogDetail {
28
30
  totalTime?: number;
29
31
  }
30
32
 
31
- enum LOG_LEVEL {
32
- OFF,
33
- WARNING,
34
- INFO,
35
- DEBUG,
36
- }
33
+ const LOG_LEVEL = {
34
+ OFF: 0,
35
+ WARNING: 1,
36
+ INFO: 2,
37
+ DEBUG: 3,
38
+ };
37
39
 
38
40
  /* istanbul ignore file */
39
41
 
@@ -51,71 +53,38 @@ const NODE = {
51
53
  logLevel() {
52
54
  return (
53
55
  // @ts-expect-error ignore
54
- global.LOG_LEVEL ??
55
- (process.env.NODE_ENV !== "production"
56
- ? LOG_LEVEL.DEBUG
57
- : LOG_LEVEL.WARNING)
56
+ (global.LOG_LEVEL as unknown as number) ?? (process.env.NODE_ENV !== "production" ? LOG_LEVEL.DEBUG : LOG_LEVEL.WARNING)
58
57
  );
59
58
  },
60
59
 
61
- makeLog(
62
- level: string,
63
- { process, module, duration, totalTime }: LogDetail = {},
64
- ) {
60
+ makeLog(level: string, { process, module, duration, totalTime }: LogDetail = {}) {
65
61
  const ret = [];
66
62
  if (process) ret.push(`${this.PROCESS}Process: ${process}${this.RESET}`);
67
63
  if (module) ret.push(`${this.PROCESS}Module: ${module}${this.RESET}`);
68
- if (duration)
69
- ret.push(`${this.DURATION}Duration: ${duration}${this.RESET}`);
70
- if (module)
71
- ret.push(`${this.DURATION}TotalTime: ${totalTime}${this.RESET}`);
64
+ if (duration) ret.push(`${this.DURATION}Duration: ${duration}${this.RESET}`);
65
+ if (module) ret.push(`${this.DURATION}TotalTime: ${totalTime}${this.RESET}`);
72
66
 
73
- return [
74
- `[${this.TIME}${new Date().toISOString()}${this.RESET}] ${level}`,
75
- ret.join(" "),
76
- ]
77
- .filter(Boolean)
78
- .join("\n");
67
+ return [`[${this.TIME}${new Date().toISOString()}${this.RESET}] ${level}`, ret.join(" ")].filter(Boolean).join("\n");
79
68
  },
80
69
 
81
70
  log(msg: string, opts: LogDetail, ...rest: unknown[]) {
82
71
  if (+this.logLevel() < LOG_LEVEL.DEBUG) return;
83
- console.log(
84
- this.makeLog(`${this.LOG}LOG${this.RESET}`, opts),
85
- `\n${msg}\n`,
86
- ...rest,
87
- );
72
+ console.log(this.makeLog(`${this.LOG}LOG${this.RESET}`, opts), `\n${msg}\n`, ...rest);
88
73
  },
89
74
  debug(msg: string, opts: LogDetail, ...rest: unknown[]) {
90
75
  if (+this.logLevel() < LOG_LEVEL.DEBUG) return;
91
- console.debug(
92
- this.makeLog(`${this.DEBUG}DEBUG${this.RESET}`, opts),
93
- `\n${msg}\n`,
94
- ...rest,
95
- );
76
+ console.debug(this.makeLog(`${this.DEBUG}DEBUG${this.RESET}`, opts), `\n${msg}\n`, ...rest);
96
77
  },
97
78
  info(msg: string, opts: LogDetail, ...rest: unknown[]) {
98
79
  if (+this.logLevel() < LOG_LEVEL.INFO) return;
99
- console.info(
100
- this.makeLog(`${this.INFO}INFO${this.RESET}`, opts),
101
- `\n${msg}\n`,
102
- ...rest,
103
- );
80
+ console.info(this.makeLog(`${this.INFO}INFO${this.RESET}`, opts), `\n${msg}\n`, ...rest);
104
81
  },
105
82
  error(msg: string, opts: LogDetail, ...rest: unknown[]) {
106
- console.error(
107
- this.makeLog(`${this.ERROR}ERROR${this.RESET}`, opts),
108
- `\n${msg}\n`,
109
- ...rest,
110
- );
83
+ console.error(this.makeLog(`${this.ERROR}ERROR${this.RESET}`, opts), `\n${msg}\n`, ...rest);
111
84
  },
112
85
  warning(msg: string, opts: LogDetail, ...rest: unknown[]) {
113
86
  if (+this.logLevel() < LOG_LEVEL.WARNING) return;
114
- console.warn(
115
- this.makeLog(`${this.WARNING}WARNING${this.RESET}`, opts),
116
- `\n${msg}\n`,
117
- ...rest,
118
- );
87
+ console.warn(this.makeLog(`${this.WARNING}WARNING${this.RESET}`, opts), `\n${msg}\n`, ...rest);
119
88
  },
120
89
  };
121
90
 
@@ -132,23 +101,14 @@ const BROWSER = {
132
101
  logLevel() {
133
102
  return (
134
103
  // @ts-expect-error ignore
135
- (typeof window !== "undefined" ? window.LOG_LEVEL : undefined) ??
136
- (process.env.NODE_ENV !== "production"
137
- ? LOG_LEVEL.DEBUG
138
- : LOG_LEVEL.WARNING)
104
+ (typeof window !== "undefined" ? (window.LOG_LEVEL as number) : undefined) ??
105
+ (process.env.NODE_ENV !== "production" ? LOG_LEVEL.DEBUG : LOG_LEVEL.WARNING)
139
106
  );
140
107
  },
141
108
 
142
- makeLog(
143
- level: string,
144
- color: string,
145
- { process, module, duration, totalTime }: LogDetail = {},
146
- ) {
109
+ makeLog(level: string, color: string, { process, module, duration, totalTime }: LogDetail = {}) {
147
110
  const ret = [];
148
- const colors = [
149
- `color:${this.TIME};font-weight:bold;`,
150
- `color:${color};font-weight:bold;`,
151
- ];
111
+ const colors = [`color:${this.TIME};font-weight:bold;`, `color:${color};font-weight:bold;`];
152
112
  if (module) ret.push(`%cModule: ${module}`);
153
113
  if (process) ret.push(`%cProcess: ${process}`);
154
114
  if (duration) ret.push(`%cDuration: ${duration}`);
@@ -158,12 +118,7 @@ const BROWSER = {
158
118
  if (duration) colors.push(`color:${this.DURATION}`);
159
119
  if (module) colors.push(`color:${this.DURATION}`);
160
120
 
161
- return [
162
- [`%c[${new Date().toISOString()}] ${level}`, ret.join(" ")]
163
- .filter(Boolean)
164
- .join("\n"),
165
- colors,
166
- ];
121
+ return [[`%c[${new Date().toISOString()}] ${level}`, ret.join(" ")].filter(Boolean).join("\n"), colors];
167
122
  },
168
123
 
169
124
  log(msg: string, opts: LogDetail, ...rest: unknown[]) {
@@ -198,9 +153,9 @@ const logger = () => {
198
153
  };
199
154
 
200
155
  /**
201
- * @internal
156
+ * Returns a logger object with log/debug/info/error/warning methods, adapted for Node or browser. Optionally takes a module name.
202
157
  */
203
- export const useLogger = (mod?: string) => ({
158
+ export const getLogger = (mod?: string) => ({
204
159
  timer(process: string) {
205
160
  const startTime = new Date().getTime();
206
161
  let nextTime = new Date().getTime();
@@ -278,27 +233,23 @@ export const useLogger = (mod?: string) => ({
278
233
  };
279
234
  },
280
235
 
281
- log(msg: string, { module = mod, ...opts }: LogDetail, ...rest: unknown[]) {
282
- logger()?.log(msg, opts, ...rest);
236
+ log(msg: string, opts: LogDetail, ...rest: unknown[]) {
237
+ logger()?.log(msg, { module: mod, ...opts }, ...rest);
283
238
  },
284
239
 
285
- debug(msg: string, { module = mod, ...opts }: LogDetail, ...rest: unknown[]) {
286
- logger()?.debug(msg, opts, ...rest);
240
+ debug(msg: string, opts: LogDetail, ...rest: unknown[]) {
241
+ logger()?.debug(msg, { module: mod, ...opts }, ...rest);
287
242
  },
288
243
 
289
- info(msg: string, { module = mod, ...opts }: LogDetail, ...rest: unknown[]) {
290
- logger()?.info(msg, opts, ...rest);
244
+ info(msg: string, opts: LogDetail, ...rest: unknown[]) {
245
+ logger()?.info(msg, { module: mod, ...opts }, ...rest);
291
246
  },
292
247
 
293
- error(msg: string, { module = mod, ...opts }: LogDetail, ...rest: unknown[]) {
294
- logger()?.error(msg, opts, ...rest);
248
+ error(msg: string, opts: LogDetail, ...rest: unknown[]) {
249
+ logger()?.error(msg, { module: mod, ...opts }, ...rest);
295
250
  },
296
251
 
297
- warning(
298
- msg: string,
299
- { module = mod, ...opts }: LogDetail,
300
- ...rest: unknown[]
301
- ) {
302
- logger()?.warning(msg, opts, ...rest);
252
+ warning(msg: string, opts: LogDetail, ...rest: unknown[]) {
253
+ logger()?.warning(msg, { module: mod, ...opts }, ...rest);
303
254
  },
304
255
  });
@@ -0,0 +1,124 @@
1
+ /*
2
+ * React Fabric
3
+ * @version: 1.0.0
4
+ *
5
+ *
6
+ * The MIT License (MIT)
7
+ * Copyright (c) 2025 Adarsh Pastakia
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
11
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13
+ * subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
16
+ * portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ import { isEmpty } from "../matchers/isEmpty";
25
+ import { isArray, isObject, isString } from "../matchers/typeChecks";
26
+
27
+ export type LngLatLike =
28
+ | {
29
+ lng: number;
30
+ lat: number;
31
+ }
32
+ | {
33
+ lon: number;
34
+ lat: number;
35
+ }
36
+ | {
37
+ longitude: number;
38
+ latitude: number;
39
+ }
40
+ | [lon: number | string, lat: number | string]
41
+ | [lon: number | string, lat: number | string, z: number | string]
42
+ | string;
43
+
44
+ /**
45
+ * Convert a decimal degree coordinate to Degrees, Minutes, Seconds (DMS) format.
46
+ * Takes a single coordinate value and returns a formatted string with direction
47
+ * indicators (N/S for latitude, E/W for longitude).
48
+ *
49
+ * @param {number} coord - The decimal degree coordinate to convert.
50
+ * @param {boolean} [isLat=false] - Whether this is a latitude coordinate (affects direction suffix).
51
+ * @returns {string} A string in the format `"degrees˚minutes'seconds" Direction` (e.g., `"40˚42'51.36"N"`).
52
+ */
53
+ function convertToDMS(coord: number, isLat = false) {
54
+ const degree = Math.floor(Math.abs(coord));
55
+ const hour = (Math.abs(coord) - degree) * 60;
56
+ const minute = (hour - Math.floor(hour)) * 60;
57
+
58
+ return `${degree}˚${Math.floor(hour)}'${minute.toFixed(2)}"${coord < 0 ? (isLat ? "S" : "W") : isLat ? "N" : "E"}`;
59
+ }
60
+
61
+ /**
62
+ * Convert various formats of longitude and latitude to a tuple of [lon, lat].
63
+ * This function supports:
64
+ * - Arrays with two or three elements (e.g., [lon, lat] or [lon, lat, alt])
65
+ * - Objects with properties `lng`, `lat`, `lon`, or `longitude` and `latitude`
66
+ * - Strings in the format "lat,lon"
67
+ * The function will return a tuple of numbers [lon, lat].
68
+ *
69
+ * @param {LngLatLike} lonLat - The input longitude and latitude in various formats.
70
+ * @returns { [lon: number, lat: number] } A tuple of [lon, lat] where lon and lat are numbers.
71
+ * @throws Error if the input is not a valid format.
72
+ */
73
+ export function convertToLonLat(lonLat: LngLatLike): [lon: number, lat: number] {
74
+ if (isEmpty(lonLat)) {
75
+ throw Error("Invalid geo coordinates");
76
+ }
77
+ if ((isArray(lonLat) && lonLat.length === 2) || (isArray(lonLat) && lonLat.length === 3)) {
78
+ return [Number(lonLat[0]), Number(lonLat[1])];
79
+ }
80
+
81
+ if (isObject(lonLat)) {
82
+ if ("longitude" in lonLat) {
83
+ return [lonLat.longitude, lonLat.latitude];
84
+ }
85
+ return ["lon" in lonLat ? lonLat.lon : lonLat.lng, lonLat.lat];
86
+ }
87
+
88
+ if (isString(lonLat)) {
89
+ const [lat, lon] = lonLat.split(",");
90
+ if (!isNaN(+lat) && !isNaN(+lon)) return [+lon, +lat];
91
+ }
92
+
93
+ throw Error("Invalid geo coordinates");
94
+ }
95
+
96
+ export function getLatitudeLongitude(lonLat: LngLatLike): { latitude: number; longitude: number } {
97
+ const [lon, lat] = convertToLonLat(lonLat);
98
+ return { latitude: lat, longitude: lon };
99
+ }
100
+
101
+ /**
102
+ * Convert a latitude and longitude to a human-readable text format.
103
+ * This function takes a latitude and longitude in various formats and
104
+ * returns a string in the format "degrees˚minutes'seconds" with direction (N/S, E/W).
105
+ *
106
+ * This function supports:
107
+ *
108
+ * - Objects with properties `lng`, `lat`, `lon`, or `longitude` and `latitude`
109
+ * - Arrays with two or three elements (e.g., [lon, lat] or [lon, lat, alt])
110
+ * - Strings in the format "lat,lon"
111
+ *
112
+ * @param {LngLatLike} latlon - The latitude and longitude in various formats.
113
+ * @returns {string} A string representation of the location in DMS format.
114
+ *
115
+ * @example
116
+ * ```jsx
117
+ * const location = getLocationAsText({ lat: 40.7128, lng: -74.0060 });
118
+ * console.log(location); // "40˚42'51.36"N, 74˚0'21.60"W"
119
+ * ```
120
+ */
121
+ export function getLocationAsText(latlon: LngLatLike) {
122
+ const [lon, lat] = convertToLonLat(latlon);
123
+ return `${convertToDMS(lat, true)}, ${convertToDMS(lon)}`;
124
+ }