@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.
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/async.cjs +134 -0
- package/dist/async.d.cts +81 -0
- package/dist/async.d.ts +81 -0
- package/dist/async.js +1 -0
- package/dist/chunk-63IWZEOC.js +51 -0
- package/dist/chunk-6P4YWHCJ.js +47 -0
- package/dist/chunk-BMNZVRFN.js +25 -0
- package/dist/chunk-DKWI2AZG.js +128 -0
- package/dist/chunk-DY6WSWXH.js +60 -0
- package/dist/chunk-ETJDEEF5.js +129 -0
- package/dist/chunk-FX7K6FKW.js +57 -0
- package/dist/chunk-JHYMIU2G.js +121 -0
- package/dist/chunk-L4BLBOLO.js +93 -0
- package/dist/chunk-PTNHOSWH.js +40 -0
- package/dist/chunk-QMPHN3LG.js +78 -0
- package/dist/chunk-RIFUQ7JM.js +47 -0
- package/dist/chunk-YU5NRSDP.js +11 -0
- package/dist/classname.cjs +28 -0
- package/dist/classname.d.cts +15 -0
- package/dist/classname.d.ts +15 -0
- package/dist/classname.js +1 -0
- package/dist/clipboard.cjs +51 -0
- package/dist/clipboard.d.cts +16 -0
- package/dist/clipboard.d.ts +16 -0
- package/dist/clipboard.js +1 -0
- package/dist/collection.cjs +109 -0
- package/dist/collection.d.cts +44 -0
- package/dist/collection.d.ts +44 -0
- package/dist/collection.js +1 -0
- package/dist/currency.cjs +64 -0
- package/dist/currency.d.cts +16 -0
- package/dist/currency.d.ts +16 -0
- package/dist/currency.js +1 -0
- package/dist/date.cjs +140 -0
- package/dist/date.d.cts +32 -0
- package/dist/date.d.ts +32 -0
- package/dist/date.js +1 -0
- package/dist/events.cjs +13 -0
- package/dist/events.d.cts +10 -0
- package/dist/events.d.ts +10 -0
- package/dist/events.js +1 -0
- package/dist/file.cjs +141 -0
- package/dist/file.d.cts +58 -0
- package/dist/file.d.ts +58 -0
- package/dist/file.js +1 -0
- package/dist/index.cjs +977 -0
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/locale.cjs +58 -0
- package/dist/locale.d.cts +51 -0
- package/dist/locale.d.ts +51 -0
- package/dist/locale.js +1 -0
- package/dist/number.cjs +61 -0
- package/dist/number.d.cts +14 -0
- package/dist/number.d.ts +14 -0
- package/dist/number.js +1 -0
- package/dist/object.cjs +87 -0
- package/dist/object.d.cts +48 -0
- package/dist/object.d.ts +48 -0
- package/dist/object.js +1 -0
- package/dist/query.cjs +65 -0
- package/dist/query.d.cts +48 -0
- package/dist/query.d.ts +48 -0
- package/dist/query.js +1 -0
- package/dist/string.cjs +50 -0
- package/dist/string.d.cts +15 -0
- package/dist/string.d.ts +15 -0
- package/dist/string.js +1 -0
- package/dist/validation.cjs +123 -0
- package/dist/validation.d.cts +77 -0
- package/dist/validation.d.ts +77 -0
- package/dist/validation.js +102 -0
- package/package.json +127 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { AsyncState, AsyncStatus, DebounceOptions, Debounced, RetryOptions, ToAsyncStateInput, createRetry, debounce, sleep, throttle, toAsyncState } from './async.cjs';
|
|
2
|
+
export { ClassValue, cn, toneClass } from './classname.cjs';
|
|
3
|
+
export { canCopy, copyText, readText } from './clipboard.cjs';
|
|
4
|
+
export { SortDirection, averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy } from './collection.cjs';
|
|
5
|
+
export { CurrencyFormatOptions, ParseCurrencyOptions, formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency } from './currency.cjs';
|
|
6
|
+
export { DateFormatOptions, DateValue, TimeAgoOptions, addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate } from './date.cjs';
|
|
7
|
+
export { composeEventHandlers } from './events.cjs';
|
|
8
|
+
export { FileKind, FormatBytesOptions, baseName, downloadBlob, downloadText, exceedsSize, extension, fileKind, formatBytes, isImage, matchesAccept, readAsDataUrl, readAsText } from './file.cjs';
|
|
9
|
+
export { DEFAULT_LOCALE, ListFormatOptions, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale } from './locale.cjs';
|
|
10
|
+
export { NumberFormatOptions, clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber } from './number.cjs';
|
|
11
|
+
export { DeepPartial, deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath } from './object.cjs';
|
|
12
|
+
export { QueryParamsInput, QueryValue, ToQueryStringOptions, fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString } from './query.cjs';
|
|
13
|
+
export { capitalize, initials, isBlank, maskMiddle, normalizeIdentifier, normalizeSpaces, slugify, titleCase, truncate } from './string.cjs';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { AsyncState, AsyncStatus, DebounceOptions, Debounced, RetryOptions, ToAsyncStateInput, createRetry, debounce, sleep, throttle, toAsyncState } from './async.js';
|
|
2
|
+
export { ClassValue, cn, toneClass } from './classname.js';
|
|
3
|
+
export { canCopy, copyText, readText } from './clipboard.js';
|
|
4
|
+
export { SortDirection, averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy } from './collection.js';
|
|
5
|
+
export { CurrencyFormatOptions, ParseCurrencyOptions, formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency } from './currency.js';
|
|
6
|
+
export { DateFormatOptions, DateValue, TimeAgoOptions, addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate } from './date.js';
|
|
7
|
+
export { composeEventHandlers } from './events.js';
|
|
8
|
+
export { FileKind, FormatBytesOptions, baseName, downloadBlob, downloadText, exceedsSize, extension, fileKind, formatBytes, isImage, matchesAccept, readAsDataUrl, readAsText } from './file.js';
|
|
9
|
+
export { DEFAULT_LOCALE, ListFormatOptions, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale } from './locale.js';
|
|
10
|
+
export { NumberFormatOptions, clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber } from './number.js';
|
|
11
|
+
export { DeepPartial, deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath } from './object.js';
|
|
12
|
+
export { QueryParamsInput, QueryValue, ToQueryStringOptions, fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString } from './query.js';
|
|
13
|
+
export { capitalize, initials, isBlank, maskMiddle, normalizeIdentifier, normalizeSpaces, slugify, titleCase, truncate } from './string.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { baseName, downloadBlob, downloadText, exceedsSize, extension, fileKind, formatBytes, isImage, matchesAccept, readAsDataUrl, readAsText } from './chunk-ETJDEEF5.js';
|
|
2
|
+
export { DEFAULT_LOCALE, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale } from './chunk-6P4YWHCJ.js';
|
|
3
|
+
export { clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber } from './chunk-63IWZEOC.js';
|
|
4
|
+
export { deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath } from './chunk-QMPHN3LG.js';
|
|
5
|
+
export { fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString } from './chunk-DY6WSWXH.js';
|
|
6
|
+
export { capitalize, initials, isBlank, maskMiddle, normalizeIdentifier, normalizeSpaces, slugify, titleCase, truncate } from './chunk-PTNHOSWH.js';
|
|
7
|
+
export { createRetry, debounce, sleep, throttle, toAsyncState } from './chunk-DKWI2AZG.js';
|
|
8
|
+
export { cn, toneClass } from './chunk-BMNZVRFN.js';
|
|
9
|
+
export { canCopy, copyText, readText } from './chunk-RIFUQ7JM.js';
|
|
10
|
+
export { averageBy, chunk, compact, groupBy, isDefined, keyBy, move, partition, range, sortBy, sum, sumBy, toggleItem, unique, uniqueBy } from './chunk-L4BLBOLO.js';
|
|
11
|
+
export { formatAmount, formatCurrency, getCurrencySymbol, majorToMinor, minorToMajor, parseCurrency } from './chunk-FX7K6FKW.js';
|
|
12
|
+
export { addDays, addMonths, addYears, diffInDays, formatDate, formatDateRange, formatDateTime, formatRelativeDate, formatTimeAgo, getFirstDayOfMonth, getLastDayOfMonth, isPastDate, parseDate, subDays, subMonths, subYears, toDisplayDate, toIsoDate } from './chunk-JHYMIU2G.js';
|
|
13
|
+
export { composeEventHandlers } from './chunk-YU5NRSDP.js';
|
package/dist/locale.cjs
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/locale.ts
|
|
4
|
+
var DEFAULT_LOCALE = "fr-FR";
|
|
5
|
+
function resolveLocale(preferred) {
|
|
6
|
+
if (preferred) return preferred;
|
|
7
|
+
if (typeof navigator !== "undefined" && navigator.language) {
|
|
8
|
+
return navigator.language;
|
|
9
|
+
}
|
|
10
|
+
return DEFAULT_LOCALE;
|
|
11
|
+
}
|
|
12
|
+
function languageOf(locale = DEFAULT_LOCALE) {
|
|
13
|
+
return locale.split("-")[0] ?? locale;
|
|
14
|
+
}
|
|
15
|
+
function regionOf(locale = DEFAULT_LOCALE) {
|
|
16
|
+
return locale.split("-")[1];
|
|
17
|
+
}
|
|
18
|
+
var collators = /* @__PURE__ */ new Map();
|
|
19
|
+
function collator(locale = DEFAULT_LOCALE) {
|
|
20
|
+
let found = collators.get(locale);
|
|
21
|
+
if (!found) {
|
|
22
|
+
found = new Intl.Collator(locale, { sensitivity: "base", numeric: true });
|
|
23
|
+
collators.set(locale, found);
|
|
24
|
+
}
|
|
25
|
+
return found;
|
|
26
|
+
}
|
|
27
|
+
function compareStrings(a, b, locale = DEFAULT_LOCALE) {
|
|
28
|
+
return collator(locale).compare(a, b);
|
|
29
|
+
}
|
|
30
|
+
function looseIncludes(text, needle, locale = DEFAULT_LOCALE) {
|
|
31
|
+
if (!needle) return true;
|
|
32
|
+
const strip = (value) => value.toLocaleLowerCase(locale).normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
33
|
+
return strip(text).includes(strip(needle));
|
|
34
|
+
}
|
|
35
|
+
function formatList(items, options = {}) {
|
|
36
|
+
const { locale = DEFAULT_LOCALE, type = "conjunction" } = options;
|
|
37
|
+
if (items.length === 0) return "";
|
|
38
|
+
return new Intl.ListFormat(locale, { style: "long", type }).format(items);
|
|
39
|
+
}
|
|
40
|
+
function plural(count, singular, pluralForm) {
|
|
41
|
+
return Math.abs(count) < 2 ? singular : pluralForm ?? `${singular}s`;
|
|
42
|
+
}
|
|
43
|
+
function countLabel(count, singular, options = {}) {
|
|
44
|
+
const { pluralForm, zero, locale = DEFAULT_LOCALE } = options;
|
|
45
|
+
if (count === 0 && zero) return zero;
|
|
46
|
+
return `${count.toLocaleString(locale)} ${plural(count, singular, pluralForm)}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
|
|
50
|
+
exports.collator = collator;
|
|
51
|
+
exports.compareStrings = compareStrings;
|
|
52
|
+
exports.countLabel = countLabel;
|
|
53
|
+
exports.formatList = formatList;
|
|
54
|
+
exports.languageOf = languageOf;
|
|
55
|
+
exports.looseIncludes = looseIncludes;
|
|
56
|
+
exports.plural = plural;
|
|
57
|
+
exports.regionOf = regionOf;
|
|
58
|
+
exports.resolveLocale = resolveLocale;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Langue et région.
|
|
3
|
+
*
|
|
4
|
+
* Le dépôt écrit `"fr-FR"` en dur à une douzaine d'endroits. Ce module donne
|
|
5
|
+
* le seul défaut, et la façon d'en changer.
|
|
6
|
+
*/
|
|
7
|
+
declare const DEFAULT_LOCALE = "fr-FR";
|
|
8
|
+
/**
|
|
9
|
+
* La locale à utiliser.
|
|
10
|
+
*
|
|
11
|
+
* Ordre : ce qui est demandé, puis la préférence du navigateur, puis le
|
|
12
|
+
* français. La préférence du navigateur n'est lue qu'à défaut — une
|
|
13
|
+
* application de gestion camerounaise ne doit pas passer en anglais parce que
|
|
14
|
+
* le poste est configuré ainsi.
|
|
15
|
+
*/
|
|
16
|
+
declare function resolveLocale(preferred?: string | null): string;
|
|
17
|
+
/** La langue seule : `fr` pour `fr-FR`. */
|
|
18
|
+
declare function languageOf(locale?: string): string;
|
|
19
|
+
/** La région seule : `FR` pour `fr-FR`, `undefined` pour `fr`. */
|
|
20
|
+
declare function regionOf(locale?: string): string | undefined;
|
|
21
|
+
/** Comparateur de chaînes localisé, réutilisé d'un appel à l'autre. */
|
|
22
|
+
declare function collator(locale?: string): Intl.Collator;
|
|
23
|
+
/** Compare deux chaînes : « Émile » se range avant « Zoé ». */
|
|
24
|
+
declare function compareStrings(a: string, b: string, locale?: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Vrai si le texte contient la recherche, accents et casse ignorés.
|
|
27
|
+
*
|
|
28
|
+
* C'est ce qu'attend quiconque tape « cote » pour trouver « Côte d'Ivoire ».
|
|
29
|
+
*/
|
|
30
|
+
declare function looseIncludes(text: string, needle: string, locale?: string): boolean;
|
|
31
|
+
interface ListFormatOptions {
|
|
32
|
+
locale?: string;
|
|
33
|
+
type?: "conjunction" | "disjunction";
|
|
34
|
+
}
|
|
35
|
+
/** « Douala, Yaoundé et Bafoussam ». */
|
|
36
|
+
declare function formatList(items: readonly string[], options?: ListFormatOptions): string;
|
|
37
|
+
/**
|
|
38
|
+
* Accorde un mot avec un nombre.
|
|
39
|
+
*
|
|
40
|
+
* Règle française, pas anglaise : le singulier couvre `0` et `1`, le pluriel
|
|
41
|
+
* commence à `2`. « 0 facture » et non « 0 factures ».
|
|
42
|
+
*/
|
|
43
|
+
declare function plural(count: number, singular: string, pluralForm?: string): string;
|
|
44
|
+
/** « 1 facture », « 3 factures », « aucune facture ». */
|
|
45
|
+
declare function countLabel(count: number, singular: string, options?: {
|
|
46
|
+
pluralForm?: string;
|
|
47
|
+
zero?: string;
|
|
48
|
+
locale?: string;
|
|
49
|
+
}): string;
|
|
50
|
+
|
|
51
|
+
export { DEFAULT_LOCALE, type ListFormatOptions, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale };
|
package/dist/locale.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Langue et région.
|
|
3
|
+
*
|
|
4
|
+
* Le dépôt écrit `"fr-FR"` en dur à une douzaine d'endroits. Ce module donne
|
|
5
|
+
* le seul défaut, et la façon d'en changer.
|
|
6
|
+
*/
|
|
7
|
+
declare const DEFAULT_LOCALE = "fr-FR";
|
|
8
|
+
/**
|
|
9
|
+
* La locale à utiliser.
|
|
10
|
+
*
|
|
11
|
+
* Ordre : ce qui est demandé, puis la préférence du navigateur, puis le
|
|
12
|
+
* français. La préférence du navigateur n'est lue qu'à défaut — une
|
|
13
|
+
* application de gestion camerounaise ne doit pas passer en anglais parce que
|
|
14
|
+
* le poste est configuré ainsi.
|
|
15
|
+
*/
|
|
16
|
+
declare function resolveLocale(preferred?: string | null): string;
|
|
17
|
+
/** La langue seule : `fr` pour `fr-FR`. */
|
|
18
|
+
declare function languageOf(locale?: string): string;
|
|
19
|
+
/** La région seule : `FR` pour `fr-FR`, `undefined` pour `fr`. */
|
|
20
|
+
declare function regionOf(locale?: string): string | undefined;
|
|
21
|
+
/** Comparateur de chaînes localisé, réutilisé d'un appel à l'autre. */
|
|
22
|
+
declare function collator(locale?: string): Intl.Collator;
|
|
23
|
+
/** Compare deux chaînes : « Émile » se range avant « Zoé ». */
|
|
24
|
+
declare function compareStrings(a: string, b: string, locale?: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Vrai si le texte contient la recherche, accents et casse ignorés.
|
|
27
|
+
*
|
|
28
|
+
* C'est ce qu'attend quiconque tape « cote » pour trouver « Côte d'Ivoire ».
|
|
29
|
+
*/
|
|
30
|
+
declare function looseIncludes(text: string, needle: string, locale?: string): boolean;
|
|
31
|
+
interface ListFormatOptions {
|
|
32
|
+
locale?: string;
|
|
33
|
+
type?: "conjunction" | "disjunction";
|
|
34
|
+
}
|
|
35
|
+
/** « Douala, Yaoundé et Bafoussam ». */
|
|
36
|
+
declare function formatList(items: readonly string[], options?: ListFormatOptions): string;
|
|
37
|
+
/**
|
|
38
|
+
* Accorde un mot avec un nombre.
|
|
39
|
+
*
|
|
40
|
+
* Règle française, pas anglaise : le singulier couvre `0` et `1`, le pluriel
|
|
41
|
+
* commence à `2`. « 0 facture » et non « 0 factures ».
|
|
42
|
+
*/
|
|
43
|
+
declare function plural(count: number, singular: string, pluralForm?: string): string;
|
|
44
|
+
/** « 1 facture », « 3 factures », « aucune facture ». */
|
|
45
|
+
declare function countLabel(count: number, singular: string, options?: {
|
|
46
|
+
pluralForm?: string;
|
|
47
|
+
zero?: string;
|
|
48
|
+
locale?: string;
|
|
49
|
+
}): string;
|
|
50
|
+
|
|
51
|
+
export { DEFAULT_LOCALE, type ListFormatOptions, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale };
|
package/dist/locale.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DEFAULT_LOCALE, collator, compareStrings, countLabel, formatList, languageOf, looseIncludes, plural, regionOf, resolveLocale } from './chunk-6P4YWHCJ.js';
|
package/dist/number.cjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/number.ts
|
|
4
|
+
function formatter(locale, options) {
|
|
5
|
+
return new Intl.NumberFormat(locale, options);
|
|
6
|
+
}
|
|
7
|
+
function formatNumber(value, options = {}) {
|
|
8
|
+
const { locale = "fr-FR", ...formatOptions } = options;
|
|
9
|
+
return formatter(locale, { maximumFractionDigits: 2, ...formatOptions }).format(value);
|
|
10
|
+
}
|
|
11
|
+
function formatPercent(value, options = {}) {
|
|
12
|
+
const { locale = "fr-FR", ...formatOptions } = options;
|
|
13
|
+
return formatter(locale, {
|
|
14
|
+
style: "percent",
|
|
15
|
+
maximumFractionDigits: 2,
|
|
16
|
+
...formatOptions
|
|
17
|
+
}).format(value);
|
|
18
|
+
}
|
|
19
|
+
function clamp(value, min, max) {
|
|
20
|
+
return Math.min(Math.max(value, min), max);
|
|
21
|
+
}
|
|
22
|
+
function round(value, digits = 0) {
|
|
23
|
+
const factor = 10 ** digits;
|
|
24
|
+
return Math.round(value * factor) / factor;
|
|
25
|
+
}
|
|
26
|
+
function toNumber(value, fallback = 0) {
|
|
27
|
+
if (typeof value === "number") return value;
|
|
28
|
+
if (typeof value === "string") {
|
|
29
|
+
const parsed = Number(value);
|
|
30
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
31
|
+
}
|
|
32
|
+
return fallback;
|
|
33
|
+
}
|
|
34
|
+
function parseDecimal(value) {
|
|
35
|
+
const parsed = Number(value);
|
|
36
|
+
if (!Number.isFinite(parsed)) {
|
|
37
|
+
throw new Error("The provided numeric value is invalid.");
|
|
38
|
+
}
|
|
39
|
+
return parsed;
|
|
40
|
+
}
|
|
41
|
+
function roundCurrency(value) {
|
|
42
|
+
return Math.round((value + Number.EPSILON) * 100) / 100;
|
|
43
|
+
}
|
|
44
|
+
function formatRate(value) {
|
|
45
|
+
return value.toFixed(4);
|
|
46
|
+
}
|
|
47
|
+
function safeDivide(a, b, fallback = 0) {
|
|
48
|
+
if (b === 0) return fallback;
|
|
49
|
+
const result = a / b;
|
|
50
|
+
return Number.isFinite(result) ? result : fallback;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
exports.clamp = clamp;
|
|
54
|
+
exports.formatNumber = formatNumber;
|
|
55
|
+
exports.formatPercent = formatPercent;
|
|
56
|
+
exports.formatRate = formatRate;
|
|
57
|
+
exports.parseDecimal = parseDecimal;
|
|
58
|
+
exports.round = round;
|
|
59
|
+
exports.roundCurrency = roundCurrency;
|
|
60
|
+
exports.safeDivide = safeDivide;
|
|
61
|
+
exports.toNumber = toNumber;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface NumberFormatOptions extends Intl.NumberFormatOptions {
|
|
2
|
+
locale?: string;
|
|
3
|
+
}
|
|
4
|
+
declare function formatNumber(value: number, options?: NumberFormatOptions): string;
|
|
5
|
+
declare function formatPercent(value: number, options?: NumberFormatOptions): string;
|
|
6
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
7
|
+
declare function round(value: number, digits?: number): number;
|
|
8
|
+
declare function toNumber(value: number | string | null | undefined, fallback?: number): number;
|
|
9
|
+
declare function parseDecimal(value: string | number): number;
|
|
10
|
+
declare function roundCurrency(value: number): number;
|
|
11
|
+
declare function formatRate(value: number): string;
|
|
12
|
+
declare function safeDivide(a: number, b: number, fallback?: number): number;
|
|
13
|
+
|
|
14
|
+
export { type NumberFormatOptions, clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber };
|
package/dist/number.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface NumberFormatOptions extends Intl.NumberFormatOptions {
|
|
2
|
+
locale?: string;
|
|
3
|
+
}
|
|
4
|
+
declare function formatNumber(value: number, options?: NumberFormatOptions): string;
|
|
5
|
+
declare function formatPercent(value: number, options?: NumberFormatOptions): string;
|
|
6
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
7
|
+
declare function round(value: number, digits?: number): number;
|
|
8
|
+
declare function toNumber(value: number | string | null | undefined, fallback?: number): number;
|
|
9
|
+
declare function parseDecimal(value: string | number): number;
|
|
10
|
+
declare function roundCurrency(value: number): number;
|
|
11
|
+
declare function formatRate(value: number): string;
|
|
12
|
+
declare function safeDivide(a: number, b: number, fallback?: number): number;
|
|
13
|
+
|
|
14
|
+
export { type NumberFormatOptions, clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber };
|
package/dist/number.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { clamp, formatNumber, formatPercent, formatRate, parseDecimal, round, roundCurrency, safeDivide, toNumber } from './chunk-63IWZEOC.js';
|
package/dist/object.cjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/object.ts
|
|
4
|
+
function isPlainObject(value) {
|
|
5
|
+
if (typeof value !== "object" || value === null) return false;
|
|
6
|
+
if (Array.isArray(value)) return false;
|
|
7
|
+
const proto = Object.getPrototypeOf(value);
|
|
8
|
+
return proto === Object.prototype || proto === null;
|
|
9
|
+
}
|
|
10
|
+
function pick(source, keys) {
|
|
11
|
+
const out = {};
|
|
12
|
+
for (const key of keys) {
|
|
13
|
+
if (key in source) out[key] = source[key];
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function omit(source, keys) {
|
|
18
|
+
const out = { ...source };
|
|
19
|
+
for (const key of keys) delete out[key];
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
function isEmpty(value) {
|
|
23
|
+
if (value === null || value === void 0) return true;
|
|
24
|
+
if (typeof value === "string") return value.trim().length === 0;
|
|
25
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
26
|
+
if (value instanceof Map || value instanceof Set) return value.size === 0;
|
|
27
|
+
if (isPlainObject(value)) return Object.keys(value).length === 0;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
function deepMerge(base, patch) {
|
|
31
|
+
const out = { ...base };
|
|
32
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
33
|
+
if (value === void 0) continue;
|
|
34
|
+
const current = out[key];
|
|
35
|
+
out[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function getPath(source, path, fallback) {
|
|
40
|
+
const segments = path.split(".").filter(Boolean);
|
|
41
|
+
let current = source;
|
|
42
|
+
for (const segment of segments) {
|
|
43
|
+
if (current === null || current === void 0) return fallback;
|
|
44
|
+
if (typeof current !== "object") return fallback;
|
|
45
|
+
current = current[segment];
|
|
46
|
+
}
|
|
47
|
+
return current ?? fallback;
|
|
48
|
+
}
|
|
49
|
+
function setPath(source, path, value) {
|
|
50
|
+
const segments = path.split(".").filter(Boolean);
|
|
51
|
+
if (segments.length === 0) return source;
|
|
52
|
+
const [head, ...rest] = segments;
|
|
53
|
+
const child = source[head];
|
|
54
|
+
return {
|
|
55
|
+
...source,
|
|
56
|
+
[head]: rest.length === 0 ? value : setPath(isPlainObject(child) ? child : {}, rest.join("."), value)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function isEqual(a, b) {
|
|
60
|
+
if (Object.is(a, b)) return true;
|
|
61
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
62
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
63
|
+
return a.length === b.length && a.every((item, i) => isEqual(item, b[i]));
|
|
64
|
+
}
|
|
65
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
66
|
+
const keys = Object.keys(a);
|
|
67
|
+
if (keys.length !== Object.keys(b).length) return false;
|
|
68
|
+
return keys.every((key) => key in b && isEqual(a[key], b[key]));
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
function diff(before, after) {
|
|
73
|
+
const out = {};
|
|
74
|
+
for (const [key, value] of Object.entries(after)) {
|
|
75
|
+
if (!isEqual(before[key], value)) out[key] = value;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
exports.deepMerge = deepMerge;
|
|
81
|
+
exports.diff = diff;
|
|
82
|
+
exports.getPath = getPath;
|
|
83
|
+
exports.isEmpty = isEmpty;
|
|
84
|
+
exports.isEqual = isEqual;
|
|
85
|
+
exports.omit = omit;
|
|
86
|
+
exports.pick = pick;
|
|
87
|
+
exports.setPath = setPath;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Objets. */
|
|
2
|
+
type Plain = Record<string, unknown>;
|
|
3
|
+
/** Garde uniquement les clés demandées. */
|
|
4
|
+
declare function pick<T extends object, K extends keyof T>(source: T, keys: readonly K[]): Pick<T, K>;
|
|
5
|
+
/** Retire les clés demandées. */
|
|
6
|
+
declare function omit<T extends object, K extends keyof T>(source: T, keys: readonly K[]): Omit<T, K>;
|
|
7
|
+
/** Vrai pour `{}`, `[]`, `""`, `null`, `undefined`, une `Map` vide. */
|
|
8
|
+
declare function isEmpty(value: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Le correctif d'une fusion profonde.
|
|
11
|
+
*
|
|
12
|
+
* `Partial<T>` ne rend facultatif que le premier niveau : passer
|
|
13
|
+
* `{ nested: { y: 9 } }` exigerait alors de réécrire tout `nested`, ce qui
|
|
14
|
+
* annule l'intérêt de la fusion. Les types qui ne se fusionnent pas champ
|
|
15
|
+
* par champ — tableau, `Date`, `File`, `Map`, `Set` — sont laissés entiers.
|
|
16
|
+
*/
|
|
17
|
+
type DeepPartial<T> = T extends readonly unknown[] | Date | File | Blob | Map<unknown, unknown> | Set<unknown> ? T : T extends object ? {
|
|
18
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
19
|
+
} : T;
|
|
20
|
+
/**
|
|
21
|
+
* Fusionne en profondeur, sans modifier les objets d'origine.
|
|
22
|
+
*
|
|
23
|
+
* Les tableaux sont **remplacés**, jamais concaténés : une liste d'options
|
|
24
|
+
* fusionnée se retrouverait sinon avec les valeurs par défaut collées aux
|
|
25
|
+
* nouvelles, ce que personne n'attend.
|
|
26
|
+
*/
|
|
27
|
+
declare function deepMerge<T extends Plain>(base: T, patch: DeepPartial<T>): T;
|
|
28
|
+
/**
|
|
29
|
+
* Lit une valeur par son chemin : `get(client, "adresse.ville")`.
|
|
30
|
+
*
|
|
31
|
+
* Utile pour une colonne de tableau décrite par une chaîne, ou un message
|
|
32
|
+
* d'erreur du serveur dont le champ est `adresse.ville`.
|
|
33
|
+
*/
|
|
34
|
+
declare function getPath<T = unknown>(source: unknown, path: string, fallback?: T): T | undefined;
|
|
35
|
+
/** Écrit une valeur par son chemin, en rendant une copie. */
|
|
36
|
+
declare function setPath<T extends Plain>(source: T, path: string, value: unknown): T;
|
|
37
|
+
/**
|
|
38
|
+
* Compare deux valeurs en profondeur.
|
|
39
|
+
*
|
|
40
|
+
* Volontairement limitée aux objets simples, tableaux, dates et primitives :
|
|
41
|
+
* c'est tout ce qu'on compare dans une interface, et une comparaison
|
|
42
|
+
* universelle coûte plus qu'elle ne rapporte.
|
|
43
|
+
*/
|
|
44
|
+
declare function isEqual(a: unknown, b: unknown): boolean;
|
|
45
|
+
/** Ce qui a changé entre deux objets — pour un `PATCH` minimal. */
|
|
46
|
+
declare function diff<T extends Plain>(before: T, after: T): Partial<T>;
|
|
47
|
+
|
|
48
|
+
export { type DeepPartial, deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath };
|
package/dist/object.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Objets. */
|
|
2
|
+
type Plain = Record<string, unknown>;
|
|
3
|
+
/** Garde uniquement les clés demandées. */
|
|
4
|
+
declare function pick<T extends object, K extends keyof T>(source: T, keys: readonly K[]): Pick<T, K>;
|
|
5
|
+
/** Retire les clés demandées. */
|
|
6
|
+
declare function omit<T extends object, K extends keyof T>(source: T, keys: readonly K[]): Omit<T, K>;
|
|
7
|
+
/** Vrai pour `{}`, `[]`, `""`, `null`, `undefined`, une `Map` vide. */
|
|
8
|
+
declare function isEmpty(value: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Le correctif d'une fusion profonde.
|
|
11
|
+
*
|
|
12
|
+
* `Partial<T>` ne rend facultatif que le premier niveau : passer
|
|
13
|
+
* `{ nested: { y: 9 } }` exigerait alors de réécrire tout `nested`, ce qui
|
|
14
|
+
* annule l'intérêt de la fusion. Les types qui ne se fusionnent pas champ
|
|
15
|
+
* par champ — tableau, `Date`, `File`, `Map`, `Set` — sont laissés entiers.
|
|
16
|
+
*/
|
|
17
|
+
type DeepPartial<T> = T extends readonly unknown[] | Date | File | Blob | Map<unknown, unknown> | Set<unknown> ? T : T extends object ? {
|
|
18
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
19
|
+
} : T;
|
|
20
|
+
/**
|
|
21
|
+
* Fusionne en profondeur, sans modifier les objets d'origine.
|
|
22
|
+
*
|
|
23
|
+
* Les tableaux sont **remplacés**, jamais concaténés : une liste d'options
|
|
24
|
+
* fusionnée se retrouverait sinon avec les valeurs par défaut collées aux
|
|
25
|
+
* nouvelles, ce que personne n'attend.
|
|
26
|
+
*/
|
|
27
|
+
declare function deepMerge<T extends Plain>(base: T, patch: DeepPartial<T>): T;
|
|
28
|
+
/**
|
|
29
|
+
* Lit une valeur par son chemin : `get(client, "adresse.ville")`.
|
|
30
|
+
*
|
|
31
|
+
* Utile pour une colonne de tableau décrite par une chaîne, ou un message
|
|
32
|
+
* d'erreur du serveur dont le champ est `adresse.ville`.
|
|
33
|
+
*/
|
|
34
|
+
declare function getPath<T = unknown>(source: unknown, path: string, fallback?: T): T | undefined;
|
|
35
|
+
/** Écrit une valeur par son chemin, en rendant une copie. */
|
|
36
|
+
declare function setPath<T extends Plain>(source: T, path: string, value: unknown): T;
|
|
37
|
+
/**
|
|
38
|
+
* Compare deux valeurs en profondeur.
|
|
39
|
+
*
|
|
40
|
+
* Volontairement limitée aux objets simples, tableaux, dates et primitives :
|
|
41
|
+
* c'est tout ce qu'on compare dans une interface, et une comparaison
|
|
42
|
+
* universelle coûte plus qu'elle ne rapporte.
|
|
43
|
+
*/
|
|
44
|
+
declare function isEqual(a: unknown, b: unknown): boolean;
|
|
45
|
+
/** Ce qui a changé entre deux objets — pour un `PATCH` minimal. */
|
|
46
|
+
declare function diff<T extends Plain>(before: T, after: T): Partial<T>;
|
|
47
|
+
|
|
48
|
+
export { type DeepPartial, deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath };
|
package/dist/object.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deepMerge, diff, getPath, isEmpty, isEqual, omit, pick, setPath } from './chunk-QMPHN3LG.js';
|
package/dist/query.cjs
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/query.ts
|
|
4
|
+
function serialize(value) {
|
|
5
|
+
if (value instanceof Date) return value.toISOString();
|
|
6
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
7
|
+
return String(value);
|
|
8
|
+
}
|
|
9
|
+
function toQueryString(params, options = {}) {
|
|
10
|
+
if (!params) return "";
|
|
11
|
+
const { prefix = true, skipEmpty = false } = options;
|
|
12
|
+
const entries = Object.entries(params).filter(([, value]) => value !== void 0 && value !== null).flatMap(([key, value]) => {
|
|
13
|
+
const values = Array.isArray(value) ? value : [value];
|
|
14
|
+
return values.filter((item) => item !== void 0 && item !== null).map((item) => serialize(item)).filter((item) => !skipEmpty || item !== "").map(
|
|
15
|
+
(item) => `${encodeURIComponent(key)}=${encodeURIComponent(item)}`
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
if (entries.length === 0) return "";
|
|
19
|
+
return `${prefix ? "?" : ""}${entries.join("&")}`;
|
|
20
|
+
}
|
|
21
|
+
function fromQueryString(search) {
|
|
22
|
+
const params = new URLSearchParams(
|
|
23
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
24
|
+
);
|
|
25
|
+
const out = {};
|
|
26
|
+
for (const [key, value] of params) {
|
|
27
|
+
const existing = out[key];
|
|
28
|
+
if (existing === void 0) out[key] = value;
|
|
29
|
+
else if (Array.isArray(existing)) existing.push(value);
|
|
30
|
+
else out[key] = [existing, value];
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function removeEmptyParams(params) {
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const [key, value] of Object.entries(params)) {
|
|
37
|
+
if (value === null || value === void 0) continue;
|
|
38
|
+
if (value === "") continue;
|
|
39
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
40
|
+
out[key] = value;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
function mergeSearchParams(base, patch, options = {}) {
|
|
45
|
+
const params = new URLSearchParams(
|
|
46
|
+
base.startsWith("?") ? base.slice(1) : base
|
|
47
|
+
);
|
|
48
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
49
|
+
params.delete(key);
|
|
50
|
+
if (value === null || value === void 0) continue;
|
|
51
|
+
const values = Array.isArray(value) ? value : [value];
|
|
52
|
+
for (const item of values) {
|
|
53
|
+
if (item === null || item === void 0) continue;
|
|
54
|
+
params.append(key, serialize(item));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const result = params.toString();
|
|
58
|
+
if (!result) return "";
|
|
59
|
+
return `${options.prefix === false ? "" : "?"}${result}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.fromQueryString = fromQueryString;
|
|
63
|
+
exports.mergeSearchParams = mergeSearchParams;
|
|
64
|
+
exports.removeEmptyParams = removeEmptyParams;
|
|
65
|
+
exports.toQueryString = toQueryString;
|
package/dist/query.d.cts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chaînes de requête.
|
|
3
|
+
*
|
|
4
|
+
* Une seule implémentation pour tout le dépôt : `buildQueryString` de
|
|
5
|
+
* `@sia-ui/api` délègue ici, avec son propre typage. Deux sérialisations qui
|
|
6
|
+
* divergent d'un espace produisent des caches qui ne se recoupent jamais.
|
|
7
|
+
*/
|
|
8
|
+
type QueryValue = string | number | boolean | Date | null | undefined | Record<string, unknown>;
|
|
9
|
+
type QueryParamsInput = Record<string, QueryValue | QueryValue[]>;
|
|
10
|
+
interface ToQueryStringOptions {
|
|
11
|
+
/** Préfixe la chaîne d'un `?` quand elle n'est pas vide. */
|
|
12
|
+
prefix?: boolean;
|
|
13
|
+
/** Retire aussi les chaînes vides et les tableaux vides. */
|
|
14
|
+
skipEmpty?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sérialise un objet en chaîne de requête.
|
|
18
|
+
*
|
|
19
|
+
* `null` et `undefined` sont retirés — envoyer `?statut=undefined` est une
|
|
20
|
+
* source classique de filtre fantôme côté serveur. Un tableau produit une
|
|
21
|
+
* clé répétée, forme que tous les cadres serveur savent lire.
|
|
22
|
+
*/
|
|
23
|
+
declare function toQueryString(params?: QueryParamsInput, options?: ToQueryStringOptions): string;
|
|
24
|
+
/**
|
|
25
|
+
* Lit une chaîne de requête.
|
|
26
|
+
*
|
|
27
|
+
* Une clé répétée rend un tableau, une clé unique rend une chaîne : c'est la
|
|
28
|
+
* forme que `toQueryString` accepte en retour, donc l'aller-retour est sûr.
|
|
29
|
+
*/
|
|
30
|
+
declare function fromQueryString(search: string): Record<string, string | string[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Retire les valeurs qui ne veulent rien dire dans une requête.
|
|
33
|
+
*
|
|
34
|
+
* `null`, `undefined`, la chaîne vide et le tableau vide. Le `0` et le
|
|
35
|
+
* `false` sont **gardés** : ce sont des filtres légitimes, et les perdre est
|
|
36
|
+
* le bogue le plus fréquent de ce genre de fonction.
|
|
37
|
+
*/
|
|
38
|
+
declare function removeEmptyParams<T extends Record<string, unknown>>(params: T): Partial<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Applique un correctif à une chaîne de requête existante.
|
|
41
|
+
*
|
|
42
|
+
* Une valeur `null` ou `undefined` **retire** la clé : c'est ce qui permet
|
|
43
|
+
* d'écrire `mergeSearchParams(location.search, { page: 2, statut: null })`
|
|
44
|
+
* sans reconstruire tout l'état.
|
|
45
|
+
*/
|
|
46
|
+
declare function mergeSearchParams(base: string, patch: QueryParamsInput, options?: ToQueryStringOptions): string;
|
|
47
|
+
|
|
48
|
+
export { type QueryParamsInput, type QueryValue, type ToQueryStringOptions, fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString };
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chaînes de requête.
|
|
3
|
+
*
|
|
4
|
+
* Une seule implémentation pour tout le dépôt : `buildQueryString` de
|
|
5
|
+
* `@sia-ui/api` délègue ici, avec son propre typage. Deux sérialisations qui
|
|
6
|
+
* divergent d'un espace produisent des caches qui ne se recoupent jamais.
|
|
7
|
+
*/
|
|
8
|
+
type QueryValue = string | number | boolean | Date | null | undefined | Record<string, unknown>;
|
|
9
|
+
type QueryParamsInput = Record<string, QueryValue | QueryValue[]>;
|
|
10
|
+
interface ToQueryStringOptions {
|
|
11
|
+
/** Préfixe la chaîne d'un `?` quand elle n'est pas vide. */
|
|
12
|
+
prefix?: boolean;
|
|
13
|
+
/** Retire aussi les chaînes vides et les tableaux vides. */
|
|
14
|
+
skipEmpty?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sérialise un objet en chaîne de requête.
|
|
18
|
+
*
|
|
19
|
+
* `null` et `undefined` sont retirés — envoyer `?statut=undefined` est une
|
|
20
|
+
* source classique de filtre fantôme côté serveur. Un tableau produit une
|
|
21
|
+
* clé répétée, forme que tous les cadres serveur savent lire.
|
|
22
|
+
*/
|
|
23
|
+
declare function toQueryString(params?: QueryParamsInput, options?: ToQueryStringOptions): string;
|
|
24
|
+
/**
|
|
25
|
+
* Lit une chaîne de requête.
|
|
26
|
+
*
|
|
27
|
+
* Une clé répétée rend un tableau, une clé unique rend une chaîne : c'est la
|
|
28
|
+
* forme que `toQueryString` accepte en retour, donc l'aller-retour est sûr.
|
|
29
|
+
*/
|
|
30
|
+
declare function fromQueryString(search: string): Record<string, string | string[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Retire les valeurs qui ne veulent rien dire dans une requête.
|
|
33
|
+
*
|
|
34
|
+
* `null`, `undefined`, la chaîne vide et le tableau vide. Le `0` et le
|
|
35
|
+
* `false` sont **gardés** : ce sont des filtres légitimes, et les perdre est
|
|
36
|
+
* le bogue le plus fréquent de ce genre de fonction.
|
|
37
|
+
*/
|
|
38
|
+
declare function removeEmptyParams<T extends Record<string, unknown>>(params: T): Partial<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Applique un correctif à une chaîne de requête existante.
|
|
41
|
+
*
|
|
42
|
+
* Une valeur `null` ou `undefined` **retire** la clé : c'est ce qui permet
|
|
43
|
+
* d'écrire `mergeSearchParams(location.search, { page: 2, statut: null })`
|
|
44
|
+
* sans reconstruire tout l'état.
|
|
45
|
+
*/
|
|
46
|
+
declare function mergeSearchParams(base: string, patch: QueryParamsInput, options?: ToQueryStringOptions): string;
|
|
47
|
+
|
|
48
|
+
export { type QueryParamsInput, type QueryValue, type ToQueryStringOptions, fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString };
|
package/dist/query.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { fromQueryString, mergeSearchParams, removeEmptyParams, toQueryString } from './chunk-DY6WSWXH.js';
|