@karbonjs/utils 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KarbonJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @karbonjs/utils
2
+
3
+ Lightweight utility functions for date, string, number formatting and more. Pure TypeScript, zero dependencies, works with any framework.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @karbonjs/utils
9
+ ```
10
+
11
+ ## Date
12
+
13
+ ```typescript
14
+ import { formatDate, formatDateTime, timeAgo, formatMonthYear, isToday, isPast } from '@karbonjs/utils'
15
+
16
+ formatDate('2026-03-15') // "15 mars 2026"
17
+ formatDateTime('2026-03-15T14:30:00') // "15 mars 2026 à 14:30"
18
+ timeAgo('2026-03-15T10:00:00') // "Il y a 5h"
19
+ formatMonthYear('2026-03-15') // "mars 2026"
20
+
21
+ // English locale
22
+ formatDate('2026-03-15', { locale: 'en-US' }) // "Mar 15, 2026"
23
+ timeAgo('2026-03-15', { locale: 'en' }) // "5h ago"
24
+ ```
25
+
26
+ ## String
27
+
28
+ ```typescript
29
+ import { truncate, slugify, capitalize, pluralize, stripHtml, initials, escapeHtml, camelCase, kebabCase } from '@karbonjs/utils'
30
+
31
+ truncate('Long text here...', 10) // "Long text ..."
32
+ slugify('Mon Super Article !') // "mon-super-article"
33
+ capitalize('hello') // "Hello"
34
+ pluralize(3, 'article') // "3 articles"
35
+ pluralize(1, 'article') // "1 article"
36
+ stripHtml('<p>Hello <b>world</b></p>') // "Hello world"
37
+ initials('John Doe') // "JO"
38
+ escapeHtml('<script>alert("xss")</script>') // "&lt;script&gt;..."
39
+ camelCase('my-variable') // "myVariable"
40
+ kebabCase('myVariable') // "my-variable"
41
+ ```
42
+
43
+ ## Number
44
+
45
+ ```typescript
46
+ import { formatSize, formatCount, clamp, formatPercent, formatPrice, randomInt } from '@karbonjs/utils'
47
+
48
+ formatSize(2_500_000) // "2.4 Mo"
49
+ formatSize(2_500_000, 'en') // "2.4 MB"
50
+ formatCount(12345) // "12 345"
51
+ clamp(150, 0, 100) // 100
52
+ formatPercent(0.856) // "85.6%"
53
+ formatPrice(29.99) // "29,99 €"
54
+ formatPrice(29.99, 'USD', 'en-US') // "$29.99"
55
+ randomInt(1, 10) // 7
56
+ ```
57
+
58
+ ## Timing
59
+
60
+ ```typescript
61
+ import { debounce, throttle } from '@karbonjs/utils'
62
+
63
+ const search = debounce(() => fetchResults(), 400)
64
+ const scroll = throttle(() => handleScroll(), 200)
65
+ ```
66
+
67
+ ## Cookies
68
+
69
+ ```typescript
70
+ import { setCookie, getCookie, deleteCookie } from '@karbonjs/utils'
71
+
72
+ setCookie('theme', 'dark', { days: 365 })
73
+ getCookie('theme') // "dark"
74
+ deleteCookie('theme')
75
+ ```
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,19 @@
1
+ export interface CookieOptions {
2
+ days?: number;
3
+ path?: string;
4
+ sameSite?: 'Strict' | 'Lax' | 'None';
5
+ secure?: boolean;
6
+ }
7
+ /**
8
+ * Set a client-side cookie.
9
+ */
10
+ export declare function setCookie(name: string, value: string, opts?: CookieOptions): void;
11
+ /**
12
+ * Get a client-side cookie value.
13
+ */
14
+ export declare function getCookie(name: string): string | null;
15
+ /**
16
+ * Delete a client-side cookie.
17
+ */
18
+ export declare function deleteCookie(name: string, opts?: CookieOptions): void;
19
+ //# sourceMappingURL=cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../src/cookie.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;IACpC,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAgBD;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,IAAI,CAKrF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUrD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,IAAI,CAGzE"}
package/dist/cookie.js ADDED
@@ -0,0 +1,50 @@
1
+ const IS_BROWSER = typeof document !== 'undefined';
2
+ const IS_SECURE = IS_BROWSER && window.location.protocol === 'https:';
3
+ function buildFlags(opts = {}) {
4
+ const path = opts.path ?? '/';
5
+ const sameSite = opts.sameSite ?? 'Strict';
6
+ const secure = opts.secure ?? (sameSite === 'None' ? true : IS_SECURE);
7
+ return `path=${path}; SameSite=${sameSite}${secure ? '; Secure' : ''}`;
8
+ }
9
+ /**
10
+ * Escape special regex characters in a string.
11
+ */
12
+ function escapeRegex(str) {
13
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
14
+ }
15
+ /**
16
+ * Set a client-side cookie.
17
+ */
18
+ export function setCookie(name, value, opts = {}) {
19
+ if (!IS_BROWSER)
20
+ return;
21
+ const days = opts.days ?? 30;
22
+ const expires = new Date(Date.now() + days * 864e5).toUTCString();
23
+ document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; ${buildFlags(opts)}`;
24
+ }
25
+ /**
26
+ * Get a client-side cookie value.
27
+ */
28
+ export function getCookie(name) {
29
+ if (!IS_BROWSER)
30
+ return null;
31
+ const escaped = escapeRegex(name);
32
+ const match = document.cookie.match(new RegExp(`(?:^|; )${escaped}=([^;]*)`));
33
+ if (!match)
34
+ return null;
35
+ try {
36
+ return decodeURIComponent(match[1]);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ /**
43
+ * Delete a client-side cookie.
44
+ */
45
+ export function deleteCookie(name, opts = {}) {
46
+ if (!IS_BROWSER)
47
+ return;
48
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; ${buildFlags(opts)}`;
49
+ }
50
+ //# sourceMappingURL=cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.js","sourceRoot":"","sources":["../src/cookie.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,WAAW,CAAA;AAClD,MAAM,SAAS,GAAG,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAA;AASrE,SAAS,UAAU,CAAC,OAAsB,EAAE;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAA;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACtE,OAAO,QAAQ,IAAI,cAAc,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AACxE,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,OAAsB,EAAE;IAC7E,IAAI,CAAC,UAAU;QAAE,OAAM;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;IAC5B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;IACjE,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,IAAI,kBAAkB,CAAC,KAAK,CAAC,aAAa,OAAO,KAAK,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;AACnG,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,WAAW,OAAO,UAAU,CAAC,CAAC,CAAA;IAC7E,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAsB,EAAE;IACjE,IAAI,CAAC,UAAU;QAAE,OAAM;IACvB,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,6CAA6C,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;AAC1F,CAAC"}
package/dist/date.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ export interface DateFormatOptions {
2
+ locale?: string;
3
+ }
4
+ /**
5
+ * Format a date as "14 mars 2026"
6
+ */
7
+ export declare function formatDate(d: string | Date, opts?: DateFormatOptions): string;
8
+ /**
9
+ * Format a date+time as "14 mars 2026 à 15:30"
10
+ */
11
+ export declare function formatDateTime(d: string | Date, opts?: DateFormatOptions): string;
12
+ /**
13
+ * Relative time: "Il y a 5 min", "Il y a 3j", "Il y a 2 mois"
14
+ * Supports French (default) and English.
15
+ */
16
+ export declare function timeAgo(dateStr: string | Date, opts?: DateFormatOptions): string;
17
+ /**
18
+ * Format as "mars 2026" — useful for "Member since..."
19
+ */
20
+ export declare function formatMonthYear(d: string | Date, opts?: DateFormatOptions): string;
21
+ /**
22
+ * Check if a date is today
23
+ */
24
+ export declare function isToday(d: string | Date): boolean;
25
+ /**
26
+ * Check if a date is in the past
27
+ */
28
+ export declare function isPast(d: string | Date): boolean;
29
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../src/date.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAUD;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAM7E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAIjF;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CA+BhF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAElF;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAIjD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEhD"}
package/dist/date.js ADDED
@@ -0,0 +1,88 @@
1
+ const DEFAULT_LOCALE = 'fr-FR';
2
+ function toDate(d) {
3
+ const date = new Date(d);
4
+ if (isNaN(date.getTime()))
5
+ return new Date();
6
+ return date;
7
+ }
8
+ /**
9
+ * Format a date as "14 mars 2026"
10
+ */
11
+ export function formatDate(d, opts) {
12
+ return toDate(d).toLocaleDateString(opts?.locale ?? DEFAULT_LOCALE, {
13
+ day: '2-digit',
14
+ month: 'short',
15
+ year: 'numeric',
16
+ });
17
+ }
18
+ /**
19
+ * Format a date+time as "14 mars 2026 à 15:30"
20
+ */
21
+ export function formatDateTime(d, opts) {
22
+ const locale = opts?.locale ?? DEFAULT_LOCALE;
23
+ const date = toDate(d);
24
+ return `${formatDate(date, opts)} à ${date.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' })}`;
25
+ }
26
+ /**
27
+ * Relative time: "Il y a 5 min", "Il y a 3j", "Il y a 2 mois"
28
+ * Supports French (default) and English.
29
+ */
30
+ export function timeAgo(dateStr, opts) {
31
+ const locale = opts?.locale ?? DEFAULT_LOCALE;
32
+ const fr = locale.startsWith('fr');
33
+ const date = toDate(dateStr);
34
+ const diff = Date.now() - date.getTime();
35
+ // Future date
36
+ if (diff < 0)
37
+ return fr ? "À l'instant" : 'Just now';
38
+ const minutes = Math.floor(diff / 60_000);
39
+ const hours = Math.floor(diff / 3_600_000);
40
+ const days = Math.floor(diff / 86_400_000);
41
+ const months = Math.floor(days / 30);
42
+ const years = Math.floor(months / 12);
43
+ if (fr) {
44
+ if (minutes < 1)
45
+ return "À l'instant";
46
+ if (minutes < 60)
47
+ return `Il y a ${minutes} min`;
48
+ if (hours < 24)
49
+ return `Il y a ${hours}h`;
50
+ if (days < 30)
51
+ return `Il y a ${days}j`;
52
+ if (months < 12)
53
+ return `Il y a ${months} mois`;
54
+ return `Il y a ${years} an${years > 1 ? 's' : ''}`;
55
+ }
56
+ if (minutes < 1)
57
+ return 'Just now';
58
+ if (minutes < 60)
59
+ return `${minutes}m ago`;
60
+ if (hours < 24)
61
+ return `${hours}h ago`;
62
+ if (days < 30)
63
+ return `${days}d ago`;
64
+ if (months < 12)
65
+ return `${months}mo ago`;
66
+ return `${years}y ago`;
67
+ }
68
+ /**
69
+ * Format as "mars 2026" — useful for "Member since..."
70
+ */
71
+ export function formatMonthYear(d, opts) {
72
+ return toDate(d).toLocaleDateString(opts?.locale ?? DEFAULT_LOCALE, { month: 'long', year: 'numeric' });
73
+ }
74
+ /**
75
+ * Check if a date is today
76
+ */
77
+ export function isToday(d) {
78
+ const date = toDate(d);
79
+ const now = new Date();
80
+ return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate();
81
+ }
82
+ /**
83
+ * Check if a date is in the past
84
+ */
85
+ export function isPast(d) {
86
+ return toDate(d).getTime() < Date.now();
87
+ }
88
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../src/date.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=date.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.test.d.ts","sourceRoot":"","sources":["../src/date.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { formatDate, formatDateTime, timeAgo, formatMonthYear, isToday, isPast } from './date';
3
+ describe('formatDate', () => {
4
+ it('formats date in French by default', () => {
5
+ const result = formatDate('2026-03-14');
6
+ expect(result).toMatch(/14/);
7
+ expect(result).toMatch(/2026/);
8
+ });
9
+ it('accepts locale override', () => {
10
+ const result = formatDate('2026-03-14', { locale: 'en-US' });
11
+ expect(result).toMatch(/14/);
12
+ expect(result).toMatch(/2026/);
13
+ });
14
+ });
15
+ describe('formatDateTime', () => {
16
+ it('includes time', () => {
17
+ const result = formatDateTime('2026-03-14T15:30:00');
18
+ expect(result).toMatch(/15/);
19
+ expect(result).toMatch(/30/);
20
+ });
21
+ });
22
+ describe('timeAgo', () => {
23
+ it('returns "À l\'instant" for recent dates in French', () => {
24
+ expect(timeAgo(new Date().toISOString())).toBe("À l'instant");
25
+ });
26
+ it('returns "Just now" for English locale', () => {
27
+ expect(timeAgo(new Date().toISOString(), { locale: 'en-US' })).toBe('Just now');
28
+ });
29
+ });
30
+ describe('formatMonthYear', () => {
31
+ it('formats month and year in French', () => {
32
+ const result = formatMonthYear('2026-03-14');
33
+ expect(result).toMatch(/2026/);
34
+ });
35
+ });
36
+ describe('isToday', () => {
37
+ it('returns true for today', () => {
38
+ expect(isToday(new Date())).toBe(true);
39
+ });
40
+ it('returns false for yesterday', () => {
41
+ const yesterday = new Date(Date.now() - 86_400_000);
42
+ expect(isToday(yesterday)).toBe(false);
43
+ });
44
+ });
45
+ describe('isPast', () => {
46
+ it('returns true for past date', () => {
47
+ expect(isPast('2020-01-01')).toBe(true);
48
+ });
49
+ it('returns false for future date', () => {
50
+ expect(isPast('2099-01-01')).toBe(false);
51
+ });
52
+ });
53
+ //# sourceMappingURL=date.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.test.js","sourceRoot":"","sources":["../src/date.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE9F,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE;QACvB,MAAM,MAAM,GAAG,cAAc,CAAC,qBAAqB,CAAC,CAAA;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACjF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAA;QACnD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,22 @@
1
+ export interface Cancelable {
2
+ cancel: () => void;
3
+ }
4
+ /**
5
+ * Create a debounced version of a function.
6
+ * The call is delayed by `ms` milliseconds; any new call resets the timer.
7
+ * Call `.cancel()` to clear pending execution.
8
+ *
9
+ * ```ts
10
+ * const debouncedSearch = debounce(() => loadItems(), 400)
11
+ * input.addEventListener('input', debouncedSearch)
12
+ * // cleanup: debouncedSearch.cancel()
13
+ * ```
14
+ */
15
+ export declare function debounce<T extends (...args: any[]) => void>(fn: T, ms?: number): T & Cancelable;
16
+ /**
17
+ * Create a throttled version of a function.
18
+ * The function is called at most once every `ms` milliseconds.
19
+ * Call `.cancel()` to reset the throttle.
20
+ */
21
+ export declare function throttle<T extends (...args: any[]) => void>(fn: T, ms?: number): T & Cancelable;
22
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../src/debounce.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAM,GAAG,CAAC,GAAG,UAAU,CAQ5F;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAM,GAAG,CAAC,GAAG,UAAU,CAW5F"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Create a debounced version of a function.
3
+ * The call is delayed by `ms` milliseconds; any new call resets the timer.
4
+ * Call `.cancel()` to clear pending execution.
5
+ *
6
+ * ```ts
7
+ * const debouncedSearch = debounce(() => loadItems(), 400)
8
+ * input.addEventListener('input', debouncedSearch)
9
+ * // cleanup: debouncedSearch.cancel()
10
+ * ```
11
+ */
12
+ export function debounce(fn, ms = 400) {
13
+ let timer = null;
14
+ const debounced = ((...args) => {
15
+ if (timer)
16
+ clearTimeout(timer);
17
+ timer = setTimeout(() => { timer = null; fn(...args); }, ms);
18
+ });
19
+ debounced.cancel = () => { if (timer) {
20
+ clearTimeout(timer);
21
+ timer = null;
22
+ } };
23
+ return debounced;
24
+ }
25
+ /**
26
+ * Create a throttled version of a function.
27
+ * The function is called at most once every `ms` milliseconds.
28
+ * Call `.cancel()` to reset the throttle.
29
+ */
30
+ export function throttle(fn, ms = 200) {
31
+ let last = 0;
32
+ const throttled = ((...args) => {
33
+ const now = Date.now();
34
+ if (now - last >= ms) {
35
+ last = now;
36
+ fn(...args);
37
+ }
38
+ });
39
+ throttled.cancel = () => { last = 0; };
40
+ return throttled;
41
+ }
42
+ //# sourceMappingURL=debounce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.js","sourceRoot":"","sources":["../src/debounce.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAqC,EAAK,EAAE,EAAE,GAAG,GAAG;IAC1E,IAAI,KAAK,GAAyC,IAAI,CAAA;IACtD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,IAAW,EAAE,EAAE;QACpC,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAA;QAC9B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC7D,CAAC,CAA8B,CAAA;IAC/B,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,KAAK,EAAE,CAAC;QAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAAC,KAAK,GAAG,IAAI,CAAA;IAAC,CAAC,CAAC,CAAC,CAAA;IAC7E,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAqC,EAAK,EAAE,EAAE,GAAG,GAAG;IAC1E,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,IAAW,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YACrB,IAAI,GAAG,GAAG,CAAA;YACV,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;QACb,CAAC;IACH,CAAC,CAA8B,CAAA;IAC/B,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,CAAA,CAAC,CAAC,CAAA;IACrC,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debounce.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.d.ts","sourceRoot":"","sources":["../src/debounce.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { debounce, throttle } from './debounce';
3
+ describe('debounce', () => {
4
+ it('delays execution', async () => {
5
+ vi.useFakeTimers();
6
+ const fn = vi.fn();
7
+ const debounced = debounce(fn, 100);
8
+ debounced();
9
+ expect(fn).not.toHaveBeenCalled();
10
+ vi.advanceTimersByTime(100);
11
+ expect(fn).toHaveBeenCalledTimes(1);
12
+ vi.useRealTimers();
13
+ });
14
+ it('resets timer on subsequent calls', () => {
15
+ vi.useFakeTimers();
16
+ const fn = vi.fn();
17
+ const debounced = debounce(fn, 100);
18
+ debounced();
19
+ vi.advanceTimersByTime(50);
20
+ debounced();
21
+ vi.advanceTimersByTime(50);
22
+ expect(fn).not.toHaveBeenCalled();
23
+ vi.advanceTimersByTime(50);
24
+ expect(fn).toHaveBeenCalledTimes(1);
25
+ vi.useRealTimers();
26
+ });
27
+ });
28
+ describe('throttle', () => {
29
+ it('executes immediately on first call', () => {
30
+ const fn = vi.fn();
31
+ const throttled = throttle(fn, 100);
32
+ throttled();
33
+ expect(fn).toHaveBeenCalledTimes(1);
34
+ });
35
+ it('blocks subsequent calls within interval', () => {
36
+ vi.useFakeTimers();
37
+ const fn = vi.fn();
38
+ const throttled = throttle(fn, 100);
39
+ throttled();
40
+ throttled();
41
+ throttled();
42
+ expect(fn).toHaveBeenCalledTimes(1);
43
+ vi.advanceTimersByTime(100);
44
+ throttled();
45
+ expect(fn).toHaveBeenCalledTimes(2);
46
+ vi.useRealTimers();
47
+ });
48
+ });
49
+ //# sourceMappingURL=debounce.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.js","sourceRoot":"","sources":["../src/debounce.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE/C,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAEnC,SAAS,EAAE,CAAA;QACX,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;QAEjC,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAEnC,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAEnC,SAAS,EAAE,CAAA;QACX,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAC1B,SAAS,EAAE,CAAA;QACX,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAC1B,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;QAEjC,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;QAC1B,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAEnC,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QACnC,SAAS,EAAE,CAAA;QACX,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAEnC,SAAS,EAAE,CAAA;QACX,SAAS,EAAE,CAAA;QACX,SAAS,EAAE,CAAA;QACX,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAEnC,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAA;QAC3B,SAAS,EAAE,CAAA;QACX,MAAM,CAAC,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAEnC,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ export { formatDate, formatDateTime, timeAgo, formatMonthYear, isToday, isPast } from './date';
2
+ export type { DateFormatOptions } from './date';
3
+ export { truncate, slugify, capitalize, pluralize, stripHtml, initials, hashColorIndex, escapeHtml, camelCase, kebabCase, isImage } from './string';
4
+ export { formatSize, formatCount, clamp, formatPercent, formatPrice, randomInt } from './number';
5
+ export { debounce, throttle } from './debounce';
6
+ export type { Cancelable } from './debounce';
7
+ export { setCookie, getCookie, deleteCookie } from './cookie';
8
+ export type { CookieOptions } from './cookie';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC9F,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE/C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEnJ,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEhG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC/C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC7D,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { formatDate, formatDateTime, timeAgo, formatMonthYear, isToday, isPast } from './date';
2
+ export { truncate, slugify, capitalize, pluralize, stripHtml, initials, hashColorIndex, escapeHtml, camelCase, kebabCase, isImage } from './string';
3
+ export { formatSize, formatCount, clamp, formatPercent, formatPrice, randomInt } from './number';
4
+ export { debounce, throttle } from './debounce';
5
+ export { setCookie, getCookie, deleteCookie } from './cookie';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG9F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEnJ,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEhG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Format bytes to human-readable size.
3
+ * formatSize(1536) → "1.5 Ko" (fr) or "1.5 KB" (en)
4
+ */
5
+ export declare function formatSize(bytes: number, locale?: string): string;
6
+ /**
7
+ * Format a number with locale separators.
8
+ * formatCount(12345) → "12 345" (fr) or "12,345" (en)
9
+ */
10
+ export declare function formatCount(n: number, locale?: string): string;
11
+ /**
12
+ * Clamp a value between min and max.
13
+ */
14
+ export declare function clamp(value: number, min: number, max: number): number;
15
+ /**
16
+ * Format a ratio as percentage.
17
+ * formatPercent(0.856) → "85.6%"
18
+ */
19
+ export declare function formatPercent(ratio: number, decimals?: number): string;
20
+ /**
21
+ * Format a price with currency.
22
+ * formatPrice(29.99) → "29,99 €" (fr) or "$29.99" (en)
23
+ */
24
+ export declare function formatPrice(amount: number, currency?: string, locale?: string): string;
25
+ /**
26
+ * Generate a random integer between min and max (inclusive).
27
+ */
28
+ export declare function randomInt(min: number, max: number): number;
29
+ //# sourceMappingURL=number.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.d.ts","sourceRoot":"","sources":["../src/number.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,CAS/D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,SAAU,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAGjE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAQ,EAAE,MAAM,SAAU,GAAG,MAAM,CAMtF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D"}
package/dist/number.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Format bytes to human-readable size.
3
+ * formatSize(1536) → "1.5 Ko" (fr) or "1.5 KB" (en)
4
+ */
5
+ export function formatSize(bytes, locale = 'fr') {
6
+ const fr = locale.startsWith('fr');
7
+ const units = fr ? ['o', 'Ko', 'Mo', 'Go', 'To'] : ['B', 'KB', 'MB', 'GB', 'TB'];
8
+ if (bytes < 1024)
9
+ return `${bytes} ${units[0]}`;
10
+ if (bytes < 1_048_576)
11
+ return `${(bytes / 1024).toFixed(1)} ${units[1]}`;
12
+ if (bytes < 1_073_741_824)
13
+ return `${(bytes / 1_048_576).toFixed(1)} ${units[2]}`;
14
+ if (bytes < 1_099_511_627_776)
15
+ return `${(bytes / 1_073_741_824).toFixed(1)} ${units[3]}`;
16
+ return `${(bytes / 1_099_511_627_776).toFixed(1)} ${units[4]}`;
17
+ }
18
+ /**
19
+ * Format a number with locale separators.
20
+ * formatCount(12345) → "12 345" (fr) or "12,345" (en)
21
+ */
22
+ export function formatCount(n, locale = 'fr-FR') {
23
+ return n.toLocaleString(locale);
24
+ }
25
+ /**
26
+ * Clamp a value between min and max.
27
+ */
28
+ export function clamp(value, min, max) {
29
+ return Math.min(Math.max(value, min), max);
30
+ }
31
+ /**
32
+ * Format a ratio as percentage.
33
+ * formatPercent(0.856) → "85.6%"
34
+ */
35
+ export function formatPercent(ratio, decimals = 1) {
36
+ const d = Math.max(0, Math.min(decimals, 20));
37
+ return `${(ratio * 100).toFixed(d)}%`;
38
+ }
39
+ /**
40
+ * Format a price with currency.
41
+ * formatPrice(29.99) → "29,99 €" (fr) or "$29.99" (en)
42
+ */
43
+ export function formatPrice(amount, currency = 'EUR', locale = 'fr-FR') {
44
+ try {
45
+ return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(amount);
46
+ }
47
+ catch {
48
+ return `${amount.toFixed(2)} ${currency}`;
49
+ }
50
+ }
51
+ /**
52
+ * Generate a random integer between min and max (inclusive).
53
+ */
54
+ export function randomInt(min, max) {
55
+ return Math.floor(Math.random() * (max - min + 1)) + min;
56
+ }
57
+ //# sourceMappingURL=number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.js","sourceRoot":"","sources":["../src/number.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAM,GAAG,IAAI;IACrD,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IAEhF,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/C,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACxE,IAAI,KAAK,GAAG,aAAa;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACjF,IAAI,KAAK,GAAG,iBAAiB;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACzF,OAAO,GAAG,CAAC,KAAK,GAAG,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,MAAM,GAAG,OAAO;IACrD,OAAO,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,QAAQ,GAAG,CAAC;IACvD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAA;IAC7C,OAAO,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,QAAQ,GAAG,KAAK,EAAE,MAAM,GAAG,OAAO;IAC5E,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAA;IAC3C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAA;AAC1D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=number.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.test.d.ts","sourceRoot":"","sources":["../src/number.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { formatSize, formatCount, clamp, formatPercent, formatPrice, randomInt } from './number';
3
+ describe('formatSize', () => {
4
+ it('formats bytes in French', () => {
5
+ expect(formatSize(500)).toBe('500 o');
6
+ expect(formatSize(1536)).toBe('1.5 Ko');
7
+ });
8
+ it('formats bytes in English', () => {
9
+ expect(formatSize(500, 'en')).toBe('500 B');
10
+ expect(formatSize(1536, 'en')).toBe('1.5 KB');
11
+ });
12
+ it('handles large sizes', () => {
13
+ expect(formatSize(1_073_741_824)).toBe('1.0 Go');
14
+ });
15
+ });
16
+ describe('formatCount', () => {
17
+ it('formats with French separators by default', () => {
18
+ const result = formatCount(12345);
19
+ // French uses non-breaking space or narrow no-break space
20
+ expect(result.replace(/\s/g, ' ')).toContain('12');
21
+ expect(result.replace(/\s/g, ' ')).toContain('345');
22
+ });
23
+ });
24
+ describe('clamp', () => {
25
+ it('clamps value between min and max', () => {
26
+ expect(clamp(5, 0, 10)).toBe(5);
27
+ expect(clamp(-5, 0, 10)).toBe(0);
28
+ expect(clamp(15, 0, 10)).toBe(10);
29
+ });
30
+ });
31
+ describe('formatPercent', () => {
32
+ it('formats ratio as percentage', () => {
33
+ expect(formatPercent(0.856)).toBe('85.6%');
34
+ expect(formatPercent(1)).toBe('100.0%');
35
+ });
36
+ it('supports custom decimals', () => {
37
+ expect(formatPercent(0.856, 0)).toBe('86%');
38
+ });
39
+ });
40
+ describe('formatPrice', () => {
41
+ it('formats in French EUR by default', () => {
42
+ const result = formatPrice(29.99);
43
+ expect(result).toContain('29');
44
+ expect(result).toContain('99');
45
+ });
46
+ });
47
+ describe('randomInt', () => {
48
+ it('returns value within range', () => {
49
+ for (let i = 0; i < 100; i++) {
50
+ const val = randomInt(1, 10);
51
+ expect(val).toBeGreaterThanOrEqual(1);
52
+ expect(val).toBeLessThanOrEqual(10);
53
+ }
54
+ });
55
+ });
56
+ //# sourceMappingURL=number.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.test.js","sourceRoot":"","sources":["../src/number.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Truncate text to `len` characters with "..."
3
+ */
4
+ export declare function truncate(text: string, len: number, suffix?: string): string;
5
+ /**
6
+ * Generate a URL-safe slug from text.
7
+ * "Mon Super Article !" → "mon-super-article"
8
+ */
9
+ export declare function slugify(text: string): string;
10
+ /**
11
+ * Capitalize first letter.
12
+ */
13
+ export declare function capitalize(text: string): string;
14
+ /**
15
+ * Simple pluralization.
16
+ * pluralize(3, "article") → "3 articles"
17
+ * pluralize(1, "article") → "1 article"
18
+ */
19
+ export declare function pluralize(count: number, word: string, plural?: string): string;
20
+ /**
21
+ * Strip HTML tags from a string.
22
+ * For untrusted HTML, prefer a proper sanitizer (DOMPurify).
23
+ */
24
+ export declare function stripHtml(html: string): string;
25
+ /**
26
+ * Get initials from a name (first 2 letters, uppercased).
27
+ */
28
+ export declare function initials(name: string): string;
29
+ /**
30
+ * Deterministic hash-based color index from a string.
31
+ * Same string always returns the same index.
32
+ * Use with your own color palette.
33
+ */
34
+ export declare function hashColorIndex(name: string, paletteSize: number): number;
35
+ /**
36
+ * Escape HTML entities to prevent XSS.
37
+ */
38
+ export declare function escapeHtml(text: string): string;
39
+ /**
40
+ * Convert a string to camelCase.
41
+ * "my-variable-name" → "myVariableName"
42
+ */
43
+ export declare function camelCase(str: string): string;
44
+ /**
45
+ * Convert a string to kebab-case.
46
+ * "myVariableName" → "my-variable-name"
47
+ */
48
+ export declare function kebabCase(str: string): string;
49
+ /**
50
+ * Check if a filename or URL points to an image.
51
+ * isImage("photo.jpg") → true
52
+ * isImage("doc.pdf") → false
53
+ */
54
+ export declare function isImage(filename: string): boolean;
55
+ //# sourceMappingURL=string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,SAAQ,GAAG,MAAM,CAE1E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO5C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAKxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAID;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGjD"}
package/dist/string.js ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Truncate text to `len` characters with "..."
3
+ */
4
+ export function truncate(text, len, suffix = '...') {
5
+ return text.length > len ? text.slice(0, len) + suffix : text;
6
+ }
7
+ /**
8
+ * Generate a URL-safe slug from text.
9
+ * "Mon Super Article !" → "mon-super-article"
10
+ */
11
+ export function slugify(text) {
12
+ return text
13
+ .toLowerCase()
14
+ .normalize('NFD')
15
+ .replace(/[\u0300-\u036f]/g, '')
16
+ .replace(/[^a-z0-9]+/g, '-')
17
+ .replace(/(^-|-$)/g, '');
18
+ }
19
+ /**
20
+ * Capitalize first letter.
21
+ */
22
+ export function capitalize(text) {
23
+ if (!text)
24
+ return '';
25
+ return text.charAt(0).toUpperCase() + text.slice(1);
26
+ }
27
+ /**
28
+ * Simple pluralization.
29
+ * pluralize(3, "article") → "3 articles"
30
+ * pluralize(1, "article") → "1 article"
31
+ */
32
+ export function pluralize(count, word, plural) {
33
+ const form = count > 1 ? (plural ?? word + 's') : word;
34
+ return `${count} ${form}`;
35
+ }
36
+ /**
37
+ * Strip HTML tags from a string.
38
+ * For untrusted HTML, prefer a proper sanitizer (DOMPurify).
39
+ */
40
+ export function stripHtml(html) {
41
+ return html.replace(/<[^>]*?>/g, '').replace(/</g, '&lt;');
42
+ }
43
+ /**
44
+ * Get initials from a name (first 2 letters, uppercased).
45
+ */
46
+ export function initials(name) {
47
+ return (name ?? 'A').slice(0, 2).toUpperCase();
48
+ }
49
+ /**
50
+ * Deterministic hash-based color index from a string.
51
+ * Same string always returns the same index.
52
+ * Use with your own color palette.
53
+ */
54
+ export function hashColorIndex(name, paletteSize) {
55
+ if (paletteSize <= 0)
56
+ return 0;
57
+ let hash = 0;
58
+ for (let i = 0; i < name.length; i++)
59
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
60
+ return Math.abs(hash) % paletteSize;
61
+ }
62
+ /**
63
+ * Escape HTML entities to prevent XSS.
64
+ */
65
+ export function escapeHtml(text) {
66
+ return text
67
+ .replace(/&/g, '&amp;')
68
+ .replace(/</g, '&lt;')
69
+ .replace(/>/g, '&gt;')
70
+ .replace(/"/g, '&quot;')
71
+ .replace(/'/g, '&#039;');
72
+ }
73
+ /**
74
+ * Convert a string to camelCase.
75
+ * "my-variable-name" → "myVariableName"
76
+ */
77
+ export function camelCase(str) {
78
+ return str.replace(/[-_]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));
79
+ }
80
+ /**
81
+ * Convert a string to kebab-case.
82
+ * "myVariableName" → "my-variable-name"
83
+ */
84
+ export function kebabCase(str) {
85
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[\s_]+/g, '-').toLowerCase();
86
+ }
87
+ const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'svg', 'bmp', 'ico']);
88
+ /**
89
+ * Check if a filename or URL points to an image.
90
+ * isImage("photo.jpg") → true
91
+ * isImage("doc.pdf") → false
92
+ */
93
+ export function isImage(filename) {
94
+ const ext = filename.split('.').pop()?.toLowerCase() ?? '';
95
+ return IMAGE_EXTENSIONS.has(ext);
96
+ }
97
+ //# sourceMappingURL=string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=string.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.test.d.ts","sourceRoot":"","sources":["../src/string.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { truncate, slugify, capitalize, pluralize, stripHtml, initials, hashColorIndex, escapeHtml, camelCase, kebabCase, isImage } from './string';
3
+ describe('truncate', () => {
4
+ it('returns short text unchanged', () => {
5
+ expect(truncate('hello', 10)).toBe('hello');
6
+ });
7
+ it('truncates long text with suffix', () => {
8
+ expect(truncate('hello world', 5)).toBe('hello...');
9
+ });
10
+ it('supports custom suffix', () => {
11
+ expect(truncate('hello world', 5, '…')).toBe('hello…');
12
+ });
13
+ });
14
+ describe('slugify', () => {
15
+ it('converts text to slug', () => {
16
+ expect(slugify('Mon Super Article !')).toBe('mon-super-article');
17
+ });
18
+ it('handles accents', () => {
19
+ expect(slugify('Éléphant à la crème')).toBe('elephant-a-la-creme');
20
+ });
21
+ it('handles empty string', () => {
22
+ expect(slugify('')).toBe('');
23
+ });
24
+ });
25
+ describe('capitalize', () => {
26
+ it('capitalizes first letter', () => {
27
+ expect(capitalize('hello')).toBe('Hello');
28
+ });
29
+ it('handles empty string', () => {
30
+ expect(capitalize('')).toBe('');
31
+ });
32
+ });
33
+ describe('pluralize', () => {
34
+ it('returns singular for 1', () => {
35
+ expect(pluralize(1, 'article')).toBe('1 article');
36
+ });
37
+ it('returns plural for > 1', () => {
38
+ expect(pluralize(3, 'article')).toBe('3 articles');
39
+ });
40
+ it('supports custom plural', () => {
41
+ expect(pluralize(2, 'child', 'children')).toBe('2 children');
42
+ });
43
+ });
44
+ describe('stripHtml', () => {
45
+ it('removes HTML tags', () => {
46
+ expect(stripHtml('<p>Hello <b>world</b></p>')).toBe('Hello world');
47
+ });
48
+ });
49
+ describe('initials', () => {
50
+ it('returns first 2 letters uppercase', () => {
51
+ expect(initials('david')).toBe('DA');
52
+ });
53
+ });
54
+ describe('hashColorIndex', () => {
55
+ it('returns consistent index', () => {
56
+ const idx = hashColorIndex('test', 10);
57
+ expect(hashColorIndex('test', 10)).toBe(idx);
58
+ });
59
+ it('returns index within palette size', () => {
60
+ expect(hashColorIndex('anything', 5)).toBeLessThan(5);
61
+ expect(hashColorIndex('anything', 5)).toBeGreaterThanOrEqual(0);
62
+ });
63
+ });
64
+ describe('escapeHtml', () => {
65
+ it('escapes HTML entities', () => {
66
+ expect(escapeHtml('<script>"a" & \'b\'</script>')).toBe('&lt;script&gt;&quot;a&quot; &amp; &#039;b&#039;&lt;/script&gt;');
67
+ });
68
+ });
69
+ describe('camelCase', () => {
70
+ it('converts kebab to camel', () => {
71
+ expect(camelCase('my-variable-name')).toBe('myVariableName');
72
+ });
73
+ it('converts snake to camel', () => {
74
+ expect(camelCase('my_variable_name')).toBe('myVariableName');
75
+ });
76
+ });
77
+ describe('kebabCase', () => {
78
+ it('converts camelCase to kebab', () => {
79
+ expect(kebabCase('myVariableName')).toBe('my-variable-name');
80
+ });
81
+ });
82
+ describe('isImage', () => {
83
+ it('detects image extensions', () => {
84
+ expect(isImage('photo.jpg')).toBe(true);
85
+ expect(isImage('photo.jpeg')).toBe(true);
86
+ expect(isImage('photo.png')).toBe(true);
87
+ expect(isImage('photo.gif')).toBe(true);
88
+ expect(isImage('photo.webp')).toBe(true);
89
+ expect(isImage('photo.avif')).toBe(true);
90
+ expect(isImage('photo.svg')).toBe(true);
91
+ });
92
+ it('rejects non-image extensions', () => {
93
+ expect(isImage('doc.pdf')).toBe(false);
94
+ expect(isImage('file.txt')).toBe(false);
95
+ expect(isImage('archive.zip')).toBe(false);
96
+ });
97
+ it('is case-insensitive', () => {
98
+ expect(isImage('photo.JPG')).toBe(true);
99
+ expect(isImage('photo.PNG')).toBe(true);
100
+ });
101
+ });
102
+ //# sourceMappingURL=string.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.test.js","sourceRoot":"","sources":["../src/string.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@karbonjs/utils",
3
+ "version": "0.1.0",
4
+ "description": "Utility functions for date, string, number formatting and more",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "license": "MIT",
21
+ "keywords": [
22
+ "karbon",
23
+ "utils",
24
+ "date",
25
+ "string",
26
+ "number",
27
+ "formatting"
28
+ ],
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/YOUR_USER/karbonjs",
32
+ "directory": "packages/utils"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "dev": "tsc --watch"
37
+ }
38
+ }