Move some modules from src to shlink-web-component

This commit is contained in:
Alejandro Celaya
2023-07-27 22:23:46 +02:00
parent 0169060de7
commit 275745fd3a
51 changed files with 212 additions and 133 deletions

View File

@@ -7,7 +7,7 @@ export const csvToJson = <T>(csvContent: string) => new Promise<T[]>((resolve) =
export type CsvToJson = typeof csvToJson;
const jsonParser = new Parser(); // TODO This accepts options if needed
const jsonParser = new Parser(); // This accepts options if needed
export const jsonToCsv = <T>(data: T[]): string => jsonParser.parse(data);

View File

@@ -1,9 +1,8 @@
import type { DependencyList, EffectCallback } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useSwipeable as useReactSwipeable } from 'react-swipeable';
import { v4 as uuid } from 'uuid';
import { parseQuery, stringifyQuery } from './query';
import { parseQuery } from '../../../shlink-web-component/utils/helpers/query';
const DEFAULT_DELAY = 2000;
@@ -35,40 +34,6 @@ export const useToggle = (initialValue = false): ToggleResult => {
return [flag, () => setFlag(!flag), () => setFlag(true), () => setFlag(false)];
};
export const useSwipeable = (showSidebar: () => void, hideSidebar: () => void) => {
const swipeMenuIfNoModalExists = (callback: () => void) => (e: any) => {
const swippedOnVisitsTable = (e.event.composedPath() as HTMLElement[]).some(
({ classList }) => classList?.contains('visits-table'),
);
if (swippedOnVisitsTable || document.querySelector('.modal')) {
return;
}
callback();
};
return useReactSwipeable({
delta: 40,
onSwipedLeft: swipeMenuIfNoModalExists(hideSidebar),
onSwipedRight: swipeMenuIfNoModalExists(showSidebar),
});
};
export const useQueryState = <T>(paramName: string, initialState: T): [ T, (newValue: T) => void ] => {
const [value, setValue] = useState(initialState);
const setValueWithLocation = (valueToSet: T) => {
const { location, history } = window;
const query = parseQuery<any>(location.search);
query[paramName] = valueToSet;
history.pushState(null, '', `${location.pathname}?${stringifyQuery(query)}`);
setValue(valueToSet);
};
return [value, setValueWithLocation];
};
export const useEffectExceptFirstTime = (callback: EffectCallback, deps: DependencyList): void => {
const isFirstLoad = useRef(true);

View File

@@ -1,5 +1,5 @@
import { isEmpty } from 'ramda';
import { stringifyQuery } from './query';
import { stringifyQuery } from '../../../shlink-web-component/utils/helpers/query';
export type QrCodeFormat = 'svg' | 'png';

View File

@@ -1,5 +0,0 @@
import qs from 'qs';
export const parseQuery = <T>(search: string) => qs.parse(search, { ignoreQueryPrefix: true }) as unknown as T;
export const stringifyQuery = (query: any): string => qs.stringify(query, { arrayFormat: 'brackets' });

View File

@@ -1,59 +0,0 @@
import { isNil } from 'ramda';
import { rangeOf } from '../utils';
import type { LocalStorage } from './LocalStorage';
const HEX_COLOR_LENGTH = 6;
const HEX_DIGITS = '0123456789ABCDEF';
const LIGHTNESS_BREAKPOINT = 128;
const { floor, random, sqrt, round } = Math;
const buildRandomColor = () =>
`#${rangeOf(HEX_COLOR_LENGTH, () => HEX_DIGITS[floor(random() * HEX_DIGITS.length)]).join('')}`;
const normalizeKey = (key: string) => key.toLowerCase().trim();
const hexColorToRgbArray = (colorHex: string): number[] =>
(colorHex.match(/../g) ?? []).map((hex) => parseInt(hex, 16) || 0);
// HSP by Darel Rex Finley https://alienryderflex.com/hsp.html
const perceivedLightness = (r = 0, g = 0, b = 0) => round(sqrt(0.299 * r ** 2 + 0.587 * g ** 2 + 0.114 * b ** 2));
export class ColorGenerator {
private readonly colors: Record<string, string>;
private readonly lights: Record<string, boolean>;
public constructor(private readonly storage: LocalStorage) {
this.colors = this.storage.get<Record<string, string>>('colors') ?? {};
this.lights = {};
}
public readonly getColorForKey = (key: string) => {
const normalizedKey = normalizeKey(key);
const color = this.colors[normalizedKey];
// If a color has not been set yet, generate a random one and save it
if (!color) {
return this.setColorForKey(normalizedKey, buildRandomColor());
}
return color;
};
public readonly setColorForKey = (key: string, color: string) => {
const normalizedKey = normalizeKey(key);
this.colors[normalizedKey] = color;
this.storage.set('colors', this.colors);
return color;
};
public readonly isColorLightForKey = (key: string): boolean => {
const colorHex = this.getColorForKey(key).substring(1);
if (isNil(this.lights[colorHex])) {
const rgb = hexColorToRgbArray(colorHex);
this.lights[colorHex] = perceivedLightness(...rgb) >= LIGHTNESS_BREAKPOINT;
}
return this.lights[colorHex];
};
}

View File

@@ -1,7 +1,7 @@
import type Bottle from 'bottlejs';
import { ColorGenerator } from '../../../shlink-web-component/utils/services/ColorGenerator';
import { csvToJson, jsonToCsv } from '../helpers/csvjson';
import { useTimeoutToggle } from '../helpers/hooks';
import { ColorGenerator } from './ColorGenerator';
import { LocalStorage } from './LocalStorage';
export const provideServices = (bottle: Bottle) => {