@carto/ps-utils 2.0.1 → 2.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 (46) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +436 -74
  4. package/dist/index.js.map +1 -1
  5. package/dist/types/clipboard/copy.d.ts +4 -6
  6. package/dist/types/colors/carto-palettes/carto-palettes.d.ts +47 -0
  7. package/dist/types/colors/hex-to-rgba/hex-to-rgba.d.ts +7 -16
  8. package/dist/types/colors/palette-to-hex/palette-to-hex.d.ts +19 -0
  9. package/dist/types/colors/palette-to-hex/palette-to-hex.test.d.ts +1 -0
  10. package/dist/types/colors/rgba-to-hex/rgba-to-hex.d.ts +7 -19
  11. package/dist/types/debounce/debounce.d.ts +12 -2
  12. package/dist/types/formatters/constants.d.ts +23 -1
  13. package/dist/types/formatters/date/format-date.d.ts +13 -8
  14. package/dist/types/formatters/number/format-number.d.ts +17 -20
  15. package/dist/types/index.d.ts +3 -0
  16. package/dist/types/strings/match-text/match-text.d.ts +10 -6
  17. package/dist/types/strings/normalize/normalize.d.ts +6 -9
  18. package/dist/types/strings/routes/replace-route.d.ts +10 -14
  19. package/package.json +7 -3
  20. package/src/clipboard/copy.test.ts +49 -0
  21. package/src/clipboard/copy.ts +18 -0
  22. package/src/colors/carto-palettes/carto-palettes.ts +355 -0
  23. package/src/colors/hex-to-rgba/hex-to-rgba.test.ts +82 -0
  24. package/src/colors/hex-to-rgba/hex-to-rgba.ts +67 -0
  25. package/src/colors/palette-to-hex/palette-to-hex.test.ts +60 -0
  26. package/src/colors/palette-to-hex/palette-to-hex.ts +45 -0
  27. package/src/colors/rgba-to-hex/rgba-to-hex.test.ts +34 -0
  28. package/src/colors/rgba-to-hex/rgba-to-hex.ts +42 -0
  29. package/src/colors/rgba-to-hex/types.ts +9 -0
  30. package/src/debounce/debounce.test.ts +21 -0
  31. package/src/debounce/debounce.ts +29 -0
  32. package/src/formatters/constants.ts +49 -0
  33. package/src/formatters/date/format-date.test.ts +36 -0
  34. package/src/formatters/date/format-date.ts +34 -0
  35. package/src/formatters/number/format-number.test.ts +49 -0
  36. package/src/formatters/number/format-number.ts +68 -0
  37. package/src/index.ts +18 -0
  38. package/src/strings/match-text/match-text.test.ts +38 -0
  39. package/src/strings/match-text/match-text.ts +36 -0
  40. package/src/strings/match-text/types.ts +15 -0
  41. package/src/strings/normalize/normalize.test.ts +12 -0
  42. package/src/strings/normalize/normalize.ts +22 -0
  43. package/src/strings/normalize/types.ts +15 -0
  44. package/src/strings/routes/replace-route.test.ts +64 -0
  45. package/src/strings/routes/replace-route.ts +39 -0
  46. package/src/strings/routes/types.ts +2 -0
@@ -1,14 +1,12 @@
1
1
  /**
2
- * This function is a helper function to copy text to the clipboard.
3
- *
4
- * @param {string} text - The text to copy to the clipboard.
5
- *
6
- * @returns {void}
2
+ * Asynchronously copies text content to the user's clipboard using the Clipboard API.
7
3
  *
4
+ * @param text - The text content to copy to the clipboard.
5
+ * @returns A promise that resolves when the text is successfully copied, or rejects with an error.
8
6
  *
9
7
  * @example
10
8
  * ```ts
11
- * copy('Hello world!')
9
+ * await copy('Hello world!')
12
10
  * ```
13
11
  */
14
12
  export declare function copy(text: string): Promise<void>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * CARTOColors palettes (name -> hex ramp), full CARTO-native set: sequential
