toolbox-x 1.0.0 → 1.0.1-rc.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 (158) hide show
  1. package/README.md +409 -0
  2. package/dist/{Color-B3mgF9Dh.d.cts → Color-BK-IISGk.d.cts} +2 -2
  3. package/dist/{Color-D38Xrw65.d.mts → Color-BrtYYm8M.d.mts} +2 -2
  4. package/dist/{Stylog-Df7eq3-j.d.cts → Stylog-BmrFKYBu.d.mts} +5 -5
  5. package/dist/{Stylog-jvlLcMQq.d.mts → Stylog-oNGfcRqH.d.cts} +5 -5
  6. package/dist/{array-DvW0zIu6.d.mts → array-606C3HIi.d.cts} +1 -1
  7. package/dist/{array-rUnEVisO.d.cts → array-qTbLCFHP.d.mts} +1 -1
  8. package/dist/{basics-WEYWlnRO.d.cts → basics-BlJgwEqR.d.mts} +3 -3
  9. package/dist/{basics-uBSfkBEI.d.mts → basics-CEMMxosO.d.cts} +3 -3
  10. package/dist/{basics-D_eSv0cu.cjs → basics-CYqqguZr.cjs} +3 -3
  11. package/dist/{basics-Dp_aEK81.mjs → basics-DQe9mP_M.mjs} +3 -3
  12. package/dist/{case-BWIt8Ash.mjs → case-BQwn5N-k.mjs} +2 -2
  13. package/dist/{case-C-S-b5YP.d.cts → case-BYCCZ2yI.d.cts} +1 -1
  14. package/dist/{case-CybASFPD.d.mts → case-DF2Af4Fw.d.mts} +1 -1
  15. package/dist/{case-CS8Ii3A7.cjs → case-uKFzt5TY.cjs} +2 -2
  16. package/dist/change-case.cjs +1 -1
  17. package/dist/change-case.d.cts +1 -1
  18. package/dist/change-case.d.mts +1 -1
  19. package/dist/change-case.mjs +1 -1
  20. package/dist/colors.cjs +5 -5
  21. package/dist/colors.d.cts +2 -2
  22. package/dist/colors.d.mts +2 -2
  23. package/dist/colors.mjs +5 -5
  24. package/dist/constants.cjs +9 -9
  25. package/dist/constants.d.cts +5 -5
  26. package/dist/constants.d.mts +5 -5
  27. package/dist/constants.mjs +9 -9
  28. package/dist/{convert-Bn4jFomQ.mjs → convert-C8LsoKmI.mjs} +4 -4
  29. package/dist/{convert-BrzlG-m_.cjs → convert-Cqy2Llek.cjs} +3 -3
  30. package/dist/{convert-BOCgUv2D.cjs → convert-IaWh6Wab.cjs} +4 -4
  31. package/dist/{convert-DhaUoPVU.mjs → convert-lXdkXPJR.mjs} +3 -3
  32. package/dist/{converter-CmkcAppi.d.cts → converter-B2gv4EJb.d.cts} +4 -4
  33. package/dist/{converter-1P90_RcP.d.mts → converter-CcIdAN8V.d.mts} +4 -4
  34. package/dist/converter.cjs +3 -3
  35. package/dist/converter.d.cts +2 -2
  36. package/dist/converter.d.mts +2 -2
  37. package/dist/converter.mjs +3 -3
  38. package/dist/date.cjs +8 -8
  39. package/dist/date.d.cts +3 -3
  40. package/dist/date.d.mts +3 -3
  41. package/dist/date.mjs +8 -8
  42. package/dist/dom.cjs +5 -5
  43. package/dist/dom.d.cts +3 -3
  44. package/dist/dom.d.mts +3 -3
  45. package/dist/dom.mjs +5 -5
  46. package/dist/{form-BMFVGUrN.d.mts → form-CpzhN8Ub.d.mts} +2 -2
  47. package/dist/{form-DRFbryvK.d.cts → form-j_V9ZSHn.d.cts} +2 -2
  48. package/dist/{guards-DdyU4h4o.mjs → guards-DEcnNbI5.mjs} +4 -4
  49. package/dist/{guards-C8gkvIHb.cjs → guards-DGN95D2h.cjs} +1 -1
  50. package/dist/{guards-3kaUX66g.mjs → guards-DziDBD0p.mjs} +1 -1
  51. package/dist/{guards-Efhp1mNy.cjs → guards-FSW16LfU.cjs} +4 -4
  52. package/dist/guards.cjs +5 -5
  53. package/dist/guards.d.cts +3 -3
  54. package/dist/guards.d.mts +3 -3
  55. package/dist/guards.mjs +5 -5
  56. package/dist/{hash-B6JPEyAz.d.mts → hash-gQrZTSQ8.d.mts} +1 -1
  57. package/dist/{hash-NTpeKYB_.d.cts → hash-wrjn4ZYW.d.cts} +1 -1
  58. package/dist/hash.cjs +9 -9
  59. package/dist/hash.d.cts +8 -8
  60. package/dist/hash.d.mts +8 -8
  61. package/dist/hash.mjs +9 -9
  62. package/dist/{http-status-BAZdtr7-.d.mts → http-status-BLU4rv3n.d.cts} +2 -2
  63. package/dist/{http-status-U_3MtoGb.d.cts → http-status-BmUnryXC.d.mts} +2 -2
  64. package/dist/http-status.cjs +4 -4
  65. package/dist/http-status.d.cts +5 -5
  66. package/dist/http-status.d.mts +5 -5
  67. package/dist/http-status.mjs +4 -4
  68. package/dist/index.cjs +10 -10
  69. package/dist/index.d.cts +8 -8
  70. package/dist/index.d.mts +8 -8
  71. package/dist/index.mjs +10 -10
  72. package/dist/{object-B0TV3eHx.d.mts → object-NOZEWHcC.d.cts} +2 -2
  73. package/dist/{object-Blq0Amdv.d.cts → object-NOZEWHcC.d.mts} +2 -2
  74. package/dist/{objectify-CDs0Fbr1.mjs → objectify-CryKLquR.mjs} +5 -5
  75. package/dist/{objectify-DIJ-OBmo.cjs → objectify-DrwoO4bJ.cjs} +5 -5
  76. package/dist/paginator.d.cts +1 -1
  77. package/dist/paginator.d.mts +1 -1
  78. package/dist/{parse-2ubxXZRp.cjs → parse-CejohxY0.cjs} +5 -5
  79. package/dist/{parse-N7g942uy.mjs → parse-DDN7KuOa.mjs} +5 -5
  80. package/dist/{pluralizer-BjMIc6uT.d.mts → pluralizer-Bk7lN1fi.d.cts} +1 -1
  81. package/dist/{pluralizer-Cb6ZmrDl.d.cts → pluralizer-D-YOFs-L.d.mts} +1 -1
  82. package/dist/pluralizer.cjs +6 -6
  83. package/dist/pluralizer.d.cts +5 -5
  84. package/dist/pluralizer.d.mts +5 -5
  85. package/dist/pluralizer.mjs +6 -6
  86. package/dist/{specials-DzLr1ZgU.cjs → specials-BM6cx43o.cjs} +1 -1
  87. package/dist/{specials-LVONlKbQ.d.cts → specials-C-SQ_GTS.d.mts} +1 -1
  88. package/dist/{specials-D48_IZbd.d.mts → specials-CpwNC9PE.d.cts} +1 -1
  89. package/dist/{specials-uhDuRg8H.mjs → specials-Cye93-uo.mjs} +1 -1
  90. package/dist/{string-CsNsm_65.d.cts → string-BhaQOeKm.d.mts} +2 -2
  91. package/dist/{string-CBAbxaG1.d.mts → string-DN4hbA7H.d.cts} +2 -2
  92. package/dist/stylog.cjs +9 -9
  93. package/dist/stylog.d.cts +2 -2
  94. package/dist/stylog.d.mts +2 -2
  95. package/dist/stylog.mjs +9 -9
  96. package/dist/types/array.d.cts +1 -1
  97. package/dist/types/array.d.mts +1 -1
  98. package/dist/types/colors.d.cts +1 -1
  99. package/dist/types/colors.d.mts +1 -1
  100. package/dist/types/converter.d.cts +1 -1
  101. package/dist/types/converter.d.mts +1 -1
  102. package/dist/types/form.d.cts +1 -1
  103. package/dist/types/form.d.mts +1 -1
  104. package/dist/types/hash.d.cts +1 -1
  105. package/dist/types/hash.d.mts +1 -1
  106. package/dist/types/http-status.d.cts +1 -1
  107. package/dist/types/http-status.d.mts +1 -1
  108. package/dist/types/index.d.cts +1 -1
  109. package/dist/types/index.d.mts +1 -1
  110. package/dist/types/number.d.cts +1 -1
  111. package/dist/types/number.d.mts +1 -1
  112. package/dist/types/object.d.cts +1 -1
  113. package/dist/types/object.d.mts +1 -1
  114. package/dist/types/pluralizer.d.cts +1 -1
  115. package/dist/types/pluralizer.d.mts +1 -1
  116. package/dist/types/string.d.cts +1 -1
  117. package/dist/types/string.d.mts +1 -1
  118. package/dist/types/stylog.d.cts +1 -1
  119. package/dist/types/stylog.d.mts +1 -1
  120. package/dist/types/utils.d.cts +1 -1
  121. package/dist/types/utils.d.mts +1 -1
  122. package/dist/{utilities-m5yFKqLd.mjs → utilities-B9axOvOX.mjs} +3 -3
  123. package/dist/{utilities-CLUmdQeV.cjs → utilities-CzyXCRHM.cjs} +3 -3
  124. package/dist/{utils-DLFRgXUC.cjs → utils-B1BHomba.cjs} +6 -6
  125. package/dist/{utils-ClW9LA6f.mjs → utils-BCytS67y.mjs} +6 -6
  126. package/dist/verbalizer.cjs +3 -3
  127. package/dist/verbalizer.d.cts +2 -2
  128. package/dist/verbalizer.d.mts +2 -2
  129. package/dist/verbalizer.mjs +3 -3
  130. package/package.json +2 -3
  131. /package/dist/{constants-2gAw23_7.mjs → constants-B0zJiNqH.mjs} +0 -0
  132. /package/dist/{constants-DqwnkJ_d.cjs → constants-B3nc8psr.cjs} +0 -0
  133. /package/dist/{constants-X5hm1UtB.mjs → constants-BLAcLxOu.mjs} +0 -0
  134. /package/dist/{constants-BxN9l5el.cjs → constants-BOs8tjzp.cjs} +0 -0
  135. /package/dist/{constants-eNd-iYsV.mjs → constants-ByLTHWQm.mjs} +0 -0
  136. /package/dist/{constants-DQYeCjlx.cjs → constants-C4RW7Lei.cjs} +0 -0
  137. /package/dist/{constants-B34K0QPi.d.cts → constants-C7wERz5m.d.cts} +0 -0
  138. /package/dist/{constants-Deeie-iH.d.mts → constants-C7wERz5m.d.mts} +0 -0
  139. /package/dist/{constants-DpTG9RP6.d.mts → constants-D8RzBjsL.d.cts} +0 -0
  140. /package/dist/{constants-VcRtQu0K.d.cts → constants-D8RzBjsL.d.mts} +0 -0
  141. /package/dist/{constants-DAfRxaa8.mjs → constants-DCZL77t-.mjs} +0 -0
  142. /package/dist/{constants-BWT-810U.cjs → constants-DIBRCBIP.cjs} +0 -0
  143. /package/dist/{constants-CLS_bgKD.d.mts → constants-DNIXgBkz.d.cts} +0 -0
  144. /package/dist/{constants-qm8FafmD.d.cts → constants-DNIXgBkz.d.mts} +0 -0
  145. /package/dist/{constants-DvRUY_FY.cjs → constants-D_HkIg02.cjs} +0 -0
  146. /package/dist/{constants-BIBDKY1u.cjs → constants-ZnFGKd7G.cjs} +0 -0
  147. /package/dist/{constants-BwbHnXlM.mjs → constants-ZyfpysiQ.mjs} +0 -0
  148. /package/dist/{constants-D73iFu8g.mjs → constants-rNhoy4DH.mjs} +0 -0
  149. /package/dist/{countries-CIpmtEzV.cjs → countries-C0x58zVg.cjs} +0 -0
  150. /package/dist/{countries-Cy0xiqS3.mjs → countries-CMxHxKiK.mjs} +0 -0
  151. /package/dist/{css-colors-DfUW3nTR.mjs → css-colors-B-y4TmeC.mjs} +0 -0
  152. /package/dist/{css-colors-CXCDqQbG.cjs → css-colors-DC7oZ46Y.cjs} +0 -0
  153. /package/dist/{css-colors-Bx947Ng3.d.cts → css-colors-Dqz6Bfnp.d.cts} +0 -0
  154. /package/dist/{css-colors-CXTp1vvy.d.mts → css-colors-Dqz6Bfnp.d.mts} +0 -0
  155. /package/dist/{primitives-B26uZolQ.cjs → primitives-CBGICrDR.cjs} +0 -0
  156. /package/dist/{primitives-KsFUp3kQ.mjs → primitives-Djsevc69.mjs} +0 -0
  157. /package/dist/{timezone-Beh9IGpw.cjs → timezone-CSz7R0L6.cjs} +0 -0
  158. /package/dist/{timezone-B2OYK6Fh.mjs → timezone-avZ4TvDx.mjs} +0 -0
