Move lib up one level

This commit is contained in:
garronej
2023-03-16 22:43:09 +01:00
parent 79997efbb6
commit 0040464ca1
283 changed files with 29 additions and 29 deletions

View File

@ -0,0 +1,21 @@
export type AndByDiscriminatingKey<
DiscriminatingKey extends string,
U1 extends Record<DiscriminatingKey, string>,
U2 extends Record<DiscriminatingKey, string>
> = AndByDiscriminatingKey.Tf1<DiscriminatingKey, U1, U1, U2>;
export declare namespace AndByDiscriminatingKey {
export type Tf1<
DiscriminatingKey extends string,
U1,
U1Again extends Record<DiscriminatingKey, string>,
U2 extends Record<DiscriminatingKey, string>
> = U1 extends Pick<U2, DiscriminatingKey> ? Tf2<DiscriminatingKey, U1, U2, U1Again> : U1;
export type Tf2<
DiscriminatingKey extends string,
SingletonU1 extends Record<DiscriminatingKey, string>,
U2,
U1 extends Record<DiscriminatingKey, string>
> = U2 extends Pick<SingletonU1, DiscriminatingKey> ? U2 & SingletonU1 : U2 extends Pick<U1, DiscriminatingKey> ? never : U2;
}

View File

@ -0,0 +1,64 @@
if (!Array.prototype.every) {
Array.prototype.every = function (callbackfn: any, thisArg: any) {
"use strict";
var T, k;
if (this == null) {
throw new TypeError("this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the this
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method
// of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (typeof callbackfn !== "function" && Object.prototype.toString.call(callbackfn) !== "[object Function]") {
throw new TypeError();
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0.
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
var testResult;
// i. Let kValue be the result of calling the Get internal method
// of O with argument Pk.
kValue = O[k];
// ii. Let testResult be the result of calling the Call internal method
// of callbackfn with T as the this value if T is not undefined
// else is the result of calling callbackfn
// and argument list containing kValue, k, and O.
if (T) testResult = callbackfn.call(T, kValue, k, O);
else testResult = callbackfn(kValue, k, O);
// iii. If ToBoolean(testResult) is false, return false.
if (!testResult) {
return false;
}
}
k++;
}
return true;
};
}

3
src/tools/DeepPartial.ts Normal file
View File

@ -0,0 +1,3 @@
export type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};

View File

@ -0,0 +1,9 @@
if (!HTMLElement.prototype.prepend) {
HTMLElement.prototype.prepend = function (childNode) {
if (typeof childNode === "string") {
throw new Error("Error with HTMLElement.prototype.appendFirst polyfill");
}
this.insertBefore(childNode, this.firstChild);
};
}

3
src/tools/Markdown.ts Normal file
View File

@ -0,0 +1,3 @@
import Markdown from "react-markdown";
export { Markdown };

1
src/tools/SetOptional.ts Normal file
View File

@ -0,0 +1 @@
export type SetOptional<T extends Record<string, unknown>, K extends keyof T> = Omit<T, K> & Partial<Record<K, T[K]>>;

View File

@ -0,0 +1,5 @@
import "minimal-polyfills/Object.fromEntries";
export function allPropertiesValuesToUndefined<T extends Record<string, unknown>>(obj: T): Record<keyof T, undefined> {
return Object.fromEntries(Object.entries(obj).map(([key]) => [key, undefined])) as any;
}

1
src/tools/assert.ts Normal file
View File

@ -0,0 +1 @@
export { assert } from "tsafe/assert";

44
src/tools/clsx.ts Normal file
View File