3
+ * (incl. aggregation), diverging and qualitative. Each entry is the palette's
4
+ * largest class-count ramp, verbatim. Kept inline so the package stays
5
+ * zero-dependency; ColorBrewer (`cb_*`) palettes are intentionally excluded.
6
+ *
7
+ * Data: CARTOColors - https://github.com/CartoDB/cartocolor - CC-BY-4.0.
8
+ * Generated from cartocolor@5.0.2 (unmodified beyond taking each max ramp).
9
+ */
10
+ export declare const CARTO_PALETTES: {
11
+ ag_GrnYl: string[];
12
+ ag_Sunset: string[];
13
+ BluGrn: string[];
14
+ BluYl: string[];
15
+ BrwnYl: string[];
16
+ Burg: string[];
17
+ BurgYl: string[];
18
+ DarkMint: string[];
19
+ Emrld: string[];
20
+ Magenta: string[];
21
+ Mint: string[];
22
+ OrYel: string[];
23
+ Peach: string[];
24
+ PinkYl: string[];
25
+ Purp: string[];
26
+ PurpOr: string[];
27
+ RedOr: string[];
28
+ Sunset: string[];
29
+ SunsetDark: string[];
30
+ Teal: string[];
31
+ TealGrn: string[];
32
+ ArmyRose: string[];
33
+ Earth: string[];
34
+ Fall: string[];
35
+ Geyser: string[];
36
+ TealRose: string[];
37
+ Temps: string[];
38
+ Tropic: string[];
39
+ Antique: string[];
40
+ Bold: string[];
41
+ Pastel: string[];
42
+ Prism: string[];
43
+ Safe: string[];
44
+ Vivid: string[];
45
+ };
46
+ /** A known CARTOColors palette name. */
47
+ export type PaletteName = keyof typeof CARTO_PALETTES;
@@ -1,24 +1,15 @@
1
1
  /**
2
- * It converts a hexadecimal color to an array of numbers
2
+ * Converts a hexadecimal color string to an RGBA array, useful for deck.gl layer styling and canvas operations.
3
3
  *
4
- * @param {string} hexadecimal - hexadecimal string, including # or not
5
- * @param {number} alpha - opacity of final color, value must be between 0-1
6
- *
7
- * @returns An array of numbers.
4
+ * @param hexadecimal - Hex color string (supports `#ffffff`, `ffffff`, `#fff`, `fff`, `#ff` formats).
5
+ * @param alpha - Opacity level from 0 (transparent) to 1 (opaque). Default is `1`.
6
+ * @returns An `[r, g, b, a]` array with values 0-255, or `undefined` for invalid inputs.
8
7
  *
9
8
  * @example
10
- *
11
- * 6 digits hexadecimal:
12
- * ```ts
13
- * hexToRgba('#d1d1d1', 1)
14
- * ```
15
- * 3 digits hexadecimal:
16
- * ```ts
17
- * hexToRgba('#d1d', 1)
18
- * ```
19
- * 2 digits hexadecimal:
20
9
  * ```ts
21
- * hexToRgba('#d1', 1)
10
+ * hexToRgba('#ff0000', 0.8) // [255, 0, 0, 204]
11
+ * hexToRgba('#f00', 0.5) // [255, 0, 0, 127.5]
12
+ * hexToRgba('00ff00') // [0, 255, 0, 255]
22
13
  * ```
23
14
  */
24
15
  export declare function hexToRgba(hexadecimal: string, alpha?: number): [number, number, number, number] | undefined;
