[DRVWEB-4373] Add Suggestion Mode spotlight onboarding modal for docs on drive
[ProtonMail-WebClient.git] / packages / pass / utils / array / interpolate.ts
blobc12d2e4b384f0a241eb55cbc6dd3566e33d6476c
1 import type { MaybeNull } from '@proton/pass/types';
3 export type InterpolationItem<Value, Cluster> =
4     | { type: 'entry'; entry: Value }
5     | { type: 'interpolation'; cluster: Cluster };
7 export type Interpolation<Value, Cluster> = {
8     clusters: Cluster[];
9     interpolated: boolean;
10     interpolation: InterpolationItem<Value, Cluster>[];
11     interpolationIndexes: number[];
14 type InterpolationOptions<T, Cluster> = {
15     clusters: Cluster[];
16     shouldInterpolate: (entry: T, cluster: Cluster) => boolean;
17     fallbackCluster?: Cluster;
20 /* Returns an interpolated array based on clusters and
21  * interpolation rules. Interpolations are between adjacent
22  * clusters where "shouldInterpolate" is true. `entries` &
23  * `clusters` must be sorted for best results. */
24 export const arrayInterpolate = <Value, Cluster>(
25     entries: Value[],
26     { clusters, shouldInterpolate, fallbackCluster }: InterpolationOptions<Value, Cluster>
27 ): Interpolation<Value, Cluster> => {
28     const initial: Interpolation<Value, Cluster> = {
29         interpolation: [],
30         interpolationIndexes: [],
31         interpolated: false,
32         clusters,
33     };
35     return entries.reduce<Interpolation<Value, Cluster>>((acc, entry) => {
36         if (acc.clusters.length === 0) {
37             acc.interpolation.push({ type: 'entry', entry });
38             return acc;
39         }
41         const cluster = acc.clusters[0];
43         let interpolate: MaybeNull<Cluster> = null;
45         if (shouldInterpolate(entry, cluster)) {
46             interpolate = !acc.interpolated ? cluster : null;
47         } else {
48             const rest = acc.clusters.slice(1);
49             const nextClusterIdx = rest.findIndex((_cluster) => shouldInterpolate(entry, _cluster));
50             const nextCluster = rest?.[nextClusterIdx];
52             acc.clusters = nextCluster ? rest.slice(nextClusterIdx) : [];
53             interpolate = nextCluster ?? fallbackCluster ?? null;
54         }
56         if (interpolate) {
57             acc.interpolated = true;
58             acc.interpolation.push({ type: 'interpolation', cluster: interpolate });
59             acc.interpolationIndexes.push(acc.interpolation.length - 1);
60         }
62         acc.interpolation.push({ type: 'entry', entry });
64         return acc;
65     }, initial);