@ -0,0 +1,44 @@
import { assert } from "tsafe/assert";
import { typeGuard } from "tsafe/typeGuard";
export type CxArg = undefined | null | string | boolean | Partial<Record<string, boolean | null | undefined>> | readonly CxArg[];
export const clsx = (...args: CxArg[]): string => {
const len = args.length;
let i = 0;
let cls = "";
for (; i < len; i++) {
const arg = args[i];
if (arg == null) continue;
let toAdd;
switch (typeof arg) {
case "boolean":
break;
case "object": {
if (Array.isArray(arg)) {
toAdd = clsx(...arg);
} else {
assert(!typeGuard<{ length: number }>(arg, false));
toAdd = "";
for (const k in arg) {
if (arg[k as string] && k) {
toAdd && (toAdd += " ");
toAdd += k;
}
}
}
break;
}
default: {
toAdd = arg;
}
}
if (toAdd) {
cls && (cls += " ");
cls += toAdd;
}
}
return cls;
};

44
src/tools/deepAssign.ts Normal file
View File

@ -0,0 +1,44 @@
import { assert } from "tsafe/assert";
import { is } from "tsafe/is";
import { deepClone } from "./deepClone";
//Warning: Be mindful that because of array this is not idempotent.
export function deepAssign(params: { target: Record<string, unknown>; source: Record<string, unknown> }) {
const { target } = params;
const source = deepClone(params.source);
Object.keys(source).forEach(key => {
var dereferencedSource = source[key];
if (target[key] === undefined || dereferencedSource instanceof Function || !(dereferencedSource instanceof Object)) {
Object.defineProperty(target, key, {
"enumerable": true,
"writable": true,
"configurable": true,
"value": dereferencedSource
});
return;
}
const dereferencedTarget = target[key];
if (dereferencedSource instanceof Array) {
assert(is<unknown[]>(dereferencedTarget));
assert(is<unknown[]>(dereferencedSource));
dereferencedSource.forEach(entry => dereferencedTarget.push(entry));
return;
}
assert(is<Record<string, unknown>>(dereferencedTarget));
assert(is<Record<string, unknown>>(dereferencedSource));
deepAssign({
"target": dereferencedTarget,
"source": dereferencedSource
});
});
}

17
src/tools/deepClone.ts Normal file
View File

@ -0,0 +1,17 @@
import "minimal-polyfills/Object.fromEntries";
export function deepClone<T>(o: T): T {
if (!(o instanceof Object)) {
return o;
}
if (typeof o === "function") {
return o;
}
if (o instanceof Array) {
return o.map(deepClone) as any;
}
return Object.fromEntries(Object.entries(o).map(([key, value]) => [key, deepClone(value)])) as any;
}

2
src/tools/emailRegExp.ts Normal file
View File

@ -0,0 +1,2 @@
export const emailRegexp =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

70
src/tools/headInsert.ts Normal file
View File

@ -0,0 +1,70 @@
import "./HTMLElement.prototype.prepend";
import { Deferred } from "evt/tools/Deferred";
export function headInsert(
params:
| {
type: "css";
href: string;
position: "append" | "prepend";
}
| {
type: "javascript";
src: string;
}
) {
const htmlElement = document.createElement(
(() => {
switch (params.type) {
case "css":
return "link";
case "javascript":
return "script";
}
})()
);
const dLoaded = new Deferred<void>();
htmlElement.addEventListener("load", () => dLoaded.resolve());
Object.assign(
htmlElement,
(() => {
switch (params.type) {
case "css":
return {
"href": params.href,
"type": "text/css",
"rel": "stylesheet",
"media": "screen,print"
};
case "javascript":
return {
"src": params.src,
"type": "text/javascript"
};
}
})()
);
document.getElementsByTagName("head")[0][
(() => {
switch (params.type) {
case "javascript":
return "appendChild";
case "css":
return (() => {
switch (params.position) {
case "append":
return "appendChild";
case "prepend":
return "prepend";
}
})();
}
})()
](htmlElement);
return dLoaded.pr;
}

55
src/tools/memoize.ts Normal file
View File