@@ -0,0 +1,19 @@
1
+ import { PaletteName } from '../carto-palettes/carto-palettes';
2
+ /**
3
+ * Resolves a CARTOColors palette name to its hex ramp.
4
+ *
5
+ * Matching is case-insensitive (`'sunset'` resolves `'Sunset'`). Returns the
6
+ * palette's largest class-count ramp. To get RGBA tuples, compose with
7
+ * `hexToRgba`: `paletteToHex('Sunset')?.map((hex) => hexToRgba(hex))`.
8
+ *
9
+ * @param name - CARTOColors palette name (e.g. `'Sunset'`), any casing.
10
+ * @returns A fresh `string[]` of hex stops (a copy — safe to mutate), or
11
+ * `undefined` for an unknown palette.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * paletteToHex('Sunset') // ['#f3e79b', …, '#5c53a5']
16
+ * paletteToHex('sunset') // ['#f3e79b', …, '#5c53a5']
17
+ * ```
18
+ */
19
+ export declare function paletteToHex(name: PaletteName | (string & {})): string[] | undefined;
@@ -1,28 +1,16 @@
1
1
  import { RgbaToHexOptions } from './types';
2
2
  /**
3
- * It converts an array of RGBA values to a hexadecimal string.
3
+ * Converts an RGBA color array to a hexadecimal string, ideal for converting deck.gl colors to CSS-compatible format.
4
4
  *
5
- * @param {number[]} rgba - rgba array, including alpha or not
6
- * @param {RgbaToHexOptions} options - options to parse
7
- *
8
- * @returns A string
5
+ * @param rgba - Array of RGBA values (each 0-255). Accepts `[r, g, b]` or `[r, g, b, a]`.
6
+ * @param options - Options including `withPrefix` to control `#` prefix (default: `true`).
7
+ * @returns The hex color string, or `undefined` for invalid inputs.
9
8
  *
10
9
  * @example
11
- *
12
- * Without alpha value:
13
- * ```ts
14
- * rgbaDeckGLToHex([0, 0, 0]) // => '#000000'
15
- * ```
16
- *
17
- * With alpha value:
18
10
  * ```ts
19
- * rgbaDeckGLToHex([0, 0, 0, 1]) // => '#000000FF'
11
+ * rgbaToHex([255, 0, 0]) // '#ff0000'
12
+ * rgbaToHex([255, 0, 0, 128]) // '#ff000080'
13
+ * rgbaToHex([0, 255, 0], { withPrefix: false }) // '00ff00'
20
14
  * ```
21
- *
22
- * Without prefix:
23
- * ```ts
24
- * rgbaDeckGLToHex([0, 0, 0], { withPrefix: false }) // => '000000'
25
- * ```
26
- *
27
15
  */
28
16
  export declare function rgbaToHex(rgba: number[] | undefined, { withPrefix }?: RgbaToHexOptions): string | undefined;
@@ -1,7 +1,17 @@
1
1
  /**
2
- * Returns a debounced version of the provided function.
2
+ * Creates a debounced version of a function that delays execution until after the specified wait time has elapsed since the last invocation.
3
+ *
3
4
  * @param func - The function to debounce.
4
- * @param {number} waitFor - The number of milliseconds to wait before invoking the debounced function.
5
+ * @param waitFor - The delay in milliseconds to wait before executing.
5
6
  * @returns A debounced version of the provided function.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const debouncedSearch = debounce((query: string) => {
11
+ * fetchResults(query)
12
+ * }, 300)
13
+ *
14
+ * debouncedSearch('hello') // Only executes after 300ms of inactivity
15
+ * ```
6
16
  */
7
17
  export declare function debounce<F extends (...args: unknown[]) => unknown>(func: F, waitFor: number): (...args: Parameters<F>) => ReturnType<F>;
