@swan-io/lake 14.0.0 → 15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/lake",
3
- "version": "14.0.0",
3
+ "version": "15.1.0",
4
4
  "engines": {
5
5
  "node": ">22.12.0"
6
6
  },
@@ -28,6 +28,7 @@ type Props = TextProps & {
28
28
  align?: TextAlign;
29
29
  children: ReactNode;
30
30
  color?: string;
31
+ dataSet?: Record<string, unknown>;
31
32
  userSelect?: TextStyle["userSelect"];
32
33
  variant?: TextVariant;
33
34
  tooltip?: Omit<ComponentProps<typeof LakeTooltip>, "children">;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getIconNameFromFilename } from "../file";
3
+ describe("getIconNameFromFilename returns the file type icon based on filename", () => {
4
+ it("returns lake-document-png for a .png file", () => {
5
+ expect(getIconNameFromFilename("photo.png")).toBe("lake-document-png");
6
+ });
7
+ it("returns lake-document-xls for a .xls file", () => {
8
+ expect(getIconNameFromFilename("sheet.xls")).toBe("lake-document-xls");
9
+ });
10
+ it("returns lake-document-pdf for a .pdf file", () => {
11
+ expect(getIconNameFromFilename("report.pdf")).toBe("lake-document-pdf");
12
+ });
13
+ it("returns lake-document-jpg for a .jpg file", () => {
14
+ expect(getIconNameFromFilename("photo.jpg")).toBe("lake-document-jpg");
15
+ });
16
+ it("is case-insensitive on the extension", () => {
17
+ expect(getIconNameFromFilename("REPORT.PDF")).toBe("lake-document-pdf");
18
+ });
19
+ it("uses the last extension when the filename contains multiple dots", () => {
20
+ expect(getIconNameFromFilename("archive.tar.pdf")).toBe("lake-document-pdf");
21
+ });
22
+ it("returns document-regular for an unknown extension", () => {
23
+ expect(getIconNameFromFilename("notes.txt")).toBe("document-regular");
24
+ });
25
+ it("returns document-regular for a filename with no extension", () => {
26
+ expect(getIconNameFromFilename("README")).toBe("document-regular");
27
+ });
28
+ it("returns document-regular for an empty filename", () => {
29
+ expect(getIconNameFromFilename("")).toBe("document-regular");
30
+ });
31
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { filterRejectionsToResult } from "../gql";
3
+ describe("filterRejectionsToResult routes GraphQL union members to Ok or Error based on __typename", () => {
4
+ it("returns an Error when __typename ends with 'Rejection'", () => {
5
+ const input = { __typename: "AccountNotFoundRejection", message: "not found" };
6
+ const result = filterRejectionsToResult(input);
7
+ expect(result.isError()).toBe(true);
8
+ expect(result.isError() && result.getError()).toEqual(input);
9
+ });
10
+ it("returns an Ok when __typename does not end with 'Rejection'", () => {
11
+ const input = { __typename: "Account", id: "abc" };
12
+ const result = filterRejectionsToResult(input);
13
+ expect(result.isOk()).toBe(true);
14
+ expect(result.isOk() && result.get()).toEqual(input);
15
+ });
16
+ it("treats a __typename of exactly 'Rejection' as an Error", () => {
17
+ const input = { __typename: "Rejection" };
18
+ expect(filterRejectionsToResult(input).isError()).toBe(true);
19
+ });
20
+ it("does not match __typename that only contains 'Rejection' as a substring", () => {
21
+ const input = { __typename: "RejectionReason" };
22
+ expect(filterRejectionsToResult(input).isOk()).toBe(true);
23
+ });
24
+ it("treats an empty __typename as an Ok", () => {
25
+ const input = { __typename: "" };
26
+ expect(filterRejectionsToResult(input).isOk()).toBe(true);
27
+ });
28
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { clampValue } from "../math";
3
+ describe("clampValue restricts a number to a given [min, max] range", () => {
4
+ it("returns the value unchanged when it lies within the range", () => {
5
+ expect(clampValue(0, 10)(5)).toBe(5);
6
+ });
7
+ it("returns min when the value is below the range", () => {
8
+ expect(clampValue(0, 10)(-3)).toBe(0);
9
+ });
10
+ it("returns max when the value is above the range", () => {
11
+ expect(clampValue(0, 10)(42)).toBe(10);
12
+ });
13
+ it("returns the boundary value when the input equals min", () => {
14
+ expect(clampValue(0, 10)(0)).toBe(0);
15
+ });
16
+ it("returns the boundary value when the input equals max", () => {
17
+ expect(clampValue(0, 10)(10)).toBe(10);
18
+ });
19
+ it("supports negative ranges", () => {
20
+ expect(clampValue(-10, -5)(-20)).toBe(-10);
21
+ expect(clampValue(-10, -5)(0)).toBe(-5);
22
+ });
23
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { emptyToUndefined, isEmpty, isNotEmpty, isNotNullishOrEmpty, isNullishOrEmpty, nullishOrEmptyToUndefined, } from "../nullish";
3
+ describe("isEmpty", () => {
4
+ it("returns true for an empty string", () => {
5
+ expect(isEmpty("")).toBe(true);
6
+ });
7
+ it("returns false for a non-empty string", () => {
8
+ expect(isEmpty("hello")).toBe(false);
9
+ });
10
+ it("returns false for a whitespace-only string", () => {
11
+ expect(isEmpty(" ")).toBe(false);
12
+ });
13
+ it("returns false for null", () => {
14
+ expect(isEmpty(null)).toBe(false);
15
+ });
16
+ it("returns false for undefined", () => {
17
+ expect(isEmpty(undefined)).toBe(false);
18
+ });
19
+ });
20
+ describe("isNotEmpty", () => {
21
+ it("returns false for an empty string", () => {
22
+ expect(isNotEmpty("")).toBe(false);
23
+ });
24
+ it("returns true for a non-empty string", () => {
25
+ expect(isNotEmpty("hello")).toBe(true);
26
+ });
27
+ it("returns true for a whitespace-only string", () => {
28
+ expect(isNotEmpty(" ")).toBe(true);
29
+ });
30
+ });
31
+ describe("isNullishOrEmpty", () => {
32
+ it("returns true for null", () => {
33
+ expect(isNullishOrEmpty(null)).toBe(true);
34
+ });
35
+ it("returns true for undefined", () => {
36
+ expect(isNullishOrEmpty(undefined)).toBe(true);
37
+ });
38
+ it("returns true for an empty string", () => {
39
+ expect(isNullishOrEmpty("")).toBe(true);
40
+ });
41
+ it("returns false for a non-empty string", () => {
42
+ expect(isNullishOrEmpty("hello")).toBe(false);
43
+ });
44
+ it("returns false for zero", () => {
45
+ expect(isNullishOrEmpty(0)).toBe(false);
46
+ });
47
+ });
48
+ describe("isNotNullishOrEmpty", () => {
49
+ it("returns false for null", () => {
50
+ expect(isNotNullishOrEmpty(null)).toBe(false);
51
+ });
52
+ it("returns false for undefined", () => {
53
+ expect(isNotNullishOrEmpty(undefined)).toBe(false);
54
+ });
55
+ it("returns false for an empty string", () => {
56
+ expect(isNotNullishOrEmpty("")).toBe(false);
57
+ });
58
+ it("returns true for a non-empty string", () => {
59
+ expect(isNotNullishOrEmpty("hello")).toBe(true);
60
+ });
61
+ it("returns true for a whitespace-only string", () => {
62
+ expect(isNotNullishOrEmpty(" ")).toBe(true);
63
+ });
64
+ });
65
+ describe("emptyToUndefined", () => {
66
+ it("returns undefined for an empty string", () => {
67
+ expect(emptyToUndefined("")).toBeUndefined();
68
+ });
69
+ it("returns the original value for a non-empty string", () => {
70
+ expect(emptyToUndefined("hello")).toBe("hello");
71
+ });
72
+ it("returns a whitespace string unchanged", () => {
73
+ expect(emptyToUndefined(" ")).toBe(" ");
74
+ });
75
+ });
76
+ describe("nullishOrEmptyToUndefined", () => {
77
+ it("returns undefined for null", () => {
78
+ expect(nullishOrEmptyToUndefined(null)).toBeUndefined();
79
+ });
80
+ it("returns undefined for undefined", () => {
81
+ expect(nullishOrEmptyToUndefined(undefined)).toBeUndefined();
82
+ });
83
+ it("returns undefined for an empty string", () => {
84
+ expect(nullishOrEmptyToUndefined("")).toBeUndefined();
85
+ });
86
+ it("returns the original value for a non-empty string", () => {
87
+ expect(nullishOrEmptyToUndefined("hello")).toBe("hello");
88
+ });
89
+ });
@@ -1,29 +1 @@
1
- type InterpolateTuple = [number, number, ...number[]];
2
- type FixedLength<L extends number> = number[] & {
3
- 0: number;
4
- length: L;
5
- };
6
- type InterpolateParams<T extends InterpolateTuple> = {
7
- inputRange: T;
8
- outputRange: FixedLength<T["length"]>;
9
- clamp?: boolean;
10
- };
11
1
  export declare const clampValue: (min: number, max: number) => (value: number) => number;
12
- /**
13
- * This function is similar to `Animated.interpolate` except this one can be used with numbers
14
- * Whereas `Animated.interpolate` works only with animated values and return a listener, not a single value
15
- */
16
- export declare const interpolate: <T extends InterpolateTuple>({ inputRange: input, outputRange: output, clamp, }: InterpolateParams<T>) => ((value: number) => number);
17
- type ElasticParams = {
18
- elasticLength?: number;
19
- elasticStrength?: number;
20
- };
21
- /**
22
- * This function takes as input a number from 0 to Infinity and returns a number from 0 to elasticLength
23
- * With an exponential curve giving a feeling of elasticity
24
- * This kind of function can be used to:
25
- * - recreate effect like scroll bounce on iOS
26
- * - limit grab smoothly with touch interaction
27
- */
28
- export declare const limitElastic: ({ elasticLength, elasticStrength }: ElasticParams) => (value: number) => number;
29
- export {};
package/src/utils/math.js CHANGED
@@ -1,55 +1 @@
1
- import { isNotNullish, isNullish } from "./nullish";
2
- const getValue = (array, index, name) => {
3
- const value = array[index];
4
- if (isNullish(value)) {
5
- throw new Error(`Interpolation Error: index "${index}" doesn't exists in ${name}`);
6
- }
7
- return value;
8
- };
9
1
  export const clampValue = (min, max) => (value) => Math.max(Math.min(value, max), min);
10
- // Here we can disable no-non-null-assertion because this function is called in interpolate which have types checking if there is at least 2 values in range
11
- const getRangeIndexes = (range, value) => {
12
- if (value < range[0]) {
13
- return [0, 1];
14
- }
15
- const maxIndex = range.length - 1;
16
- for (let i = 0; i <= maxIndex; i += 1) {
17
- const nextIndex = i + 1;
18
- const startRange = getValue(range, i, "range");
19
- const endRange = range[nextIndex];
20
- if (isNotNullish(endRange) && value > startRange && value < endRange) {
21
- return [i, nextIndex];
22
- }
23
- }
24
- // if no values was found, it means value is upper than last range value
25
- return [maxIndex - 1, maxIndex];
26
- };
27
- /**
28
- * This function is similar to `Animated.interpolate` except this one can be used with numbers
29
- * Whereas `Animated.interpolate` works only with animated values and return a listener, not a single value
30
- */
31
- export const interpolate = ({ inputRange: input, outputRange: output, clamp = true, }) => {
32
- return (value) => {
33
- const [startIndex, endIndex] = getRangeIndexes(input, value);
34
- const inputStart = getValue(input, startIndex, "inputRange");
35
- const inputEnd = getValue(input, endIndex, "inputRange");
36
- const lastInput = getValue(input, input.length - 1, "inputRange");
37
- const outputStart = getValue(output, startIndex, "outputRange");
38
- const outputEnd = getValue(output, endIndex, "outputRange");
39
- const inputRange = inputEnd - inputStart;
40
- const outputRange = outputEnd - outputStart;
41
- const valueToConvert = clamp ? clampValue(input[0], lastInput)(value) : value;
42
- const valueWithoutOffset = valueToConvert - inputStart;
43
- const outputWithoutOffset = (outputRange * valueWithoutOffset) / inputRange;
44
- const outputValue = outputWithoutOffset + outputStart;
45
- return outputValue;
46
- };
47
- };
48
- /**
49
- * This function takes as input a number from 0 to Infinity and returns a number from 0 to elasticLength
50
- * With an exponential curve giving a feeling of elasticity
51
- * This kind of function can be used to:
52
- * - recreate effect like scroll bounce on iOS
53
- * - limit grab smoothly with touch interaction
54
- */
55
- export const limitElastic = ({ elasticLength = 100, elasticStrength = 0.008 }) => (value) => elasticLength * (1 - Math.exp(-elasticStrength * value));