@sia-ui/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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/dist/async.cjs +134 -0
  4. package/dist/async.d.cts +81 -0
  5. package/dist/async.d.ts +81 -0
  6. package/dist/async.js +1 -0
  7. package/dist/chunk-63IWZEOC.js +51 -0
  8. package/dist/chunk-6P4YWHCJ.js +47 -0
  9. package/dist/chunk-BMNZVRFN.js +25 -0
  10. package/dist/chunk-DKWI2AZG.js +128 -0
  11. package/dist/chunk-DY6WSWXH.js +60 -0
  12. package/dist/chunk-ETJDEEF5.js +129 -0
  13. package/dist/chunk-FX7K6FKW.js +57 -0
  14. package/dist/chunk-JHYMIU2G.js +121 -0
  15. package/dist/chunk-L4BLBOLO.js +93 -0
  16. package/dist/chunk-PTNHOSWH.js +40 -0
  17. package/dist/chunk-QMPHN3LG.js +78 -0
  18. package/dist/chunk-RIFUQ7JM.js +47 -0
  19. package/dist/chunk-YU5NRSDP.js +11 -0
  20. package/dist/classname.cjs +28 -0
  21. package/dist/classname.d.cts +15 -0
  22. package/dist/classname.d.ts +15 -0
  23. package/dist/classname.js +1 -0
  24. package/dist/clipboard.cjs +51 -0
  25. package/dist/clipboard.d.cts +16 -0
  26. package/dist/clipboard.d.ts +16 -0
  27. package/dist/clipboard.js +1 -0
  28. package/dist/collection.cjs +109 -0
  29. package/dist/collection.d.cts +44 -0
  30. package/dist/collection.d.ts +44 -0
  31. package/dist/collection.js +1 -0
  32. package/dist/currency.cjs +64 -0
  33. package/dist/currency.d.cts +16 -0
  34. package/dist/currency.d.ts +16 -0
  35. package/dist/currency.js +1 -0
  36. package/dist/date.cjs +140 -0
  37. package/dist/date.d.cts +32 -0
  38. package/dist/date.d.ts +32 -0
  39. package/dist/date.js +1 -0
  40. package/dist/events.cjs +13 -0
  41. package/dist/events.d.cts +10 -0
  42. package/dist/events.d.ts +10 -0
  43. package/dist/events.js +1 -0
  44. package/dist/file.cjs +141 -0
  45. package/dist/file.d.cts +58 -0
  46. package/dist/file.d.ts +58 -0
  47. package/dist/file.js +1 -0
  48. package/dist/index.cjs +977 -0
  49. package/dist/index.d.cts +13 -0
  50. package/dist/index.d.ts +13 -0
  51. package/dist/index.js +13 -0
  52. package/dist/locale.cjs +58 -0
  53. package/dist/locale.d.cts +51 -0
  54. package/dist/locale.d.ts +51 -0
  55. package/dist/locale.js +1 -0
  56. package/dist/number.cjs +61 -0
  57. package/dist/number.d.cts +14 -0
  58. package/dist/number.d.ts +14 -0
  59. package/dist/number.js +1 -0
  60. package/dist/object.cjs +87 -0
  61. package/dist/object.d.cts +48 -0
  62. package/dist/object.d.ts +48 -0
  63. package/dist/object.js +1 -0
  64. package/dist/query.cjs +65 -0
  65. package/dist/query.d.cts +48 -0
  66. package/dist/query.d.ts +48 -0
  67. package/dist/query.js +1 -0
  68. package/dist/string.cjs +50 -0
  69. package/dist/string.d.cts +15 -0
  70. package/dist/string.d.ts +15 -0
  71. package/dist/string.js +1 -0
  72. package/dist/validation.cjs +123 -0
  73. package/dist/validation.d.cts +77 -0
  74. package/dist/validation.d.ts +77 -0
  75. package/dist/validation.js +102 -0
  76. package/package.json +127 -0
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ // src/clipboard.ts
4
+ function canCopy() {
5
+ return typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function";
6
+ }
7
+ async function copyText(text) {
8
+ if (typeof document === "undefined") return false;
9
+ if (canCopy()) {
10
+ try {
11
+ await navigator.clipboard.writeText(text);
12
+ return true;
13
+ } catch {
14
+ }
15
+ }
16
+ return copyWithTextarea(text);
17
+ }
18
+ async function readText() {
19
+ if (typeof navigator === "undefined" || typeof navigator.clipboard?.readText !== "function") {
20
+ return null;
21
+ }
22
+ try {
23
+ return await navigator.clipboard.readText();
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+ function copyWithTextarea(text) {
29
+ const field = document.createElement("textarea");
30
+ field.value = text;
31
+ field.setAttribute("readonly", "");
32
+ field.style.position = "fixed";
33
+ field.style.top = "-9999px";
34
+ field.style.opacity = "0";
35
+ document.body.appendChild(field);
36
+ const previous = document.activeElement;
37
+ try {
38
+ field.select();
39
+ field.setSelectionRange(0, field.value.length);
40
+ return document.execCommand("copy");
41
+ } catch {
42
+ return false;
43
+ } finally {
44
+ field.remove();
45
+ previous?.focus?.();
46
+ }
47
+ }
48
+
49
+ exports.canCopy = canCopy;
50
+ exports.copyText = copyText;
51
+ exports.readText = readText;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Presse-papiers.
3
+ *
4
+ * L'API moderne demande un contexte sécurisé — HTTPS ou localhost. En HTTP
5
+ * simple, sur un réseau interne par exemple, elle n'existe pas : le repli par
6
+ * un champ de saisie hors écran est la seule façon de ne pas perdre la
7
+ * fonction là où elle sert le plus.
8
+ */
9
+ /** Vrai si l'API moderne est disponible. Le repli marche de toute façon. */
10
+ declare function canCopy(): boolean;
11
+ /** Copie du texte. Rend `false` si rien n'a pu être copié. */
12
+ declare function copyText(text: string): Promise<boolean>;
13
+ /** Lit le presse-papiers. Souvent refusé : la permission est demandée. */
14
+ declare function readText(): Promise<string | null>;
15
+
16
+ export { canCopy, copyText, readText };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Presse-papiers.
3
+ *
4
+ * L'API moderne demande un contexte sécurisé — HTTPS ou localhost. En HTTP
5
+ * simple, sur un réseau interne par exemple, elle n'existe pas : le repli par
6
+ * un champ de saisie hors écran est la seule façon de ne pas perdre la
7
+ * fonction là où elle sert le plus.
8
+ */
9
+ /** Vrai si l'API moderne est disponible. Le repli marche de toute façon. */
10
+ declare function canCopy(): boolean;
11
+ /** Copie du texte. Rend `false` si rien n'a pu être copié. */
12
+ declare function copyText(text: string): Promise<boolean>;
13
+ /** Lit le presse-papiers. Souvent refusé : la permission est demandée. */
14
+ declare function readText(): Promise<string | null>;
15
+
16
+ export { canCopy, copyText, readText };
@@ -0,0 +1 @@
1
+ export { canCopy, copyText, readText } from './chunk-RIFUQ7JM.js';
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ // src/collection.ts
4
+ function isDefined(value) {
5
+ return value !== null && value !== void 0;
6
+ }
7
+ function unique(values) {
8
+ return [...new Set(values)];
9
+ }
10
+ function uniqueBy(values, key) {
11
+ const seen = /* @__PURE__ */ new Set();
12
+ const out = [];
13
+ for (const item of values) {
14
+ const id = key(item);
15
+ if (seen.has(id)) continue;
16
+ seen.add(id);
17
+ out.push(item);
18
+ }
19
+ return out;
20
+ }
21
+ function compact(values) {
22
+ return values.filter(isDefined);
23
+ }
24
+ function groupBy(values, key) {
25
+ const out = {};
26
+ for (const item of values) {
27
+ const group = key(item);
28
+ (out[group] ??= []).push(item);
29
+ }
30
+ return out;
31
+ }
32
+ function keyBy(values, key) {
33
+ const out = {};
34
+ for (const item of values) out[key(item)] = item;
35
+ return out;
36
+ }
37
+ function chunk(values, size) {
38
+ if (size <= 0) return [[...values]];
39
+ const out = [];
40
+ for (let index = 0; index < values.length; index += size) {
41
+ out.push(values.slice(index, index + size));
42
+ }
43
+ return out;
44
+ }
45
+ function partition(values, predicate) {
46
+ const yes = [];
47
+ const no = [];
48
+ values.forEach((item, index) => {
49
+ (predicate(item, index) ? yes : no).push(item);
50
+ });
51
+ return [yes, no];
52
+ }
53
+ function sortBy(values, key, direction = "asc", locale = "fr-FR") {
54
+ const sign = direction === "asc" ? 1 : -1;
55
+ return [...values].sort((a, b) => {
56
+ const left = key(a);
57
+ const right = key(b);
58
+ if (!isDefined(left)) return isDefined(right) ? 1 : 0;
59
+ if (!isDefined(right)) return -1;
60
+ if (typeof left === "string" && typeof right === "string") {
61
+ return left.localeCompare(right, locale) * sign;
62
+ }
63
+ const l = left instanceof Date ? left.getTime() : Number(left);
64
+ const r = right instanceof Date ? right.getTime() : Number(right);
65
+ return (l - r) * sign;
66
+ });
67
+ }
68
+ function sum(values) {
69
+ return values.reduce((total, value) => total + value, 0);
70
+ }
71
+ function sumBy(values, key) {
72
+ return values.reduce((total, item) => total + key(item), 0);
73
+ }
74
+ function averageBy(values, key) {
75
+ if (values.length === 0) return 0;
76
+ return sumBy(values, key) / values.length;
77
+ }
78
+ function range(start, end, step = 1) {
79
+ if (step === 0) return [];
80
+ const out = [];
81
+ if (step > 0) for (let i = start; i <= end; i += step) out.push(i);
82
+ else for (let i = start; i >= end; i += step) out.push(i);
83
+ return out;
84
+ }
85
+ function move(values, from, to) {
86
+ const out = [...values];
87
+ const [item] = out.splice(from, 1);
88
+ if (item !== void 0) out.splice(to, 0, item);
89
+ return out;
90
+ }
91
+ function toggleItem(values, item) {
92
+ return values.includes(item) ? values.filter((entry) => entry !== item) : [...values, item];
93
+ }
94
+
95
+ exports.averageBy = averageBy;
96
+ exports.chunk = chunk;
97
+ exports.compact = compact;
98
+ exports.groupBy = groupBy;
99
+ exports.isDefined = isDefined;
100
+ exports.keyBy = keyBy;
101
+ exports.move = move;
102
+ exports.partition = partition;
103
+ exports.range = range;
104
+ exports.sortBy = sortBy;
105
+ exports.sum = sum;
106
+ exports.sumBy = sumBy;
107
+ exports.toggleItem = toggleItem;
108
+ exports.unique = unique;
109
+ exports.uniqueBy = uniqueBy;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Listes.
3
+ *
4
+ * Rien qui ne s'écrive en trois lignes — mais ces trois lignes étaient
5
+ * écrites dans chaque projet, chaque fois légèrement différemment.
6
+ */
7
+ /** Retire `null` et `undefined`, et le dit au typage. */
8
+ declare function isDefined<T>(value: T | null | undefined): value is T;
9
+ /** Les valeurs distinctes, dans l'ordre d'apparition. */
10
+ declare function unique<T>(values: readonly T[]): T[];
11
+ /** Les valeurs distinctes selon une clé — un identifiant, le plus souvent. */
12
+ declare function uniqueBy<T, K>(values: readonly T[], key: (item: T) => K): T[];
13
+ /** Retire les trous : `null`, `undefined`. */
14
+ declare function compact<T>(values: readonly (T | null | undefined)[]): T[];
15
+ /** Regroupe par clé. Les groupes gardent l'ordre de la liste d'origine. */
16
+ declare function groupBy<T, K extends string | number>(values: readonly T[], key: (item: T) => K): Record<K, T[]>;
17
+ /** Indexe par clé. En cas de doublon, le dernier gagne. */
18
+ declare function keyBy<T, K extends string | number>(values: readonly T[], key: (item: T) => K): Record<K, T>;
19
+ /** Découpe en tranches de taille fixe. La dernière peut être plus courte. */
20
+ declare function chunk<T>(values: readonly T[], size: number): T[][];
21
+ /** Sépare en deux : ce qui passe le test, ce qui ne le passe pas. */
22
+ declare function partition<T>(values: readonly T[], predicate: (item: T, index: number) => boolean): [T[], T[]];
23
+ type SortDirection = "asc" | "desc";
24
+ /**
25
+ * Trie sans modifier la liste d'origine.
26
+ *
27
+ * Les chaînes sont comparées avec `localeCompare` : sans cela « Émile » se
28
+ * range après « Zoé », ce qui se voit immédiatement dans une liste de noms.
29
+ */
30
+ declare function sortBy<T>(values: readonly T[], key: (item: T) => string | number | Date | null | undefined, direction?: SortDirection, locale?: string): T[];
31
+ /** Somme d'une liste de nombres. */
32
+ declare function sum(values: readonly number[]): number;
33
+ /** Somme d'une propriété — un montant, une quantité. */
34
+ declare function sumBy<T>(values: readonly T[], key: (item: T) => number): number;
35
+ /** Moyenne. Une liste vide rend `0` plutôt que `NaN`. */
36
+ declare function averageBy<T>(values: readonly T[], key: (item: T) => number): number;
37
+ /** Une suite d'entiers, bornes incluses. */
38
+ declare function range(start: number, end: number, step?: number): number[];
39
+ /** Déplace un élément d'une position à une autre — un glisser-déposer. */
40
+ declare function move<T>(values: readonly T[], from: number, to: number): T[];
41
+ /** Ajoute ou retire selon la présence — une sélection multiple. */
42
+ declare function toggleItem<T>(values: readonly T[], item: T): T[];
43
+
44
+ export { type SortDirection, averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Listes.
3
+ *
4
+ * Rien qui ne s'écrive en trois lignes — mais ces trois lignes étaient
5
+ * écrites dans chaque projet, chaque fois légèrement différemment.
6
+ */
7
+ /** Retire `null` et `undefined`, et le dit au typage. */
8
+ declare function isDefined<T>(value: T | null | undefined): value is T;
9
+ /** Les valeurs distinctes, dans l'ordre d'apparition. */
10
+ declare function unique<T>(values: readonly T[]): T[];
11
+ /** Les valeurs distinctes selon une clé — un identifiant, le plus souvent. */
12
+ declare function uniqueBy<T, K>(values: readonly T[], key: (item: T) => K): T[];
13
+ /** Retire les trous : `null`, `undefined`. */
14
+ declare function compact<T>(values: readonly (T | null | undefined)[]): T[];
15
+ /** Regroupe par clé. Les groupes gardent l'ordre de la liste d'origine. */
16
+ declare function groupBy<T, K extends string | number>(values: readonly T[], key: (item: T) => K): Record<K, T[]>;
17
+ /** Indexe par clé. En cas de doublon, le dernier gagne. */
18
+ declare function keyBy<T, K extends string | number>(values: readonly T[], key: (item: T) => K): Record<K, T>;
19
+ /** Découpe en tranches de taille fixe. La dernière peut être plus courte. */
20
+ declare function chunk<T>(values: readonly T[], size: number): T[][];
21
+ /** Sépare en deux : ce qui passe le test, ce qui ne le passe pas. */
22
+ declare function partition<T>(values: readonly T[], predicate: (item: T, index: number) => boolean): [T[], T[]];
23
+ type SortDirection = "asc" | "desc";
24
+ /**
25
+ * Trie sans modifier la liste d'origine.
26
+ *
27
+ * Les chaînes sont comparées avec `localeCompare` : sans cela « Émile » se
28
+ * range après « Zoé », ce qui se voit immédiatement dans une liste de noms.
29
+ */
30
+ declare function sortBy<T>(values: readonly T[], key: (item: T) => string | number | Date | null | undefined, direction?: SortDirection, locale?: string): T[];
31
+ /** Somme d'une liste de nombres. */
32
+ declare function sum(values: readonly number[]): number;
33
+ /** Somme d'une propriété — un montant, une quantité. */
34
+ declare function sumBy<T>(values: readonly T[], key: (item: T) => number): number;
35
+ /** Moyenne. Une liste vide rend `0` plutôt que `NaN`. */
36
+ declare function averageBy<T>(values: readonly T[], key: (item: T) => number): number;
37
+ /** Une suite d'entiers, bornes incluses. */
38
+ declare function range(start: number, end: number, step?: number): number[];
39
+ /** Déplace un élément d'une position à une autre — un glisser-déposer. */
40
+ declare function move<T>(values: readonly T[], from: number, to: number): T[];
41
+ /** Ajoute ou retire selon la présence — une sélection multiple. */
42
+ declare function toggleItem<T>(values: readonly T[], item: T): T[];
43
+
44
+ export { type SortDirection, averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy };
@@ -0,0 +1 @@
1
+ export { averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy } from './chunk-L4BLBOLO.js';
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+
3
+ // src/currency.ts
4
+ function getNumberFormat(locale, options) {
5
+ return new Intl.NumberFormat(locale, options);
6
+ }
7
+ function normalizeNumberInput(input, decimalSeparator) {
8
+ const trimmed = input.trim();
9
+ const sanitized = trimmed.replace(/[^\d,.-]/g, "");
10
+ if (!sanitized) return "";
11
+ if (decimalSeparator) {
12
+ const normalized = decimalSeparator === "," ? sanitized.replace(/\./g, "").replace(",", ".") : sanitized.replace(/,/g, "");
13
+ return normalized;
14
+ }
15
+ const lastComma = sanitized.lastIndexOf(",");
16
+ const lastDot = sanitized.lastIndexOf(".");
17
+ if (lastComma > lastDot) {
18
+ return sanitized.replace(/\./g, "").replace(",", ".");
19
+ }
20
+ return sanitized.replace(/,/g, "");
21
+ }
22
+ function formatCurrency(value, options = {}) {
23
+ const { locale = "fr-FR", currency = "XAF", ...formatOptions } = options;
24
+ return getNumberFormat(locale, {
25
+ style: "currency",
26
+ currency,
27
+ maximumFractionDigits: currency === "XAF" || currency === "XOF" ? 0 : 2,
28
+ ...formatOptions
29
+ }).format(value);
30
+ }
31
+ function formatAmount(value, options = {}) {
32
+ const { locale = "fr-FR", ...formatOptions } = options;
33
+ return getNumberFormat(locale, {
34
+ maximumFractionDigits: 2,
35
+ ...formatOptions
36
+ }).format(value);
37
+ }
38
+ function parseCurrency(input, options = {}) {
39
+ const normalized = normalizeNumberInput(input, options.decimalSeparator);
40
+ if (!normalized) return null;
41
+ const value = Number(normalized);
42
+ return Number.isFinite(value) ? value : null;
43
+ }
44
+ function minorToMajor(amount, digits = 2) {
45
+ return amount / 10 ** digits;
46
+ }
47
+ function majorToMinor(amount, digits = 2) {
48
+ return Math.round(amount * 10 ** digits);
49
+ }
50
+ function getCurrencySymbol(currency, locale = "fr-FR") {
51
+ const parts = getNumberFormat(locale, {
52
+ style: "currency",
53
+ currency,
54
+ currencyDisplay: "narrowSymbol"
55
+ }).formatToParts(1);
56
+ return parts.find((part) => part.type === "currency")?.value ?? currency;
57
+ }
58
+
59
+ exports.formatAmount = formatAmount;
60
+ exports.formatCurrency = formatCurrency;
61
+ exports.getCurrencySymbol = getCurrencySymbol;
62
+ exports.majorToMinor = majorToMinor;
63
+ exports.minorToMajor = minorToMajor;
64
+ exports.parseCurrency = parseCurrency;
@@ -0,0 +1,16 @@
1
+ interface CurrencyFormatOptions extends Intl.NumberFormatOptions {
2
+ locale?: string;
3
+ currency?: string;
4
+ }
5
+ interface ParseCurrencyOptions {
6
+ locale?: string;
7
+ decimalSeparator?: "." | ",";
8
+ }
9
+ declare function formatCurrency(value: number, options?: CurrencyFormatOptions): string;
10
+ declare function formatAmount(value: number, options?: CurrencyFormatOptions): string;
11
+ declare function parseCurrency(input: string, options?: ParseCurrencyOptions): number | null;
12
+ declare function minorToMajor(amount: number, digits?: number): number;
13
+ declare function majorToMinor(amount: number, digits?: number): number;
14
+ declare function getCurrencySymbol(currency: string, locale?: string): string;
15
+
16
+ export { type CurrencyFormatOptions, type ParseCurrencyOptions, formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency };
@@ -0,0 +1,16 @@
1
+ interface CurrencyFormatOptions extends Intl.NumberFormatOptions {
2
+ locale?: string;
3
+ currency?: string;
4
+ }
5
+ interface ParseCurrencyOptions {
6
+ locale?: string;
7
+ decimalSeparator?: "." | ",";
8
+ }
9
+ declare function formatCurrency(value: number, options?: CurrencyFormatOptions): string;
10
+ declare function formatAmount(value: number, options?: CurrencyFormatOptions): string;
11
+ declare function parseCurrency(input: string, options?: ParseCurrencyOptions): number | null;
12
+ declare function minorToMajor(amount: number, digits?: number): number;
13
+ declare function majorToMinor(amount: number, digits?: number): number;
14
+ declare function getCurrencySymbol(currency: string, locale?: string): string;
15
+
16
+ export { type CurrencyFormatOptions, type ParseCurrencyOptions, formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency };
@@ -0,0 +1 @@
1
+ export { formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency } from './chunk-FX7K6FKW.js';
package/dist/date.cjs ADDED
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ // src/date.ts
4
+ function toDate(value) {
5
+ const date = value instanceof Date ? new Date(value.getTime()) : new Date(value);
6
+ return Number.isNaN(date.getTime()) ? null : date;
7
+ }
8
+ function shiftDate(value, mutate) {
9
+ const date = toDate(value);
10
+ if (!date) return null;
11
+ const next = new Date(date.getTime());
12
+ mutate(next);
13
+ return next;
14
+ }
15
+ function formatWith(locale, value, options) {
16
+ return new Intl.DateTimeFormat(locale, options).format(value);
17
+ }
18
+ function parseDate(value) {
19
+ return /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
20
+ }
21
+ function diffInDays(startDate, endDate) {
22
+ const start = parseDate(startDate);
23
+ const end = parseDate(endDate);
24
+ const diffInMilliseconds = end.getTime() - start.getTime();
25
+ return Math.trunc(diffInMilliseconds / (1e3 * 60 * 60 * 24));
26
+ }
27
+ function formatDate(value, options = {}) {
28
+ const date = toDate(value);
29
+ if (!date) return "";
30
+ const { locale = "fr-FR", ...formatOptions } = options;
31
+ return formatWith(locale, date, { dateStyle: "medium", ...formatOptions });
32
+ }
33
+ function formatDateTime(value, options = {}) {
34
+ const date = toDate(value);
35
+ if (!date) return "";
36
+ const { locale = "fr-FR", ...formatOptions } = options;
37
+ return formatWith(locale, date, { dateStyle: "medium", timeStyle: "short", ...formatOptions });
38
+ }
39
+ function formatRelativeDate(value, options = {}) {
40
+ const date = toDate(value);
41
+ const now = toDate(options.now ?? /* @__PURE__ */ new Date());
42
+ if (!date || !now) return "";
43
+ const diffMs = date.getTime() - now.getTime();
44
+ const units = [
45
+ ["year", 1e3 * 60 * 60 * 24 * 365],
46
+ ["month", 1e3 * 60 * 60 * 24 * 30],
47
+ ["day", 1e3 * 60 * 60 * 24],
48
+ ["hour", 1e3 * 60 * 60],
49
+ ["minute", 1e3 * 60],
50
+ ["second", 1e3]
51
+ ];
52
+ for (const [unit, size] of units) {
53
+ if (Math.abs(diffMs) >= size || unit === "second") {
54
+ const valueForUnit = Math.round(diffMs / size);
55
+ return new Intl.RelativeTimeFormat(options.locale ?? "fr-FR", { numeric: "auto" }).format(valueForUnit, unit);
56
+ }
57
+ }
58
+ return "";
59
+ }
60
+ function formatTimeAgo(value, options = {}) {
61
+ const relative = formatRelativeDate(value, options);
62
+ if (!relative) return "";
63
+ const prefix = options.prefix?.trim();
64
+ return prefix ? `${prefix} ${relative}` : relative;
65
+ }
66
+ function formatDateRange(start, end, options = {}) {
67
+ const startDate = toDate(start);
68
+ const endDate = toDate(end);
69
+ if (!startDate || !endDate) return "";
70
+ const { locale = "fr-FR", ...formatOptions } = options;
71
+ const formatter = new Intl.DateTimeFormat(locale, { dateStyle: "medium", ...formatOptions });
72
+ if (typeof formatter.formatRange === "function") {
73
+ return formatter.formatRange(startDate, endDate);
74
+ }
75
+ return `${formatter.format(startDate)} - ${formatter.format(endDate)}`;
76
+ }
77
+ function isPastDate(value, now = /* @__PURE__ */ new Date()) {
78
+ const date = toDate(value);
79
+ const reference = toDate(now);
80
+ if (!date || !reference) return false;
81
+ return date.getTime() < reference.getTime();
82
+ }
83
+ function toIsoDate(value) {
84
+ const date = toDate(value);
85
+ if (!date) return "";
86
+ const year = date.getFullYear();
87
+ const month = String(date.getMonth() + 1).padStart(2, "0");
88
+ const day = String(date.getDate()).padStart(2, "0");
89
+ return `${year}-${month}-${day}`;
90
+ }
91
+ function toDisplayDate(value, locale = "fr-FR") {
92
+ return formatDate(value, { locale });
93
+ }
94
+ function addDays(value, days) {
95
+ return shiftDate(value, (date) => date.setDate(date.getDate() + days));
96
+ }
97
+ function subDays(value, days) {
98
+ return addDays(value, -days);
99
+ }
100
+ function addMonths(value, months) {
101
+ return shiftDate(value, (date) => date.setMonth(date.getMonth() + months));
102
+ }
103
+ function subMonths(value, months) {
104
+ return addMonths(value, -months);
105
+ }
106
+ function addYears(value, years) {
107
+ return shiftDate(value, (date) => date.setFullYear(date.getFullYear() + years));
108
+ }
109
+ function subYears(value, years) {
110
+ return addYears(value, -years);
111
+ }
112
+ function getFirstDayOfMonth(value) {
113
+ const date = toDate(value);
114
+ if (!date) return null;
115
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1));
116
+ }
117
+ function getLastDayOfMonth(value) {
118
+ const date = toDate(value);
119
+ if (!date) return null;
120
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0));
121
+ }
122
+
123
+ exports.addDays = addDays;
124
+ exports.addMonths = addMonths;
125
+ exports.addYears = addYears;
126
+ exports.diffInDays = diffInDays;
127
+ exports.formatDate = formatDate;
128
+ exports.formatDateRange = formatDateRange;
129
+ exports.formatDateTime = formatDateTime;
130
+ exports.formatRelativeDate = formatRelativeDate;
131
+ exports.formatTimeAgo = formatTimeAgo;
132
+ exports.getFirstDayOfMonth = getFirstDayOfMonth;
133
+ exports.getLastDayOfMonth = getLastDayOfMonth;
134
+ exports.isPastDate = isPastDate;
135
+ exports.parseDate = parseDate;
136
+ exports.subDays = subDays;
137
+ exports.subMonths = subMonths;
138
+ exports.subYears = subYears;
139
+ exports.toDisplayDate = toDisplayDate;
140
+ exports.toIsoDate = toIsoDate;
@@ -0,0 +1,32 @@
1
+ type DateValue = Date | string | number;
2
+ interface DateFormatOptions extends Intl.DateTimeFormatOptions {
3
+ locale?: string;
4
+ }
5
+ interface TimeAgoOptions {
6
+ locale?: string;
7
+ now?: DateValue;
8
+ prefix?: string;
9
+ }
10
+ declare function parseDate(value: string): Date;
11
+ declare function diffInDays(startDate: string, endDate: string): number;
12
+ declare function formatDate(value: DateValue, options?: DateFormatOptions): string;
13
+ declare function formatDateTime(value: DateValue, options?: DateFormatOptions): string;
14
+ declare function formatRelativeDate(value: DateValue, options?: {
15
+ locale?: string;
16
+ now?: DateValue;
17
+ }): string;
18
+ declare function formatTimeAgo(value: DateValue, options?: TimeAgoOptions): string;
19
+ declare function formatDateRange(start: DateValue, end: DateValue, options?: DateFormatOptions): string;
20
+ declare function isPastDate(value: DateValue, now?: DateValue): boolean;
21
+ declare function toIsoDate(value: DateValue): string;
22
+ declare function toDisplayDate(value: DateValue, locale?: string): string;
23
+ declare function addDays(value: DateValue, days: number): Date | null;
24
+ declare function subDays(value: DateValue, days: number): Date | null;
25
+ declare function addMonths(value: DateValue, months: number): Date | null;
26
+ declare function subMonths(value: DateValue, months: number): Date | null;
27
+ declare function addYears(value: DateValue, years: number): Date | null;
28
+ declare function subYears(value: DateValue, years: number): Date | null;
29
+ declare function getFirstDayOfMonth(value: DateValue): Date | null;
30
+ declare function getLastDayOfMonth(value: DateValue): Date | null;
31
+
32
+ export { type DateFormatOptions, type DateValue, type TimeAgoOptions, addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate };
package/dist/date.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ type DateValue = Date | string | number;
2
+ interface DateFormatOptions extends Intl.DateTimeFormatOptions {
3
+ locale?: string;
4
+ }
5
+ interface TimeAgoOptions {
6
+ locale?: string;
7
+ now?: DateValue;
8
+ prefix?: string;
9
+ }
10
+ declare function parseDate(value: string): Date;
11
+ declare function diffInDays(startDate: string, endDate: string): number;
12
+ declare function formatDate(value: DateValue, options?: DateFormatOptions): string;
13
+ declare function formatDateTime(value: DateValue, options?: DateFormatOptions): string;
14
+ declare function formatRelativeDate(value: DateValue, options?: {
15
+ locale?: string;
16
+ now?: DateValue;
17
+ }): string;
18
+ declare function formatTimeAgo(value: DateValue, options?: TimeAgoOptions): string;
19
+ declare function formatDateRange(start: DateValue, end: DateValue, options?: DateFormatOptions): string;
20
+ declare function isPastDate(value: DateValue, now?: DateValue): boolean;
21
+ declare function toIsoDate(value: DateValue): string;
22
+ declare function toDisplayDate(value: DateValue, locale?: string): string;
23
+ declare function addDays(value: DateValue, days: number): Date | null;
24
+ declare function subDays(value: DateValue, days: number): Date | null;
25
+ declare function addMonths(value: DateValue, months: number): Date | null;
26
+ declare function subMonths(value: DateValue, months: number): Date | null;
27
+ declare function addYears(value: DateValue, years: number): Date | null;
28
+ declare function subYears(value: DateValue, years: number): Date | null;
29
+ declare function getFirstDayOfMonth(value: DateValue): Date | null;
30
+ declare function getLastDayOfMonth(value: DateValue): Date | null;
31
+
32
+ export { type DateFormatOptions, type DateValue, type TimeAgoOptions, addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate };
package/dist/date.js ADDED
@@ -0,0 +1 @@
1
+ export { addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate } from './chunk-JHYMIU2G.js';
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ // src/events.ts
4
+ function composeEventHandlers(consumerHandler, internalHandler) {
5
+ return (event) => {
6
+ consumerHandler?.(event);
7
+ if (!event.defaultPrevented) {
8
+ internalHandler?.(event);
9
+ }
10
+ };
11
+ }
12
+
13
+ exports.composeEventHandlers = composeEventHandlers;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Enchaîne le gestionnaire d'un appelant et celui d'un composant.
3
+ *
4
+ * Celui de l'appelant passe en premier et peut couper la suite en appelant
5
+ * `preventDefault()` — c'est ce qui permet de neutraliser un comportement
6
+ * intégré sans avoir à le réécrire.
7
+ */
8
+ declare function composeEventHandlers<E>(consumerHandler?: ((event: E) => void) | undefined, internalHandler?: ((event: E) => void) | undefined): (event: E) => void;
9
+
10
+ export { composeEventHandlers };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Enchaîne le gestionnaire d'un appelant et celui d'un composant.
3
+ *
4
+ * Celui de l'appelant passe en premier et peut couper la suite en appelant
5
+ * `preventDefault()` — c'est ce qui permet de neutraliser un comportement
6
+ * intégré sans avoir à le réécrire.
7
+ */
8
+ declare function composeEventHandlers<E>(consumerHandler?: ((event: E) => void) | undefined, internalHandler?: ((event: E) => void) | undefined): (event: E) => void;
9
+
10
+ export { composeEventHandlers };
package/dist/events.js ADDED
@@ -0,0 +1 @@
1
+ export { composeEventHandlers } from './chunk-YU5NRSDP.js';