@@ -1 +1,23 @@
1
- export declare const DEFAULT_FORMATTERS_CONFIG: Record<string, Intl.NumberFormatOptions | Intl.DateTimeFormatOptions>;
1
+ /**
2
+ * Default configuration options for the formatter utilities (`formatNumber`, `formatCurrency`, `formatDate`).
3
+ *
4
+ * @remarks
5
+ * Contains preset `Intl.NumberFormatOptions` and `Intl.DateTimeFormatOptions` for three keys:
6
+ * - `NUMBER` - Compact decimal notation with 1 fraction digit.
7
+ * - `CURRENCY` - Compact USD currency with 2 fraction digits.
8
+ * - `DATE` - Numeric year, 2-digit month and day.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { DEFAULT_FORMATTERS_CONFIG } from '@carto/ps-utils'
13
+ *
14
+ * // Override defaults for a custom number format
15
+ * const options = { ...DEFAULT_FORMATTERS_CONFIG.NUMBER, maximumFractionDigits: 3 }
16
+ * ```
17
+ */
18
+ export type DefaultFormatterKey = 'NUMBER' | 'CURRENCY' | 'DATE';
19
+ export declare const DEFAULT_FORMATTERS_CONFIG: Record<string, Intl.NumberFormatOptions | Intl.DateTimeFormatOptions> & {
20
+ NUMBER: Intl.NumberFormatOptions;
21
+ CURRENCY: Intl.NumberFormatOptions;
22
+ DATE: Intl.DateTimeFormatOptions;
23
+ };
@@ -1,12 +1,17 @@
1
1
  /**
2
- * Formats a Date or number to a string based on the given options.
3
- * This function could be used to format a Date, in Date format or miliseconds, in specific locale and options.
4
- * @public
2
+ * Formats a date or timestamp according to locale-specific conventions using the `Intl.DateTimeFormat` API.
5
3
  *
6
- * @export
7
- * @param {number | Date} value
8
- * @param {string | string[]} locales
9
- * @param {Intl.DateTimeFormatOptions} [options]
10
- * @return {string}
4
+ * @param value - The date to format (Date object or timestamp in milliseconds).
5
+ * @param locales - Locale identifier(s) for formatting (e.g., `'en-US'`, `'fr-FR'`).
6
+ * @param options - Date/time formatting options to override the defaults (numeric year, 2-digit month and day).
7
+ * When `dateStyle` or `timeStyle` is provided the defaults are not applied, as they are incompatible with
8
+ * individual date/time component options.
9
+ * @returns The formatted date string.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * formatDate(new Date('2024-03-15'), 'en-US') // "03/15/2024"
14
+ * formatDate(new Date('2024-03-15'), 'en-US', { month: 'long' }) // "March 15, 2024"
15
+ * ```
11
16
  */
12
17
  export declare function formatDate(value: number | Date, locales: string | string[], options?: Intl.DateTimeFormatOptions): string;
@@ -1,34 +1,31 @@
1
1
  /**
2
- * Formats a number to a string.
3
- * @public
2
+ * Formats a number with locale-aware separators, compact notation, and customizable precision.
4
3
  *
5
- * @example
4
+ * @param value - The number to format.
5
+ * @param locale - The locale identifier (e.g., `'en-US'`, `'es-ES'`).
6
+ * @param options - `Intl.NumberFormatOptions` to override the defaults (compact decimal with 1 fraction digit).
7
+ * @returns The formatted number string.
6
8
  *
9
+ * @example
7
10
  * ```ts
8
- * formatNumber(3001, 'es-ES') // => '3 mil'
11
+ * formatNumber(123456, 'en-US') // "123.5K"
12
+ * formatNumber(1234567, 'en-US') // "1.2M"
13
+ * formatNumber(123456, 'es-ES') // "123 mil"
9
14
  * ```
10
- *
11
- * @export
12
- * @param {number} value - The number to be formatted.
13
- * @param {string} locale - The locale to be used.
14
- * @param {Intl.NumberFormatOptions} [options] - The options to be used.
15
- * @return {string}
16
15
  */
17
16
  export declare function formatNumber(value: number, locale: string, options?: Intl.NumberFormatOptions): string;
