remove old unused code
move to esm
This commit is contained in:
parent
be24f193ce
commit
86ccdf3701
72
dist/easings.js
vendored
Normal file
72
dist/easings.js
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
const r = {
|
||||
quart: (t, e) => n(
|
||||
[0.895, 0.03, 0.685, 0.22],
|
||||
[0.165, 0.84, 0.44, 1],
|
||||
[0.77, 0, 0.175, 1],
|
||||
t,
|
||||
e
|
||||
),
|
||||
circ: (t, e) => n(
|
||||
[0.6, 0.04, 0.98, 0.335],
|
||||
[0.075, 0.82, 0.165, 1],
|
||||
[0.785, 0.135, 0.15, 0.86],
|
||||
t,
|
||||
e
|
||||
),
|
||||
quint: (t, e) => n(
|
||||
[0.755, 0.05, 0.855, 0.06],
|
||||
[0.23, 1, 0.32, 1],
|
||||
[0.86, 0, 0.07, 1],
|
||||
t,
|
||||
e
|
||||
),
|
||||
sine: (t, e) => n(
|
||||
[0.47, 0, 0.745, 0.715],
|
||||
[0.39, 0.575, 0.565, 1],
|
||||
[0.445, 0.05, 0.55, 0.95],
|
||||
t,
|
||||
e
|
||||
),
|
||||
expo: (t, e) => n(
|
||||
[0.95, 0.05, 0.795, 0.035],
|
||||
[0.19, 1, 0.22, 1],
|
||||
[1, 0, 0, 1],
|
||||
t,
|
||||
e
|
||||
),
|
||||
cubic: (t, e) => n(
|
||||
[0.55, 0.055, 0.675, 0.19],
|
||||
[0.215, 0.61, 0.355, 1],
|
||||
[0.645, 0.045, 0.355, 1],
|
||||
t,
|
||||
e
|
||||
)
|
||||
}, a = {
|
||||
type: "tween",
|
||||
duration: 0.7
|
||||
}, n = (t, e, u, c, o) => {
|
||||
const s = c ? { duration: c } : {}, i = o ? { delay: o } : {};
|
||||
return {
|
||||
in: {
|
||||
...a,
|
||||
ease: t,
|
||||
...s,
|
||||
...i
|
||||
},
|
||||
out: {
|
||||
...a,
|
||||
ease: e,
|
||||
...s,
|
||||
...i
|
||||
},
|
||||
inOut: {
|
||||
...a,
|
||||
ease: u,
|
||||
...s,
|
||||
...i
|
||||
}
|
||||
};
|
||||
};
|
||||
export {
|
||||
r as default
|
||||
};
|
10
dist/easings/easings.d.ts
vendored
Normal file
10
dist/easings/easings.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
type EasingCollection = {
|
||||
out: any;
|
||||
in: any;
|
||||
inOut: any;
|
||||
};
|
||||
type EasingFunction = (duration: number, delay?: number) => EasingCollection;
|
||||
declare const Easings: {
|
||||
[key: string]: EasingFunction;
|
||||
};
|
||||
export default Easings;
|
7
dist/unom-style.d.ts
vendored
Normal file
7
dist/unom-style.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import ease from "./easings/easings";
|
||||
export {
|
||||
/**
|
||||
* @public
|
||||
* Util function to create framer-motion transitions based on penner's functions
|
||||
*/
|
||||
ease };
|
4
dist/unom-style.js
vendored
Normal file
4
dist/unom-style.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import { default as f } from "./easings.js";
|
||||
export {
|
||||
f as ease
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
modulePaths: ["<rootDir>/src"],
|
||||
};
|
58
package.json
58
package.json
@ -1,45 +1,43 @@
|
||||
{
|
||||
"name": "@unom/style",
|
||||
"version": "0.2.14",
|
||||
"version": "0.3.0",
|
||||
"description": "The official unom-style library",
|
||||
"main": "build/unom-style.js",
|
||||
"module": "build/unom-style.es.js",
|
||||
"jsnext:main": "build/unom-style.es.js",
|
||||
"types": "build/unom-style.d.ts",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"start": "rollup -cw",
|
||||
"test": "jest --coverage",
|
||||
"emit-types": "tsc ./src/unom-style.ts --baseUrl src --declaration --emitDeclarationOnly --jsx react --esModuleInterop --outFile ./build/unom-tools.js "
|
||||
},
|
||||
"type": "module",
|
||||
"files": [
|
||||
"build"
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": "./dist/unom-style.js",
|
||||
"./easings": "./dist/easings.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"dev": "vite",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest run --coverage"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://packages.unom.io"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "unom",
|
||||
"author": "enricobuehler",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"peerDependencies": {
|
||||
"joi": "^17.2.1",
|
||||
"rxjs": "^6.5.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^11.0.2",
|
||||
"@rollup/plugin-node-resolve": "^7.1.1",
|
||||
"@rollup/plugin-typescript": "^8.3.0",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/joi": "^17.2.3",
|
||||
"jest": "^27.3.1",
|
||||
"rollup": "^2.48.0",
|
||||
"rollup-plugin-bundle-size": "^1.0.3",
|
||||
"rollup-plugin-copy": "^3.3.0",
|
||||
"@types/node": "^18.15.5",
|
||||
"@vitest/coverage-c8": "^0.29.7",
|
||||
"dotenv": "^16.0.3",
|
||||
"rollup-plugin-peer-deps-external": "^2.2.4",
|
||||
"rollup-plugin-uglify": "^6.0.4",
|
||||
"ts-jest": "^27.0.7",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.4.4"
|
||||
"tslib": "^2.5.0",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.2.1",
|
||||
"vite-plugin-dts": "^2.1.0",
|
||||
"vite-tsconfig-paths": "^4.0.7",
|
||||
"vitest": "^0.29.7"
|
||||
},
|
||||
"volta": {
|
||||
"node": "18.12.0",
|
||||
"npm": "8.9.0",
|
||||
"yarn": "1.22.19"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,48 +0,0 @@
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import commonjs from "@rollup/plugin-commonjs";
|
||||
import external from "rollup-plugin-peer-deps-external";
|
||||
import { camelCase } from "lodash";
|
||||
import { uglify } from "rollup-plugin-uglify";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import pkg from "./package.json";
|
||||
import bundleSize from "rollup-plugin-bundle-size";
|
||||
import copy from "rollup-plugin-copy";
|
||||
|
||||
const globals = {};
|
||||
|
||||
const libraryName = "unom-style";
|
||||
|
||||
export default {
|
||||
input: `src/${libraryName}.ts`,
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
name: camelCase(libraryName),
|
||||
format: "umd",
|
||||
globals: globals,
|
||||
sourcemap: true,
|
||||
},
|
||||
{
|
||||
file: pkg.module,
|
||||
format: "es",
|
||||
exports: "named",
|
||||
globals: globals,
|
||||
sourcemap: true,
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
copy({
|
||||
targets: [{ src: "static/easings.css", dest: "build/" }],
|
||||
}),
|
||||
external(),
|
||||
resolve(),
|
||||
typescript({
|
||||
tsconfig: "./tsconfig.json",
|
||||
}),
|
||||
uglify(),
|
||||
bundleSize(),
|
||||
commonjs({
|
||||
include: ["node_modules/**"],
|
||||
}),
|
||||
],
|
||||
};
|
@ -1,55 +0,0 @@
|
||||
import { generateShades } from ".";
|
||||
|
||||
const exampleColors = {
|
||||
main: "black",
|
||||
"secondary-accent": "#fff",
|
||||
};
|
||||
|
||||
test("color shades are generated in a nested structure", () => {
|
||||
const colors = generateShades(exampleColors, {
|
||||
structure: "nested",
|
||||
format: "css-variable",
|
||||
});
|
||||
|
||||
expect(colors).toMatchObject({
|
||||
main: {
|
||||
"10": "rgba(0,0,0,0.1)",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("color shades are generated in a flat structure", () => {
|
||||
const colors = generateShades(exampleColors, {
|
||||
structure: "flat",
|
||||
format: "css-variable",
|
||||
});
|
||||
|
||||
expect(colors).toMatchObject({
|
||||
"main-10": "rgba(0,0,0,0.1)",
|
||||
});
|
||||
});
|
||||
|
||||
test("color shades are generated in a flat structure with a prefix", () => {
|
||||
const colors = generateShades(exampleColors, {
|
||||
structure: "flat",
|
||||
keyPrefix: "color-",
|
||||
format: "css-variable",
|
||||
});
|
||||
|
||||
expect(colors).toMatchObject({
|
||||
"color-main-10": "rgba(0,0,0,0.1)",
|
||||
});
|
||||
});
|
||||
|
||||
test("a filtered list of color shades is generated in a flat structure", () => {
|
||||
const colors = generateShades(exampleColors, {
|
||||
structure: "flat",
|
||||
keys: ["main"],
|
||||
format: "css-variable",
|
||||
});
|
||||
|
||||
expect(colors).toMatchObject({
|
||||
"main-10": "rgba(0,0,0,0.1)",
|
||||
});
|
||||
expect(colors["secondary-accent"]).toBeUndefined();
|
||||
});
|
@ -1,85 +0,0 @@
|
||||
import { countDecimals } from "Utils";
|
||||
import { fromString } from "css-color-converter";
|
||||
|
||||
export interface ColorsInput {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface ShadesOptions {
|
||||
keys?: string[];
|
||||
keyPrefix?: string;
|
||||
keySuffix?: string;
|
||||
opacities?: number[];
|
||||
structure?: "flat" | "nested";
|
||||
format?: "default" | "css-variable";
|
||||
}
|
||||
|
||||
const DEFAULT_OPACITIES = [0.1, 0.25, 0.5, 0.75];
|
||||
const DEFAULT_STRUCTURE = "flat";
|
||||
|
||||
const formatColor = ({
|
||||
key,
|
||||
rgb,
|
||||
opacity,
|
||||
}: {
|
||||
key?: string;
|
||||
rgb: string;
|
||||
opacity?: number;
|
||||
}) => {
|
||||
return {
|
||||
[`${key ? key + "-" : ""}${
|
||||
opacity !== undefined
|
||||
? countDecimals(opacity) === 1
|
||||
? (opacity + "").split(".")[1] + "0"
|
||||
: (opacity + "").split(".")[1]
|
||||
: ""
|
||||
}`]: `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${opacity})`,
|
||||
};
|
||||
};
|
||||
|
||||
const generateShades = (colors: ColorsInput, options?: ShadesOptions) => {
|
||||
const colorKeys = options?.keys
|
||||
? Object.keys(colors).filter((key) => options.keys?.includes(key))
|
||||
: Object.keys(colors);
|
||||
|
||||
const structure = options?.structure
|
||||
? options.structure === "nested"
|
||||
? "nested"
|
||||
: "flat"
|
||||
: DEFAULT_STRUCTURE;
|
||||
|
||||
const generatedColorShadesArr: object[] = [];
|
||||
|
||||
colorKeys.forEach((_key) => {
|
||||
const key = (options?.keyPrefix || "") + _key + (options?.keySuffix || "");
|
||||
const colorString = colors[_key];
|
||||
|
||||
const opacities = options?.opacities
|
||||
? options.opacities
|
||||
: DEFAULT_OPACITIES;
|
||||
|
||||
if (structure === "flat") {
|
||||
opacities.forEach((opacity) => {
|
||||
const rgba = fromString(colorString).toRgbaArray();
|
||||
generatedColorShadesArr.push(formatColor({ key, rgb: rgba, opacity }));
|
||||
});
|
||||
} else {
|
||||
generatedColorShadesArr.push({
|
||||
[key]: Object.assign(
|
||||
{},
|
||||
...opacities.map((opacity) => {
|
||||
const rgba = fromString(colorString).toRgbaArray();
|
||||
|
||||
return formatColor({ rgb: rgba, opacity });
|
||||
})
|
||||
),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const generatedColorShades = Object.assign({}, ...generatedColorShadesArr);
|
||||
|
||||
return generatedColorShades;
|
||||
};
|
||||
|
||||
export { generateShades, formatColor };
|
@ -1,74 +0,0 @@
|
||||
import {
|
||||
generateThemeOverride,
|
||||
generateThemeRoot,
|
||||
generateTheme,
|
||||
ThemeInput,
|
||||
} from ".";
|
||||
|
||||
const exampleProperties = {
|
||||
"color-main-10": "black",
|
||||
"color-main-50": "grey",
|
||||
};
|
||||
|
||||
const exampleThemes: ThemeInput[] = [
|
||||
{
|
||||
name: "default",
|
||||
colors: { "color-main": "black" },
|
||||
},
|
||||
{
|
||||
name: "dark",
|
||||
colors: { "color-main": "white", "color-secondary": "blue" },
|
||||
},
|
||||
{ name: "light", colors: { "color-secondary": "grey" } },
|
||||
];
|
||||
|
||||
test("it generates css based on input properties", () => {
|
||||
const themeClass = generateThemeOverride({
|
||||
properties: exampleProperties,
|
||||
selector: ".dark-theme",
|
||||
});
|
||||
|
||||
expect(themeClass).toBeDefined();
|
||||
});
|
||||
|
||||
test("no input so it returns empty string", () => {
|
||||
const themeClass = generateThemeOverride({
|
||||
properties: {},
|
||||
selector: ".dark-theme",
|
||||
});
|
||||
|
||||
expect(themeClass).toBeDefined();
|
||||
expect(themeClass).toEqual("");
|
||||
});
|
||||
|
||||
test("it generates the theme root", () => {
|
||||
const themeRoot = generateThemeRoot({ properties: exampleProperties });
|
||||
console.log(themeRoot);
|
||||
expect(themeRoot).toBeDefined();
|
||||
});
|
||||
|
||||
test("it generates the complete theme with overrides", () => {
|
||||
const theme = generateTheme({
|
||||
themes: exampleThemes,
|
||||
output: "CSS",
|
||||
});
|
||||
|
||||
console.log(theme);
|
||||
|
||||
expect(theme).toBeDefined();
|
||||
});
|
||||
|
||||
test("it generates the complete theme with overrides and color shades", () => {
|
||||
const theme = generateTheme({
|
||||
themes: exampleThemes,
|
||||
output: "CSS",
|
||||
generateColorShades: {
|
||||
structure: "flat",
|
||||
format: "css-variable",
|
||||
},
|
||||
});
|
||||
|
||||
console.log(theme);
|
||||
|
||||
expect(theme).toBeDefined();
|
||||
});
|
@ -1,89 +0,0 @@
|
||||
import * as Colors from "./Colors";
|
||||
import { generateShades, ColorsInput, ShadesOptions } from "./Colors";
|
||||
|
||||
export interface ThemeInput {
|
||||
name: string;
|
||||
colors: ColorsInput;
|
||||
common?: any;
|
||||
selector?: string;
|
||||
}
|
||||
|
||||
const generateThemeOverride = (input: {
|
||||
properties: any;
|
||||
selector: string;
|
||||
}) => {
|
||||
const propKeys = Object.keys(input.properties);
|
||||
|
||||
if (propKeys.length > 0) {
|
||||
return `
|
||||
${input.selector} {${propKeys
|
||||
.map((key) => `\t--${key}: ${input.properties[key]};`)
|
||||
.join("\n")}}`;
|
||||
} else return "";
|
||||
};
|
||||
|
||||
const generateThemeRoot = (input: { properties: any }) => {
|
||||
const propKeys = Object.keys(input.properties);
|
||||
|
||||
if (propKeys.length > 0) {
|
||||
return `
|
||||
:root {${propKeys
|
||||
.map((key) => `\t--${key}: ${input.properties[key]};`)
|
||||
.join("\n")}}`;
|
||||
} else return "";
|
||||
};
|
||||
|
||||
const generateTheme = (options: {
|
||||
output?: "CSS";
|
||||
themes: ThemeInput[];
|
||||
generateColorShades?: boolean | ShadesOptions;
|
||||
}) => {
|
||||
let themes = options.themes;
|
||||
|
||||
if (
|
||||
options.generateColorShades !== undefined &&
|
||||
options.generateColorShades !== false
|
||||
) {
|
||||
themes = themes.map((theme) => {
|
||||
const updatedColors = {
|
||||
...generateShades(
|
||||
theme.colors,
|
||||
typeof options.generateColorShades !== "boolean"
|
||||
? options.generateColorShades
|
||||
: undefined
|
||||
),
|
||||
...theme.colors,
|
||||
};
|
||||
|
||||
return { ...theme, colors: updatedColors };
|
||||
});
|
||||
}
|
||||
|
||||
const themeRoot = generateThemeRoot({
|
||||
properties: { ...themes[0].colors, ...(themes[0].common || {}) },
|
||||
});
|
||||
|
||||
if (themes.length > 1) {
|
||||
const themeOverrides = themes
|
||||
.slice(1)
|
||||
.map((theme) => {
|
||||
const overrideClass = generateThemeOverride({
|
||||
properties: { ...theme.colors, ...(theme.common || {}) },
|
||||
selector: theme.selector ? theme.selector : "." + theme.name,
|
||||
});
|
||||
|
||||
return overrideClass;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return themeRoot + themeOverrides;
|
||||
} else return themeRoot;
|
||||
};
|
||||
|
||||
export { generateThemeOverride, generateThemeRoot, generateTheme };
|
||||
export default {
|
||||
Colors,
|
||||
generateThemeOverride,
|
||||
generateThemeRoot,
|
||||
generateTheme,
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
const countDecimals = (value: number) => {
|
||||
if (Math.floor(value) === value) return 0;
|
||||
return value.toString().split(".")[1].length || 0;
|
||||
};
|
||||
|
||||
export { countDecimals };
|
||||
export default {
|
||||
countDecimals,
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
import ease from ".";
|
||||
import ease from "./easings";
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
const DURATION = 2;
|
||||
|
||||
test("returns correct ease quint out with 2 second duration", () => {
|
||||
it("returns correct ease quint out with 2 second duration", () => {
|
||||
const easing = ease.quint(DURATION).out;
|
||||
|
||||
expect(easing).toEqual({
|
||||
@ -10,9 +11,10 @@ test("returns correct ease quint out with 2 second duration", () => {
|
||||
type: "tween",
|
||||
duration: DURATION,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
test("returns correct ease circ in with 2 second duration", () => {
|
||||
|
||||
it("returns correct ease circ in with 2 second duration", () => {
|
||||
const easing = ease.circ(DURATION).in;
|
||||
|
||||
expect(easing).toEqual({
|
@ -1,23 +1,10 @@
|
||||
import Utils from "./Utils";
|
||||
import ease from "./Easings";
|
||||
import Theme from "./Theme";
|
||||
import ease from "./easings/easings";
|
||||
|
||||
declare module "unom-style";
|
||||
|
||||
export {
|
||||
/**
|
||||
* @public
|
||||
* Util function to create framer-motion transitions based on penner's functions
|
||||
*/
|
||||
ease,
|
||||
/**
|
||||
* @public
|
||||
* Collection of Utils
|
||||
*/
|
||||
Utils,
|
||||
/**
|
||||
* @public
|
||||
* Collection of theming tools
|
||||
*/
|
||||
Theme,
|
||||
ease
|
||||
};
|
||||
|
@ -1,28 +1,36 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./build",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"declarationDir": ".",
|
||||
"baseUrl": "src",
|
||||
"lib": ["es6", "dom", "es2016", "es2017", "es2019"],
|
||||
"sourceMap": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ESNext"
|
||||
],
|
||||
"allowJs": false,
|
||||
"declaration": true,
|
||||
"jsx": "react",
|
||||
"moduleResolution": "node",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": false,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strictNullChecks": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"esModuleInterop": true
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "build"]
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
9
tsconfig.node.json
Normal file
9
tsconfig.node.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
29
vite.config.ts
Normal file
29
vite.config.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/// <reference types="vitest" />
|
||||
|
||||
import { defineConfig } from "vite";
|
||||
import path from "path";
|
||||
import dts from "vite-plugin-dts";
|
||||
import external from "rollup-plugin-peer-deps-external";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [dts()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
rollupOptions: {
|
||||
plugins: [external()],
|
||||
},
|
||||
lib: {
|
||||
entry: [
|
||||
"src/easings/easings.ts",
|
||||
"src/unom-style.ts",
|
||||
],
|
||||
formats: ["es"],
|
||||
name: "unomStyle",
|
||||
},
|
||||
},
|
||||
test: {},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user