package/README.md ADDED
@@ -0,0 +1,409 @@
1
+ # Toolbox X
2
+
3
+ > “I solve problems you face daily”
4
+
5
+ <p>
6
+ <!-- Package Info -->
7
+ <a href="https://www.npmjs.com/package/toolbox-x" aria-label="NPM Downloads">
8
+ <img src="https://img.shields.io/npm/dm/toolbox-x.svg?label=DOWNLOADS&style=flat&color=red&logo=npm" alt="Downloads" />
9
+ </a>
10
+ <a href="https://www.npmjs.com/package/toolbox-x" aria-label="Latest Version">
11
+ <img src="https://img.shields.io/npm/v/toolbox-x.svg?label=NPM&style=flat&color=teal&logo=npm" alt="Latest Version" />
12
+ </a>
13
+ <a href="https://bundlejs.com/?q=toolbox-x" aria-label="Bundle Size">
14
+ <img src="https://img.shields.io/bundlejs/size/toolbox-x?label=Bundle%20Size&style=flat&color=blue&logo=npm" alt="Bundle Size" />
15
+ </a>
16
+
17
+ <!-- Project Metadata -->
18
+ <a href="https://github.com/nazmul-nhb/toolbox-x" aria-label="TypeScript">
19
+ <img src="https://img.shields.io/badge/BUILT%20with-TypeScript-3178C6?style=flat&logo=typescript&logoColor=blue" alt="Built with TypeScript" />
20
+ </a>
21
+ <a href="https://github.com/nazmul-nhb/toolbox-x/actions" aria-label="Build Status">
22
+ <img src="https://img.shields.io/github/actions/workflow/status/nazmul-nhb/toolbox-x/publish.yml?label=BUILD%20%26%20PUBLISH&style=flat&logo=github" alt="Build Status" />
23
+ </a>
24
+ <a href="https://github.com/nazmul-nhb/toolbox-x" aria-label="Project Status">
25
+ <img src="https://img.shields.io/badge/STATUS-maintained-brightgreen?style=flat&logo=git" alt="Maintained" />
26
+ </a>
27
+ <a href="https://github.com/nazmul-nhb/toolbox-x/commits/main" aria-label="Last Commit">
28
+ <img src="https://img.shields.io/github/last-commit/nazmul-nhb/toolbox-x?style=flat&label=LAST%20COMMIT&logo=git" alt="Last Commit" />
29
+ </a>
30
+
31
+ <!-- GitHub Meta -->
32
+ <a href="https://github.com/nazmul-nhb/toolbox-x/stargazers" aria-label="GitHub Stars">
33
+ <img src="https://img.shields.io/github/stars/nazmul-nhb/toolbox-x?style=flat&label=STARS&logo=github" alt="GitHub stars" />
34
+ </a>
35
+ <a href="https://github.com/nazmul-nhb/toolbox-x/issues" aria-label="Open Issues">
36
+ <img src="https://img.shields.io/github/issues/nazmul-nhb/toolbox-x?style=flat&label=ISSUES&logo=github" alt="Open Issues" />
37
+ </a>
38
+ <a href="https://github.com/nazmul-nhb/toolbox-x/pulls" aria-label="Open Pull Requests">
39
+ <img src="https://img.shields.io/github/issues-pr/nazmul-nhb/toolbox-x?style=flat&label=PRs&logo=github" alt="Pull Requests" />
40
+ </a>
41
+
42
+ <!-- License Info -->
43
+ <a href="https://www.npmjs.com/package/toolbox-x" aria-label="License">
44
+ <img src="https://img.shields.io/npm/l/toolbox-x.svg?label=LICENSE&style=flat&color=orange&logo=open-source-initiative" alt="License" />
45
+ </a>
46
+ </p>
47
+
48
+ ## JavaScript/TypeScript Utility Library
49
+
50
+ **NHB Toolbox** provides battle-tested utilities for professional JavaScript/TypeScript development. Carefully crafted to solve common challenges with elegant, production-ready solutions:
51
+
52
+ - **Helper Functions & Classes**: Reusable solutions for everyday tasks
53
+ - **Type Guards & Predicates**: Runtime safety with perfect type inference
54
+ - **Validation Utilities**: Robust data validation patterns
55
+ - **Zero Dependencies**: Framework-agnostic implementation using only native TS/JS with 0 external package
56
+
57
+ > [Explore Full Documentation →](https://toolbox-x.nazmul-nhb.dev/)
58
+
59
+ ---
60
+
61
+ ## Installation
62
+
63
+ Choose your preferred package manager:
64
+
65
+ ```shell
66
+ npm i toolbox-x
67
+ ```
68
+
69
+ ```shell
70
+ pnpm add toolbox-x
71
+ ```
72
+
73
+ ```shell
74
+ yarn add toolbox-x
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Changelog
80
+
81
+ See [Changelog](CHANGELOG.md) for recent updates.
82
+
83
+ ---
84
+
85
+ ## Key Features
86
+
87
+ - **Type-Safe Utilities**:Fully typed for perfect TypeScript integration with strict type checking
88
+ - **Modular Design**: Tree-shaking friendly – import only what you need with zero bloat
89
+ - **Zero Dependencies**: No external dependencies - works with any JS/TS framework
90
+ - **IDE Support**: Full type hints with JSDoc-powered API references in your editor
91
+ - **Comprehensive Documentation**: Learn with real-world use cases on [documentation site](https://toolbox-x.nazmul-nhb.dev/)
92
+ - **Battle-Tested**: Reliable utilities refined through real-world production use
93
+ - **Optimized for Production**: Focused on clean, efficient implementations
94
+
95
+ ---
96
+
97
+ ## Signature Utilities
98
+
99
+ ### 🎨 Professional Color Manipulation
100
+
101
+ **`Color`** - Convert between color formats, generate palettes, check accessibility contrast, and perform advanced color math with perfect type safety.
102
+
103
+ ```typescript
104
+ const blue = new Color('#0000ff');
105
+ const darkerBlue = blue.applyDarkness(20); // 20% darker
106
+ console.log(darkerBlue.hsl); // "hsl(240, 100%, 40%)" (was 50%)
107
+ ```
108
+
109
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/classes/Color)
110
+
111
+ ---
112
+
113
+ ### 🔍 Optimized Array Search
114
+
115
+ **`Finder`** - Blazing-fast array searching with binary search, fuzzy matching, and smart caching. Perfect for large datasets.
116
+
117
+ ```typescript
118
+ const productFinder = new Finder(products);
119
+
120
+ const laptop = productFinder.findOne('laptop', 'category', {
121
+ fuzzy: true,
122
+ caseInsensitive: false,
123
+ });
124
+ ```
125
+
126
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/classes/Finder)
127
+
128
+ ---
129
+
130
+ ### 🆔 Random ID Generation
131
+
132
+ **`generateRandomID`** - Enterprise-grade unique ID generation with prefixes, timestamps, and formatting.
133
+
134
+ ```typescript
135
+ generateRandomID({
136
+ prefix: 'user',
137
+ timeStamp: true,
138
+ length: 12,
139
+ caseOption: 'upper',
140
+ }); // "USER-171234567890-AB3C4D5E6F7G"
141
+ ```
142
+
143
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/string/generateRandomID)
144
+
145
+ ---
146
+
147
+ ### 🔢 Pluralize Strings and More
148
+
149
+ **`pluralizer`** - Handles English word pluralization and singularization with support for irregular forms and uncountable nouns.
150
+
151
+ ```ts
152
+ import { pluralizer } from 'toolbox-x';
153
+
154
+ pluralizer.pluralize('child'); // "children"
155
+ pluralizer.pluralize('category', { count: 3 }); // "categories"
156
+ pluralizer.pluralize('child', { count: 1, inclusive: true }); // "1 child"
157
+
158
+ pluralizer.toSingular('geese'); // "goose"
159
+ pluralizer.toSingular('children'); // "child"
160
+
161
+ pluralizer.isPlural('children'); // true
162
+ pluralizer.isSingular('child'); // true
163
+ pluralizer.isPlural('fish'); // true (uncountable)
164
+ ```
165
+
166
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/string/pluralizer)
167
+
168
+ ---
169
+
170
+ ### 🎨 Color System Utilities
171
+
172
+ **`getColorForInitial`** - Deterministic color mapping system for consistent UI theming
173
+
174
+ ```typescript
175
+ // Get color palette for user avatars
176
+ getColorForInitial(['Alice', 'Bob', 'Charlie']);
177
+ // ['#00094C', '#00376E', '#005600']
178
+
179
+ getColorForInitial('Banana', 50); // '#00376E80' (50% opacity)
180
+ ```
181
+
182
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/color/getColorForInitial)
183
+
184
+ ---
185
+
186
+ ### 📄 FormData Preparation
187
+
188
+ **`createFormData`** - Convert JavaScript objects into `FormData` with extensive configuration options for handling nested structures, files, and data transformations.
189
+
190
+ ```typescript
191
+ import { createFormData } from 'toolbox-x';
192
+
193
+ const formData = createFormData({
194
+ user: {
195
+ name: ' John Doe ',
196
+ age: 30,
197
+ preferences: { theme: 'dark' }
198
+ },
199
+ files: [file1, file2]
200
+ }, {
201
+ trimStrings: true,
202
+ lowerCaseValues: ['user.name'],
203
+ dotNotateNested: ['user.preferences'],
204
+ breakArray: ['files']
205
+ });
206
+
207
+ // Resulting FormData:
208
+ // user.name=john doe
209
+ // user.age=30
210
+ // user.preferences.theme=dark
211
+ // files[0]=[File1]
212
+ // files[1]=[File2]
213
+ ```
214
+
215
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/form/createFormData)
216
+
217
+ ---
218
+
219
+ ### 🛡️ Data Sanitization
220
+
221
+ **`sanitizeData`** - Clean and normalize strings/objects by trimming whitespace, removing empty values, and applying customizable filters.
222
+
223
+ ```typescript
224
+ const user = {
225
+ name: ' John Doe ',
226
+ age: null,
227
+ address: { city: ' NYC ', zip: '' },
228
+ tags: [],
229
+ };
230
+
231
+ sanitizeData(user, { ignoreNullish: true, ignoreEmpty: true });
232
+ // Returns { name: "John Doe", address: { city: "NYC" } } with exact input type which may cause issue when accessing missing properties
233
+
234
+ sanitizeData(user, { ignoreNullish: true, ignoreEmpty: true }, 'partial');
235
+ // Return type: $DeepPartial<typeof user> safe property access by making all the properties (nested objects/arrays) optional
236
+ // Returns { name: "John Doe", address: { city: "NYC" } }
237
+ ```
238
+
239
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/object/sanitizeData)
240
+
241
+ ---
242
+
243
+ ### 🔄 JSON Hydration
244
+
245
+ **`parseJSON`** - Bulletproof JSON parsing with primitive conversion
246
+
247
+ ```typescript
248
+ parseJSON('{"value":"42"}'); // { value: 42 } (auto-converts numbers)
249
+ ```
250
+
251
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/parseJSON)
252
+
253
+ ---
254
+
255
+ ### 🔢 Number to Words
256
+
257
+ **`numberToWords`** - Convert numbers to human-readable words (supports up to 100 quintillion).
258
+
259
+ ```typescript
260
+ numberToWords(125); // "one hundred twenty-five"
261
+ ```
262
+
263
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/number/numberToWords)
264
+
265
+ ---
266
+
267
+ ### 🔢 Advanced Number Operations
268
+
269
+ **`getNumbersInRange`** - Generate intelligent number sequences with prime, even/odd, and custom filtering capabilities
270
+
271
+ ```typescript
272
+ // Get primes between 10-30 as formatted string
273
+ getNumbersInRange('prime', { min: 10, max: 30, getAsString: true });
274
+ // "11, 13, 17, 19, 23, 29"
275
+ ```
276
+
277
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/number/getNumbersInRange)
278
+
279
+ **`calculatePercentage`** - Swiss Army knife for percentage calculations with 7 specialized modes
280
+
281
+ ```typescript
282
+ // Calculate percentage change
283
+ calculatePercentage({
284
+ mode: 'get-change-percent',
285
+ oldValue: 100,
286
+ newValue: 150,
287
+ }); // 50 (50% increase)
288
+ ```
289
+
290
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/number/calculatePercentage)
291
+
292
+ ---
293
+
294
+ ### 🔄 Extract Updated Fields
295
+
296
+ **`extractUpdatedFields`** - Detect exactly what changed between two objects (including deep nested changes).
297
+
298
+ ```typescript
299
+ const dbRecord = { id: 1, content: 'Hello', meta: { views: 0 } };
300
+ const update = { content: 'Hello', meta: { views: 1 } };
301
+ extractUpdatedFields(dbRecord, update);
302
+ // { meta: { views: 1 } }
303
+ ```
304
+
305
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/object/extractUpdatedFields)
306
+
307
+ ---
308
+
309
+ ### 🎨 Style Console Output(s)
310
+
311
+ **`Stylog`** - `Chalk`-like minimal utility to style console output(s) in both Node.js & Browser environment(s) (supports named CSS colors).
312
+
313
+ ```typescript
314
+ // Basic coloring
315
+ Stylog.error.log('Error message');
316
+ Stylog.success.log('Success message');
317
+ Stylog.info.log('Info message');
318
+ Stylog.whitesmoke.log('I am White!');
319
+
320
+ // Multiple styles
321
+ Stylog.blue.bold.underline.log('I am Bold Underlined Blue!');
322
+
323
+ // With object stringification
324
+ Stylog.magenta.italic.log({ data: 'value' }, true);
325
+ ```
326
+
327
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/stylog)
328
+
329
+ ---
330
+
331
+ ### ⚡ Performance Optimizers
332
+
333
+ **`throttleAction`** - Precision control for high-frequency events
334
+
335
+ ```typescript
336
+ // Smooth scroll handling
337
+ throttleAction(updateScrollPosition, 100);
338
+ ```
339
+
340
+ [Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/throttleAction)
341
+
342
+ **`debounceAction`** - Intelligent delay for expensive operations
343
+
344
+ ```typescript
345
+ // Search-as-you-type
346
+ debounceAction(fetchResults, 300);
347
+ ```
348
+
349
+ [Full Documentation →](https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/debounceAction)
350
+
351
+ > These utilities represent just a portion of the comprehensive `toolbox-x`. Each is designed with production-grade reliability and developer experience in mind. Explore more in the [full documentation](https://toolbox-x.nazmul-nhb.dev). All the utilities and classes are categorized.
352
+
353
+ ---
354
+
355
+ ## 🔗 Related Packages
356
+
357
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
358
+ <a target="_blank" href="https://www.npmjs.com/package/chronos-date">
359
+ <img src="https://img.shields.io/badge/Chronos_Date-chronos-date-blue" alt="bn-calendar" />
360
+ </a>
361
+ </div>
362
+
363
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
364
+ <a target="_blank" href="https://www.npmjs.com/package/bn-calendar">
365
+ <img src="https://img.shields.io/badge/Bangla_Calendar-bn-calendar-blue" alt="bn-calendar" />
366
+ </a>
367
+ </div>
368
+
369
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
370
+ <a target="_blank" href="https://www.npmjs.com/package/nhb-hooks">
371
+ <img src="https://img.shields.io/badge/React_Hooks-nhb--hooks-blue" alt="nhb-hooks" />
372
+ </a>
373
+ </div>
374
+
375
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
376
+ <a target="_blank" href="https://www.npmjs.com/package/locality-idb">
377
+ <img src="https://img.shields.io/badge/IndexedDB_ORM-locality--idb-darkviolet" alt="locality-idb" />
378
+ </a>
379
+ </div>
380
+
381
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
382
+ <a target="_blank" href="https://www.npmjs.com/package/nhb-scripts">
383
+ <img src="https://img.shields.io/badge/Development_Scripts-nhb--scripts-red" alt="nhb-scripts" />
384
+ </a>
385
+ </div>
386
+
387
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
388
+ <a target="_blank" href="https://www.npmjs.com/package/nhb-express">
389
+ <img src="https://img.shields.io/badge/Express_Server_Scaffolder-nhb--express-orange" alt="nhb-express" />
390
+ </a>
391
+ </div>
392
+
393
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
394
+ <a target="_blank" href="https://www.npmjs.com/package/nhb-anagram-generator">
395
+ <img src="https://img.shields.io/badge/Anagram_Generator-nhb--anagram--generator-teal" alt="nhb-anagram-generator" />
396
+ </a>
397
+ </div>
398
+
399
+ ---
400
+
401
+ ## License
402
+
403
+ This project is licensed under the [Apache License 2.0](LICENSE) with the following additional requirement:
404
+
405
+ **Additional Requirement:**
406
+
407
+ > Any fork, derivative work, or redistribution of this project must include clear attribution to [**Nazmul Hassan**](https://github.com/nazmul-nhb) in both the source code and any publicly available documentation.
408
+
409
+ You are free to use, modify, and distribute this project under the terms of the Apache 2.0 License, provided that appropriate credit is given.
@@ -14,8 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { $ as Maybe, V as Branded, rn as Percent } from "./object-Blq0Amdv.cjs";
18
- import { t as CSS_COLORS } from "./css-colors-Bx947Ng3.cjs";
17
+ import { $ as Maybe, V as Branded, rn as Percent } from "./object-NOZEWHcC.cjs";
18
+ import { t as CSS_COLORS } from "./css-colors-Dqz6Bfnp.cjs";
19
19
 
20
20
  //#region src/types/colors.d.ts
21
21
  /** - A string, number for generating color. */
@@ -14,8 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { $ as Maybe, V as Branded, rn as Percent } from "./object-B0TV3eHx.mjs";
18
- import { t as CSS_COLORS } from "./css-colors-CXTp1vvy.mjs";
17
+ import { $ as Maybe, V as Branded, rn as Percent } from "./object-NOZEWHcC.mjs";
18
+ import { t as CSS_COLORS } from "./css-colors-Dqz6Bfnp.mjs";
19
19
 
20
20
  //#region src/types/colors.d.ts
21
21
  /** - A string, number for generating color. */
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { s as CSSColor } from "./Color-B3mgF9Dh.cjs";
17
+ import { s as CSSColor } from "./Color-BrtYYm8M.mjs";
18
18
 
19
19
  //#region src/stylog/constants.d.ts
20
20
  /** Records of ANSI-16 colors with values */
@@ -88,7 +88,7 @@ type StylogChain = LogStyler & { [K in Styles]: StylogChain };
88
88
  *
89
89
  * @remarks
90
90
  * - Allows chaining of style methods or initializing with predefined styles.
91
- * - For fluent, chainable styling with zero configuration use {@link https://toolbox.nazmul-nhb.dev/docs/utilities/misc/stylog Stylog} (`LogStyler` chainable wrapper).
91
+ * - For fluent, chainable styling with zero configuration use {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/stylog Stylog} (`LogStyler` chainable wrapper).
92
92
  *
93
93
  * @example
94
94
  * const styled = new LogStyler(['red', 'bold']);
@@ -185,7 +185,7 @@ declare class LogStyler {
185
185
  * @remarks
186
186
  * - This method is specifically designed for browser environments and returns a tuple containing the formatted string with `%c` placeholder and an array of CSS styles (`string[]`).
187
187
  * - Use this when you need direct access to the CSS styling for custom browser output.
188
- * - If you want to format with ANSI escape codes, consider using {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#toansiinput-stringify toANSI} method.
188
+ * - If you want to format with ANSI escape codes, consider using {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#toansiinput-stringify toANSI} method.
189
189
  *
190
190
  * @param input - Input to style before printing in the shell.
191
191
  * @param stringify - Whether to apply `JSON.stringify()` before styling. Defaults to `false`.
@@ -224,7 +224,7 @@ declare class LogStyler {
224
224
  *
225
225
  * @remarks
226
226
  * - This method returns ANSI-formatted strings suitable for environments that support ANSI escape codes (terminals, modern browser consoles, etc.).
227
- * - For unsupported browsers, consider using the {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#loginput-stringify log} method to print directly or {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#tocssinput-stringify toCSS} to get styled tuple `[format, cssList]` for Browser.
227
+ * - For unsupported browsers, consider using the {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#loginput-stringify log} method to print directly or {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#tocssinput-stringify toCSS} to get styled tuple `[format, cssList]` for Browser.
228
228
  *
229
229
  * @param input - Input to style before printing in the shell.
230
230
  * @param stringify - Whether to apply `JSON.stringify()` before styling. Defaults to `false`.
@@ -493,7 +493,7 @@ declare class LogStyler {
493
493
  * - In browsers, styles are applied using `CSS`; in `Node.js`, `ANSI` escape codes are used.
494
494
  * - When multiple styles of the same category are chained, the last one wins.
495
495
  * - Use `.log(value, stringify?)` to print; set `stringify` to `true` to serialize with `JSON.stringify`.
496
- * - If you need custom reusable style configurations, use {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler Stylog} class.
496
+ * - If you need custom reusable style configurations, use {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler Stylog} class.
497
497
  *
498
498
  * @example
499
499
  * // Simple color
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { s as CSSColor } from "./Color-D38Xrw65.mjs";
17
+ import { s as CSSColor } from "./Color-BK-IISGk.cjs";
18
18
 
19
19
  //#region src/stylog/constants.d.ts
20
20
  /** Records of ANSI-16 colors with values */
@@ -88,7 +88,7 @@ type StylogChain = LogStyler & { [K in Styles]: StylogChain };
88
88
  *
89
89
  * @remarks
90
90
  * - Allows chaining of style methods or initializing with predefined styles.
91
- * - For fluent, chainable styling with zero configuration use {@link https://toolbox.nazmul-nhb.dev/docs/utilities/misc/stylog Stylog} (`LogStyler` chainable wrapper).
91
+ * - For fluent, chainable styling with zero configuration use {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/misc/stylog Stylog} (`LogStyler` chainable wrapper).
92
92
  *
93
93
  * @example
94
94
  * const styled = new LogStyler(['red', 'bold']);
@@ -185,7 +185,7 @@ declare class LogStyler {
185
185
  * @remarks
186
186
  * - This method is specifically designed for browser environments and returns a tuple containing the formatted string with `%c` placeholder and an array of CSS styles (`string[]`).
187
187
  * - Use this when you need direct access to the CSS styling for custom browser output.
188
- * - If you want to format with ANSI escape codes, consider using {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#toansiinput-stringify toANSI} method.
188
+ * - If you want to format with ANSI escape codes, consider using {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#toansiinput-stringify toANSI} method.
189
189
  *
190
190
  * @param input - Input to style before printing in the shell.
191
191
  * @param stringify - Whether to apply `JSON.stringify()` before styling. Defaults to `false`.
@@ -224,7 +224,7 @@ declare class LogStyler {
224
224
  *
225
225
  * @remarks
226
226
  * - This method returns ANSI-formatted strings suitable for environments that support ANSI escape codes (terminals, modern browser consoles, etc.).
227
- * - For unsupported browsers, consider using the {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#loginput-stringify log} method to print directly or {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler#tocssinput-stringify toCSS} to get styled tuple `[format, cssList]` for Browser.
227
+ * - For unsupported browsers, consider using the {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#loginput-stringify log} method to print directly or {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler#tocssinput-stringify toCSS} to get styled tuple `[format, cssList]` for Browser.
228
228
  *
229
229
  * @param input - Input to style before printing in the shell.
230
230
  * @param stringify - Whether to apply `JSON.stringify()` before styling. Defaults to `false`.
@@ -493,7 +493,7 @@ declare class LogStyler {
493
493
  * - In browsers, styles are applied using `CSS`; in `Node.js`, `ANSI` escape codes are used.
494
494
  * - When multiple styles of the same category are chained, the last one wins.
495
495
  * - Use `.log(value, stringify?)` to print; set `stringify` to `true` to serialize with `JSON.stringify`.
496
- * - If you need custom reusable style configurations, use {@link https://toolbox.nazmul-nhb.dev/docs/classes/LogStyler Stylog} class.
496
+ * - If you need custom reusable style configurations, use {@link https://toolbox-x.nazmul-nhb.dev/docs/classes/LogStyler Stylog} class.
497
497
  *
498
498
  * @example
499
499
  * // Simple color
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { E as NestedPrimitiveKey, nt as NormalPrimitiveKey, y as GenericObject } from "./object-B0TV3eHx.mjs";
17
+ import { E as NestedPrimitiveKey, nt as NormalPrimitiveKey, y as GenericObject } from "./object-NOZEWHcC.cjs";
18
18
 
19
19
  //#region src/types/array.d.ts
20
20
  /** * Flatten Array or Wrap in Array */
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { E as NestedPrimitiveKey, nt as NormalPrimitiveKey, y as GenericObject } from "./object-Blq0Amdv.cjs";
17
+ import { E as NestedPrimitiveKey, nt as NormalPrimitiveKey, y as GenericObject } from "./object-NOZEWHcC.mjs";
18
18
 
19
19
  //#region src/types/array.d.ts
20
20
  /** * Flatten Array or Wrap in Array */
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { F as RandomIdOptions } from "./string-CsNsm_65.cjs";
17
+ import { F as RandomIdOptions } from "./string-BhaQOeKm.mjs";
18
18
 
19
19
  //#region src/string/basics.d.ts
20
20
  /**
@@ -31,8 +31,8 @@ declare function truncateString(str: string, maxLength: number): string;
31
31
  * @param options Configuration options for random ID generation.
32
32
  * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
33
33
  *
34
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
35
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
34
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
35
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
36
36
  *
37
37
  * @example
38
38
  * // Generate an ID with all default options
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { F as RandomIdOptions } from "./string-CBAbxaG1.mjs";
17
+ import { F as RandomIdOptions } from "./string-DN4hbA7H.cjs";
18
18
 
19
19
  //#region src/string/basics.d.ts
20
20
  /**
@@ -31,8 +31,8 @@ declare function truncateString(str: string, maxLength: number): string;
31
31
  * @param options Configuration options for random ID generation.
32
32
  * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
33
33
  *
34
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
35
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
34
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
35
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
36
36
  *
37
37
  * @example
38
38
  * // Generate an ID with all default options
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- const require_primitives = require('./primitives-B26uZolQ.cjs');
17
+ const require_primitives = require('./primitives-CBGICrDR.cjs');
18
18
 
19
19
  //#region src/string/basics.ts
20
20
  /**
@@ -37,8 +37,8 @@ function truncateString(str, maxLength) {
37
37
  * @param options Configuration options for random ID generation.
38
38
  * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
39
39
  *
40
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
41
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
40
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
41
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
42
42
  *
43
43
  * @example
44
44
  * // Generate an ID with all default options
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { a as isNonEmptyString } from "./primitives-KsFUp3kQ.mjs";
17
+ import { a as isNonEmptyString } from "./primitives-Djsevc69.mjs";
18
18
 
19
19
  //#region src/string/basics.ts
20
20
  /**
@@ -37,8 +37,8 @@ function truncateString(str, maxLength) {
37
37
  * @param options Configuration options for random ID generation.
38
38
  * @returns The generated ID string composed of the random alphanumeric string of specified length with optional `timeStamp`, `prefix`, and `suffix`, `caseOption` and `separator`.
39
39
  *
40
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
41
- * @see {@link https://toolbox.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
40
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/uuid uuid} for `uuid` generation
41
+ * @see {@link https://toolbox-x.nazmul-nhb.dev/docs/utilities/hash/randomHex randomHex} for random hexadecimal string generation
42
42
  *
43
43
  * @example
44
44
  * // Generate an ID with all default options
@@ -14,8 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { a as isNonEmptyString } from "./primitives-KsFUp3kQ.mjs";
18
- import { t as LOWERCASE } from "./constants-2gAw23_7.mjs";
17
+ import { a as isNonEmptyString } from "./primitives-Djsevc69.mjs";
18
+ import { t as LOWERCASE } from "./constants-B0zJiNqH.mjs";
19
19
 
20
20
  //#region src/string/case.ts
21
21
  /** Lowercase words set for fast lookup */
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { B as TitleCase, I as SentenceCase, L as SnakeCase, M as PascalSnakeCase, N as PathCase, T as DotCase, V as TrainCase, f as CamelCase, g as ConstantCase, j as PascalCase, k as KebabCase, m as CaseFormat, p as CapitalizeOptions, z as StringCaseOptions } from "./string-CsNsm_65.cjs";
17
+ import { B as TitleCase, I as SentenceCase, L as SnakeCase, M as PascalSnakeCase, N as PathCase, T as DotCase, V as TrainCase, f as CamelCase, g as ConstantCase, j as PascalCase, k as KebabCase, m as CaseFormat, p as CapitalizeOptions, z as StringCaseOptions } from "./string-DN4hbA7H.cjs";
18
18
 
19
19
  //#region src/string/case.d.ts
20
20
  /**
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { B as TitleCase, I as SentenceCase, L as SnakeCase, M as PascalSnakeCase, N as PathCase, T as DotCase, V as TrainCase, f as CamelCase, g as ConstantCase, j as PascalCase, k as KebabCase, m as CaseFormat, p as CapitalizeOptions, z as StringCaseOptions } from "./string-CBAbxaG1.mjs";
17
+ import { B as TitleCase, I as SentenceCase, L as SnakeCase, M as PascalSnakeCase, N as PathCase, T as DotCase, V as TrainCase, f as CamelCase, g as ConstantCase, j as PascalCase, k as KebabCase, m as CaseFormat, p as CapitalizeOptions, z as StringCaseOptions } from "./string-BhaQOeKm.mjs";
18
18
 
19
19
  //#region src/string/case.d.ts
20
20
  /**