18
17
  /**
19
- * Formats a number to a currency string.
20
- * @public
18
+ * Formats a number as a currency value with proper symbols and regional conventions.
21
19
  *
22
- * @example
20
+ * @param value - The monetary value to format.
21
+ * @param locale - The locale identifier (e.g., `'en-US'`, `'fr-FR'`).
22
+ * @param options - `Intl.NumberFormatOptions` to override the defaults (compact USD with 2 fraction digits).
23
+ * @returns The formatted currency string.
23
24
  *
25
+ * @example
24
26
  * ```ts
25
- * formatCurrency(3001, 'en-US') // => '$3.00K'
27
+ * formatCurrency(123456, 'en-US') // "$123.46K"
28
+ * formatCurrency(123456, 'fr-FR', { currency: 'EUR' }) // "123,46 k €"
26
29
  * ```
27
- *
28
- * @export
29
- * @param {number} value - The number to be formatted.
30
- * @param {string} locale - The locale to be used.
31
- * @param {Intl.NumberFormatOptions} [options] - The options to be used.
32
- * @return {string}
33
30
  */
34
31
  export declare function formatCurrency(value: number, locale: string, options?: Intl.NumberFormatOptions): string;
@@ -1,5 +1,8 @@
1
1
  export { copy } from './clipboard/copy';
2
+ export { CARTO_PALETTES } from './colors/carto-palettes/carto-palettes';
3
+ export type { PaletteName } from './colors/carto-palettes/carto-palettes';
2
4
  export { hexToRgba } from './colors/hex-to-rgba/hex-to-rgba';
5
+ export { paletteToHex } from './colors/palette-to-hex/palette-to-hex';
3
6
  export { rgbaToHex } from './colors/rgba-to-hex/rgba-to-hex';
4
7
  export { debounce } from './debounce/debounce';
5
8
  export { DEFAULT_FORMATTERS_CONFIG } from './formatters/constants';
@@ -1,12 +1,16 @@
1
1
  import { MatchTextOptions } from './types';
2
2
  /**
3
- * It takes a string, an array of strings, and an optional object of options, and returns an
4
- * array of strings that match the input string
5
- * @param {string | RegExp} text - The text to match against.
6
- * @param {T[] | string} data - The data to match against.
7
- * @param {MatchTextOptions} options - The options to use.
3
+ * Performs intelligent text matching with optional Unicode normalization and custom matching functions.
8
4
  *
9
- * @returns {T[] | string | null} - The matched data or null.
5
+ * @param value - The text or RegExp pattern to match against.
6
+ * @param data - The data to search (array of items or a single string).
7
+ * @param options - Optional configuration for custom match function and normalization.
8
+ * @returns Matched items from an array, the original string if it matches, or `null`.
10
9
  *
10
+ * @example
11
+ * ```ts
12
+ * matchText('york', ['New York', 'Los Angeles']) // ['New York']
13
+ * matchText('barce', locations, { matchFn: (item) => item.name })
14
+ * ```
11
15
  */
12
16
  export declare function matchText<T>(value: string | RegExp, data: T[] | string, { matchFn, normalizeOptions }?: MatchTextOptions<T>): T[] | string | null;
@@ -1,18 +1,15 @@
1
1
  import { NormalizeOptions } from './types';
2
2
  /**
3
- * It takes a string and returns a string normalized.
4
- * @param {string} data - The data to be normalized.
5
- * @param {NormalizeOptions} options - data - The string to be normalized.
6
- * @returns A string
3
+ * Normalizes a Unicode string by removing diacritics and special characters for consistent text comparison.
7
4
  *
8
- * @remarks
9
- * The normalization by default is NFD
5
+ * @param data - The string to normalize.
6
+ * @param options - Normalization options including Unicode form and replacement pattern.
7
+ * @returns The normalized string with diacritics removed.
10
8
  *
11
9
  * @example
12
- *
13
10
  * ```ts
14
- * normalize('foo bar')
11
+ * normalize('café') // 'cafe'
12
+ * normalize('São Paulo') // 'Sao Paulo'
15
13
  * ```
16
- *
17
14
  */
18
15
  export declare function normalize(data: string, { format, replaceUnicode }?: NormalizeOptions): string;
@@ -1,23 +1,19 @@
1
1
  import { Route, Values } from './types';