@ -0,0 +1,55 @@
type SimpleType = number | string | boolean | null | undefined;
type FuncWithSimpleParams<T extends SimpleType[], R> = (...args: T) => R;
export function memoize<T extends SimpleType[], R>(
fn: FuncWithSimpleParams<T, R>,
options?: {
argsLength?: number;
max?: number;
}
): FuncWithSimpleParams<T, R> {
const cache = new Map<string, ReturnType<FuncWithSimpleParams<T, R>>>();
const { argsLength = fn.length, max = Infinity } = options ?? {};
return ((...args: Parameters<FuncWithSimpleParams<T, R>>) => {
const key = JSON.stringify(
args
.slice(0, argsLength)
.map(v => {
if (v === null) {
return "null";
}
if (v === undefined) {
return "undefined";
}
switch (typeof v) {
case "number":
return `number-${v}`;
case "string":
return `string-${v}`;
case "boolean":
return `boolean-${v ? "true" : "false"}`;
}
})
.join("-sIs9sAslOdeWlEdIos3-")
);
if (cache.has(key)) {
return cache.get(key);
}
if (max === cache.size) {
for (const key of cache.keys()) {
cache.delete(key);
break;
}
}
const value = fn(...args);
cache.set(key, value);
return value;
}) as any;
}

View File

@ -0,0 +1,3 @@
export function pathBasename(path: string) {
return path.split("/").reverse()[0];
}

View File

@ -0,0 +1,45 @@
import { useRef, useState } from "react";
import { id } from "tsafe/id";
import { memoize } from "./memoize";
export type CallbackFactory<FactoryArgs extends unknown[], Args extends unknown[], R> = (...factoryArgs: FactoryArgs) => (...args: Args) => R;
/**
* https://docs.powerhooks.dev/api-reference/usecallbackfactory
*
* const callbackFactory= useCallbackFactory(
* ([key]: [string], [params]: [{ foo: number; }]) => {
* ...
* },
* []
* );
*
* WARNING: Factory args should not be of variable length.
*
*/
export function useCallbackFactory<FactoryArgs extends (string | number | boolean)[], Args extends unknown[], R = void>(
callback: (...callbackArgs: [FactoryArgs, Args]) => R
): CallbackFactory<FactoryArgs, Args, R> {
type Out = CallbackFactory<FactoryArgs, Args, R>;
const callbackRef = useRef<typeof callback>(callback);
callbackRef.current = callback;
const memoizedRef = useRef<Out | undefined>(undefined);
return useState(() =>
id<Out>((...factoryArgs) => {
if (memoizedRef.current === undefined) {
memoizedRef.current = memoize(
(...factoryArgs: FactoryArgs) =>
(...args: Args) =>
callbackRef.current(factoryArgs, args),
{ "argsLength": factoryArgs.length }
);
}
return memoizedRef.current(...factoryArgs);
})
)[0];
}

10
src/tools/useConst.ts Normal file
View File

@ -0,0 +1,10 @@
import { useState } from "react";
/**
* Compute a value on first render and never again,
* Equivalent of const [x] = useState(()=> ...)
*/
export function useConst<T>(getValue: () => T): T {
const [value] = useState(getValue);
return value;
}

View File

@ -0,0 +1,15 @@
import { useRef, useState } from "react";
import { Parameters } from "tsafe/Parameters";
/** https://stackoverflow.com/questions/65890278/why-cant-usecallback-always-return-the-same-ref */
export function useConstCallback<T extends ((...args: any[]) => unknown) | undefined | null>(callback: NonNullable<T>): T {
const callbackRef = useRef<typeof callback>(null as any);
callbackRef.current = callback;
return useState(
() =>
(...args: Parameters<T>) =>
callbackRef.current(...args)
)[0] as T;
}

12
src/tools/useCssAndCx.ts Normal file
View File

@ -0,0 +1,12 @@
import { clsx as cx } from "./clsx";
/**
* @deprecated: Use clsx instead.
* import { clsx } from "keycloakify/lib/tools/clsx";
* You can use clsx as cx.
* If you where using the css() function you can import
* it from @emotion/css: https://emotion.sh/docs/@emotion/css
*/
export function useCssAndCx() {
return { cx };
}