2
2
  /**
3
- * Replace route with values from array or object.
4
- * @param {Route} data
5
- * @param {Values} values
3
+ * Dynamically replaces route parameters (`:paramName`) with values from an object or array.
6
4
  *
7
- * @returns {Route}
8
- *
9
- * @example
10
- * ```ts
11
- * replaceRoute('/user/:id', { id: 1 }) // /user/1
12
- * replaceRoute('/user/:id/:name', [1, 'John']) // /user/1/John
13
- * ```
5
+ * @param data - The route template string containing `:paramName` placeholders.
6
+ * @param values - An object or array of values to substitute into the route.
7
+ * @returns The route string with parameters replaced.
14
8
  *
15
9
  * @remarks
16
- * This function is used to replace the route with the values from the array or object. If the values are not found, it will replace it with `undefined`.
10
+ * Missing values are replaced with an empty string.
17
11
  *
12
+ * @example
18
13
  * ```ts
19
- * replaceRoute('/user/:id/:name', [1]) // /user/1/undefined
14
+ * replaceRoute('/user/:id', { id: '123' }) // '/user/123'
15
+ * replaceRoute('/tiles/:z/:x/:y', { z: 10, x: 512, y: 256 }) // '/tiles/10/512/256'
16
+ * replaceRoute('/user/:id/:name', ['123', 'john']) // '/user/123/john'
20
17
  * ```
21
- *
22
- **/
18
+ */
23
19
  export declare function replaceRoute(data: Route, values?: Values): Route;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carto/ps-utils",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "CARTO's Professional Service Helpers library",
5
5
  "type": "module",
6
6
  "dependencies": {},
@@ -19,10 +19,14 @@
19
19
  }
20
20
  },
21
21
  "publishConfig": {
22
- "access": "public"
22
+ "access": "public",
23
+ "files": [
24
+ "dist"
25
+ ]
23
26
  },
24
27
  "files": [
25
- "dist"
28
+ "dist",
29
+ "src"
26
30
  ],
27
31
  "keywords": [
28
32
  "carto",
@@ -0,0 +1,49 @@
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
2
+ import { copy } from './copy'
3
+
4
+ describe('utils :: clipboard :: copy', () => {
5
+ beforeEach(() => {
6
+ let clipboardData = ''
7
+ const mockClipboard = {
8
+ clipboard: {
9
+ writeText: vi.fn((data: string) => {
10
+ clipboardData = data
11
+ }),
12
+ readText: vi.fn(() => {
13
+ return clipboardData
14
+ }),
15
+ },
16
+ }
17
+
18
+ Object.assign(navigator, 'clipboard', {
19
+ ...mockClipboard,
20
+ })
21
+ })
22
+
23
+ afterEach(() => {
24
+ vi.resetAllMocks()
25
+ })
26
+
27
+ /**
28
+ * @jest-environment jsdom
29
+ */
30
+ test('should copy text to clipboard', async () => {
31
+ const data = 'test'
32
+
33
+ try {
34
+ await copy(data)
35
+ } catch (error) {
36
+ // eslint-disable-next-line no-console
37
+ console.error(error)
38
+ }
39
+
40
+ expect(navigator.clipboard.readText()).toBe(data)
41
+ })
42
+
43
+ test('should throw an error if clipboard not defined', async () => {
44
+ Object.defineProperty(navigator, 'clipboard', { value: null })
45
+ const string = 'test'
46
+
47
+ await expect(() => copy(string)).rejects.toThrowError()
48
+ })
49
+ })
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Asynchronously copies text content to the user's clipboard using the Clipboard API.
3
+ *
4
+ * @param text - The text content to copy to the clipboard.
5
+ * @returns A promise that resolves when the text is successfully copied, or rejects with an error.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * await copy('Hello world!')
10
+ * ```
11
+ */
12
+ export async function copy(text: string): Promise<void> {
13
+ try {
14
+ await navigator.clipboard.writeText(text)
15
+ } catch (e: unknown) {
16
+ throw new Error(e as string) // copy failed.
17
+ }
18
+ }