first upload

This commit is contained in:
2026-02-24 12:43:16 +08:00
commit c05aaa5e08
88904 changed files with 3936503 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 07akioni
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,69 @@
# seemly
Util functions for creating user interface.
## Installation
```bash
npm install --save-dev seemly
```
## Usage
```js
import { xxx } from 'seemly'
```
## API
### Animation
#### `beforeNextFrame(callback: Function): void`
Call the callback function before next frame.
#### `beforeNextFrameOnce(callback: Function): void`
Call the callback function before next frame. Same function won't be called more than once.
### Color
In the following functions, `RGBA` is `[number, number, number, number]`, `RGB` is `[number, number, number]`.
#### `rgba (color: string): RGBA`
Get the rgba value of a string color.
Color could only be `#000`, `#0000`, `#000000`, `#00000000`, `rgb(0, 0, 0)`, `rgba(0, 0, 0, 0)` formatted.
#### `composite (background: string | RGB | RGBA, overlay: string | RGB | RGBA): string`
Get the rgba formatted string of composited color of the two color.
For example: `composite('#FFF', 'rgba(0, 0, 0, .5)') === 'rgba(127, 127, 127, 1)'`, `composite('rgba(255, 255, 255, .5)', 'rgba(0, 0, 0, .5)') === 'rgba(85, 85, 85, 0.75)'`.
### CSS
#### `depx (value: string | number): number`
Remove the `'px'` of the input value and get the number value of it.
For example: `depx('1px') === 1`, `depx('1') === 1`, `depx(1) === 1`.
#### `pxfy (value: string | number): string`
Append the `'px'` on the input value.
For example: `pxfy(1) === '1px'`, `pxfy('1') === '1px'`, `'pxfy('1px') === '1px')`.
#### `parseResponsiveProp (responsiveProp: string): Record<string, string>`
Transform a css utility class to a js object.
For example: `parseResponsiveProp('6 m:12 l:24')` is `{ '': 6, m: '12', l: '24' }`
#### `parseResponsivePropValue (responsiveProp: string, activeKey: string): string | undefined`
Get corresponding value by key.
For example: `parseResponsiveProp('6 m:12 l:24', 'l')` is `'24'`. `parseResponsiveProp('6 m:12 l:24')`, `parseResponsiveProp('6 m:12 l:24', 'x')` are `'6'`.
### DOM
#### `getScrollParent (node: Node | null): HTMLElement | Document | null`
Get the scrollable parent node of current node.
#### `unwrapElement (target: HTMLElement | string | () => HTMLElement): HTMLElement | null`
Unwrap the HTMLElement from a element getter function or a element selector.
If the `target` is already a HTMLElement, the same value will be returned.
### Misc
#### `createId (length: number = 8): string`
Get a unique random id with length of `length`.

View File

@@ -0,0 +1,7 @@
declare function beforeNextFrameOnce(cb: () => void): void;
declare function beforeNextFrameOnce<T1>(cb: (arg1: T1) => void, arg1: T1): void;
declare function beforeNextFrameOnce<T1, T2>(cb: (arg1: T1, arg2: T2) => void, arg1: T1, arg2: T2): void;
declare function beforeNextFrameOnce<T1, T2, T3>(cb: (arg1: T1, arg2: T2, arg3: T3) => void, arg1: T1, arg2: T2, arg3: T3): void;
declare function beforeNextFrameOnce<T1, T2, T3, T4>(cb: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => void, arg1: T1, arg2: T2, arg3: T3, arg4: T4): void;
declare function beforeNextFrameOnce<T extends any[]>(cb: (...args: T) => void, ...params: T): void;
export { beforeNextFrameOnce };

View File

@@ -0,0 +1,13 @@
let onceCbs = [];
const paramsMap = new WeakMap();
function flushOnceCallbacks() {
onceCbs.forEach((cb) => cb(...paramsMap.get(cb)));
onceCbs = [];
}
function beforeNextFrameOnce(cb, ...params) {
paramsMap.set(cb, params);
if (onceCbs.includes(cb))
return;
onceCbs.push(cb) === 1 && requestAnimationFrame(flushOnceCallbacks);
}
export { beforeNextFrameOnce };

View File

@@ -0,0 +1,7 @@
declare function beforeNextFrame(cb: () => void): void;
declare function beforeNextFrame<T1>(cb: (arg1: T1) => void, arg1: T1): void;
declare function beforeNextFrame<T1, T2>(cb: (arg1: T1, arg2: T2) => void, arg1: T1, arg2: T2): void;
declare function beforeNextFrame<T1, T2, T3>(cb: (arg1: T1, arg2: T2, arg3: T3) => void, arg1: T1, arg2: T2, arg3: T3): void;
declare function beforeNextFrame<T1, T2, T3, T4>(cb: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => void, arg1: T1, arg2: T2, arg3: T3, arg4: T4): void;
declare function beforeNextFrame<T extends any[]>(cb: (...args: T) => void, ...args: T): void;
export { beforeNextFrame };

View File

@@ -0,0 +1,12 @@
let cbs = [];
let params = [];
function flushCallbacks() {
cbs.forEach((cb, i) => cb(...params[i]));
cbs = [];
params = [];
}
function beforeNextFrame(cb, ...args) {
cbs.push(cb) === 1 && requestAnimationFrame(flushCallbacks);
params.push(args);
}
export { beforeNextFrame };

View File

@@ -0,0 +1,152 @@
declare const _default: {
readonly aliceblue: "#F0F8FF";
readonly antiquewhite: "#FAEBD7";
readonly aqua: "#0FF";
readonly aquamarine: "#7FFFD4";
readonly azure: "#F0FFFF";
readonly beige: "#F5F5DC";
readonly bisque: "#FFE4C4";
readonly black: "#000";
readonly blanchedalmond: "#FFEBCD";
readonly blue: "#00F";
readonly blueviolet: "#8A2BE2";
readonly brown: "#A52A2A";
readonly burlywood: "#DEB887";
readonly cadetblue: "#5F9EA0";
readonly chartreuse: "#7FFF00";
readonly chocolate: "#D2691E";
readonly coral: "#FF7F50";
readonly cornflowerblue: "#6495ED";
readonly cornsilk: "#FFF8DC";
readonly crimson: "#DC143C";
readonly cyan: "#0FF";
readonly darkblue: "#00008B";
readonly darkcyan: "#008B8B";
readonly darkgoldenrod: "#B8860B";
readonly darkgray: "#A9A9A9";
readonly darkgrey: "#A9A9A9";
readonly darkgreen: "#006400";
readonly darkkhaki: "#BDB76B";
readonly darkmagenta: "#8B008B";
readonly darkolivegreen: "#556B2F";
readonly darkorange: "#FF8C00";
readonly darkorchid: "#9932CC";
readonly darkred: "#8B0000";
readonly darksalmon: "#E9967A";
readonly darkseagreen: "#8FBC8F";
readonly darkslateblue: "#483D8B";
readonly darkslategray: "#2F4F4F";
readonly darkslategrey: "#2F4F4F";
readonly darkturquoise: "#00CED1";
readonly darkviolet: "#9400D3";
readonly deeppink: "#FF1493";
readonly deepskyblue: "#00BFFF";
readonly dimgray: "#696969";
readonly dimgrey: "#696969";
readonly dodgerblue: "#1E90FF";
readonly firebrick: "#B22222";
readonly floralwhite: "#FFFAF0";
readonly forestgreen: "#228B22";
readonly fuchsia: "#F0F";
readonly gainsboro: "#DCDCDC";
readonly ghostwhite: "#F8F8FF";
readonly gold: "#FFD700";
readonly goldenrod: "#DAA520";
readonly gray: "#808080";
readonly grey: "#808080";
readonly green: "#008000";
readonly greenyellow: "#ADFF2F";
readonly honeydew: "#F0FFF0";
readonly hotpink: "#FF69B4";
readonly indianred: "#CD5C5C";
readonly indigo: "#4B0082";
readonly ivory: "#FFFFF0";
readonly khaki: "#F0E68C";
readonly lavender: "#E6E6FA";
readonly lavenderblush: "#FFF0F5";
readonly lawngreen: "#7CFC00";
readonly lemonchiffon: "#FFFACD";
readonly lightblue: "#ADD8E6";
readonly lightcoral: "#F08080";
readonly lightcyan: "#E0FFFF";
readonly lightgoldenrodyellow: "#FAFAD2";
readonly lightgray: "#D3D3D3";
readonly lightgrey: "#D3D3D3";
readonly lightgreen: "#90EE90";
readonly lightpink: "#FFB6C1";
readonly lightsalmon: "#FFA07A";
readonly lightseagreen: "#20B2AA";
readonly lightskyblue: "#87CEFA";
readonly lightslategray: "#778899";
readonly lightslategrey: "#778899";
readonly lightsteelblue: "#B0C4DE";
readonly lightyellow: "#FFFFE0";
readonly lime: "#0F0";
readonly limegreen: "#32CD32";
readonly linen: "#FAF0E6";
readonly magenta: "#F0F";
readonly maroon: "#800000";
readonly mediumaquamarine: "#66CDAA";
readonly mediumblue: "#0000CD";
readonly mediumorchid: "#BA55D3";
readonly mediumpurple: "#9370DB";
readonly mediumseagreen: "#3CB371";
readonly mediumslateblue: "#7B68EE";
readonly mediumspringgreen: "#00FA9A";
readonly mediumturquoise: "#48D1CC";
readonly mediumvioletred: "#C71585";
readonly midnightblue: "#191970";
readonly mintcream: "#F5FFFA";
readonly mistyrose: "#FFE4E1";
readonly moccasin: "#FFE4B5";
readonly navajowhite: "#FFDEAD";
readonly navy: "#000080";
readonly oldlace: "#FDF5E6";
readonly olive: "#808000";
readonly olivedrab: "#6B8E23";
readonly orange: "#FFA500";
readonly orangered: "#FF4500";
readonly orchid: "#DA70D6";
readonly palegoldenrod: "#EEE8AA";
readonly palegreen: "#98FB98";
readonly paleturquoise: "#AFEEEE";
readonly palevioletred: "#DB7093";
readonly papayawhip: "#FFEFD5";
readonly peachpuff: "#FFDAB9";
readonly peru: "#CD853F";
readonly pink: "#FFC0CB";
readonly plum: "#DDA0DD";
readonly powderblue: "#B0E0E6";
readonly purple: "#800080";
readonly rebeccapurple: "#663399";
readonly red: "#F00";
readonly rosybrown: "#BC8F8F";
readonly royalblue: "#4169E1";
readonly saddlebrown: "#8B4513";
readonly salmon: "#FA8072";
readonly sandybrown: "#F4A460";
readonly seagreen: "#2E8B57";
readonly seashell: "#FFF5EE";
readonly sienna: "#A0522D";
readonly silver: "#C0C0C0";
readonly skyblue: "#87CEEB";
readonly slateblue: "#6A5ACD";
readonly slategray: "#708090";
readonly slategrey: "#708090";
readonly snow: "#FFFAFA";
readonly springgreen: "#00FF7F";
readonly steelblue: "#4682B4";
readonly tan: "#D2B48C";
readonly teal: "#008080";
readonly thistle: "#D8BFD8";
readonly tomato: "#FF6347";
readonly turquoise: "#40E0D0";
readonly violet: "#EE82EE";
readonly wheat: "#F5DEB3";
readonly white: "#FFF";
readonly whitesmoke: "#F5F5F5";
readonly yellow: "#FF0";
readonly yellowgreen: "#9ACD32";
readonly transparent: "#0000";
};
export default _default;

View File

@@ -0,0 +1,152 @@
// src: https://www.w3schools.com/colors/colors_names.asp
export default {
aliceblue: "#F0F8FF",
antiquewhite: "#FAEBD7",
aqua: "#0FF",
aquamarine: "#7FFFD4",
azure: "#F0FFFF",
beige: "#F5F5DC",
bisque: "#FFE4C4",
black: "#000",
blanchedalmond: "#FFEBCD",
blue: "#00F",
blueviolet: "#8A2BE2",
brown: "#A52A2A",
burlywood: "#DEB887",
cadetblue: "#5F9EA0",
chartreuse: "#7FFF00",
chocolate: "#D2691E",
coral: "#FF7F50",
cornflowerblue: "#6495ED",
cornsilk: "#FFF8DC",
crimson: "#DC143C",
cyan: "#0FF",
darkblue: "#00008B",
darkcyan: "#008B8B",
darkgoldenrod: "#B8860B",
darkgray: "#A9A9A9",
darkgrey: "#A9A9A9",
darkgreen: "#006400",
darkkhaki: "#BDB76B",
darkmagenta: "#8B008B",
darkolivegreen: "#556B2F",
darkorange: "#FF8C00",
darkorchid: "#9932CC",
darkred: "#8B0000",
darksalmon: "#E9967A",
darkseagreen: "#8FBC8F",
darkslateblue: "#483D8B",
darkslategray: "#2F4F4F",
darkslategrey: "#2F4F4F",
darkturquoise: "#00CED1",
darkviolet: "#9400D3",
deeppink: "#FF1493",
deepskyblue: "#00BFFF",
dimgray: "#696969",
dimgrey: "#696969",
dodgerblue: "#1E90FF",
firebrick: "#B22222",
floralwhite: "#FFFAF0",
forestgreen: "#228B22",
fuchsia: "#F0F",
gainsboro: "#DCDCDC",
ghostwhite: "#F8F8FF",
gold: "#FFD700",
goldenrod: "#DAA520",
gray: "#808080",
grey: "#808080",
green: "#008000",
greenyellow: "#ADFF2F",
honeydew: "#F0FFF0",
hotpink: "#FF69B4",
indianred: "#CD5C5C",
indigo: "#4B0082",
ivory: "#FFFFF0",
khaki: "#F0E68C",
lavender: "#E6E6FA",
lavenderblush: "#FFF0F5",
lawngreen: "#7CFC00",
lemonchiffon: "#FFFACD",
lightblue: "#ADD8E6",
lightcoral: "#F08080",
lightcyan: "#E0FFFF",
lightgoldenrodyellow: "#FAFAD2",
lightgray: "#D3D3D3",
lightgrey: "#D3D3D3",
lightgreen: "#90EE90",
lightpink: "#FFB6C1",
lightsalmon: "#FFA07A",
lightseagreen: "#20B2AA",
lightskyblue: "#87CEFA",
lightslategray: "#778899",
lightslategrey: "#778899",
lightsteelblue: "#B0C4DE",
lightyellow: "#FFFFE0",
lime: "#0F0",
limegreen: "#32CD32",
linen: "#FAF0E6",
magenta: "#F0F",
maroon: "#800000",
mediumaquamarine: "#66CDAA",
mediumblue: "#0000CD",
mediumorchid: "#BA55D3",
mediumpurple: "#9370DB",
mediumseagreen: "#3CB371",
mediumslateblue: "#7B68EE",
mediumspringgreen: "#00FA9A",
mediumturquoise: "#48D1CC",
mediumvioletred: "#C71585",
midnightblue: "#191970",
mintcream: "#F5FFFA",
mistyrose: "#FFE4E1",
moccasin: "#FFE4B5",
navajowhite: "#FFDEAD",
navy: "#000080",
oldlace: "#FDF5E6",
olive: "#808000",
olivedrab: "#6B8E23",
orange: "#FFA500",
orangered: "#FF4500",
orchid: "#DA70D6",
palegoldenrod: "#EEE8AA",
palegreen: "#98FB98",
paleturquoise: "#AFEEEE",
palevioletred: "#DB7093",
papayawhip: "#FFEFD5",
peachpuff: "#FFDAB9",
peru: "#CD853F",
pink: "#FFC0CB",
plum: "#DDA0DD",
powderblue: "#B0E0E6",
purple: "#800080",
rebeccapurple: "#663399",
red: "#F00",
rosybrown: "#BC8F8F",
royalblue: "#4169E1",
saddlebrown: "#8B4513",
salmon: "#FA8072",
sandybrown: "#F4A460",
seagreen: "#2E8B57",
seashell: "#FFF5EE",
sienna: "#A0522D",
silver: "#C0C0C0",
skyblue: "#87CEEB",
slateblue: "#6A5ACD",
slategray: "#708090",
slategrey: "#708090",
snow: "#FFFAFA",
springgreen: "#00FF7F",
steelblue: "#4682B4",
tan: "#D2B48C",
teal: "#008080",
thistle: "#D8BFD8",
tomato: "#FF6347",
turquoise: "#40E0D0",
violet: "#EE82EE",
wheat: "#F5DEB3",
white: "#FFF",
whitesmoke: "#F5F5F5",
yellow: "#FF0",
yellowgreen: "#9ACD32",
transparent: "#0000"
};

View File

@@ -0,0 +1,43 @@
import { RGB, HSV, HSL } from '.';
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [h, s, v] 360, 100, 100
*/
export declare function hsl2hsv(h: number, s: number, l: number): HSV;
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [h, s, l] 360, 100, 100
*/
export declare function hsv2hsl(h: number, s: number, v: number): HSL;
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [r, g, b] 255, 255, 255
*/
export declare function hsv2rgb(h: number, s: number, v: number): RGB;
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export declare function rgb2hsv(r: number, g: number, b: number): HSV;
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export declare function rgb2hsl(r: number, g: number, b: number): HSL;
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [255, 255, 255]
*/
export declare function hsl2rgb(h: number, s: number, l: number): RGB;

View File

@@ -0,0 +1,80 @@
// All the algorithms credit to https://stackoverflow.com/questions/36721830/convert-hsl-to-rgb-and-hex/54014428#54014428
// original author: Kamil Kiełczewski
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [h, s, v] 360, 100, 100
*/
export function hsl2hsv(h, s, l) {
s /= 100;
l /= 100;
const v = s * Math.min(l, 1 - l) + l;
return [h, v ? (2 - (2 * l) / v) * 100 : 0, v * 100];
}
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [h, s, l] 360, 100, 100
*/
export function hsv2hsl(h, s, v) {
s /= 100;
v /= 100;
const l = v - (v * s) / 2;
const m = Math.min(l, 1 - l);
return [h, m ? ((v - l) / m) * 100 : 0, l * 100];
}
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [r, g, b] 255, 255, 255
*/
export function hsv2rgb(h, s, v) {
s /= 100;
v /= 100;
let f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
return [f(5) * 255, f(3) * 255, f(1) * 255];
}
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export function rgb2hsv(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
let v = Math.max(r, g, b), c = v - Math.min(r, g, b);
let h = c && (v == r ? (g - b) / c : v == g ? 2 + (b - r) / c : 4 + (r - g) / c);
return [60 * (h < 0 ? h + 6 : h), v && (c / v) * 100, v * 100];
}
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export function rgb2hsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
let v = Math.max(r, g, b), c = v - Math.min(r, g, b), f = 1 - Math.abs(v + v - c - 1);
let h = c && (v == r ? (g - b) / c : v == g ? 2 + (b - r) / c : 4 + (r - g) / c);
return [60 * (h < 0 ? h + 6 : h), f ? (c / f) * 100 : 0, (v + v - c) * 50];
}
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [255, 255, 255]
*/
export function hsl2rgb(h, s, l) {
s /= 100;
l /= 100;
let a = s * Math.min(l, 1 - l);
let f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return [f(0) * 255, f(8) * 255, f(4) * 255];
}

View File

@@ -0,0 +1,61 @@
export type RGBA = [number, number, number, number];
export type RGB = [number, number, number];
export type HSLA = [number, number, number, number];
export type HSVA = [number, number, number, number];
export type HSL = [number, number, number];
export type HSV = [number, number, number];
/**
* Convert color string to hsla array
* @param color format like hsl(180, 100%, 100%), hsla(180, 100%, 100%, 1)
* @returns
*/
export declare function hsla(color: string): HSLA;
/**
* Convert color string to hsva array
* @param color format like hsv(180, 100%, 100%), hsva(180, 100%, 100%, 1)
* @returns
*/
export declare function hsva(color: string): HSLA;
/**
* Convert color string to rgba array.
* @param color format like #000[0], #000000[00], rgb(0, 0, 0),
* rgba(0, 0, 0, 0), hsl(a) color, hsv(a) color and color keywords and
* transparent
* @returns
*/
export declare function rgba(color: string): RGBA;
export declare function composite(background: string | RGB | RGBA, overlay: string | RGB | RGBA): string;
export interface ChangeColorOptions {
alpha?: number;
}
export declare function changeColor(base: string | RGB | RGBA, options: ChangeColorOptions): string;
export interface ScaleColorOptions {
lightness?: number;
alpha?: number;
}
export declare function scaleColor(base: string | RGB | RGBA, options: ScaleColorOptions): string;
export declare function getAlpha(base: string | RGB | RGBA): number;
export declare function getAlphaString(base: string | RGB | RGBA): string;
export declare function roundAlpha(value: number | string): number;
export declare function roundDeg(value: number | string): number;
export declare function roundChannel(value: number | string): number;
export declare function roundPercent(value: number | string): number;
export declare function toRgbString(base: string | RGB | RGBA): string;
export declare function toRgbaString(base: RGBA | RGB): string;
export declare function toHsvString(base: HSVA | HSV): string;
export declare function toHsvaString(base: HSVA | HSV): string;
export declare function toHslString(base: HSVA | HSV): string;
export declare function toHslaString(base: HSLA | HSL): string;
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export declare function toHexaString(base: RGBA | RGB | string): string;
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export declare function toHexString(base: RGBA | RGB | string): string;
export { hsl2hsv, hsv2hsl, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb } from './convert';

View File

@@ -0,0 +1,300 @@
import colors from './colors';
import { hsl2rgb, hsv2rgb } from './convert';
const prefix = '^\\s*';
const suffix = '\\s*$';
const percent = '\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))%\\s*'; // 4 offset
const float = '\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))\\s*'; // 4 offset
const hex = '([0-9A-Fa-f])';
const dhex = '([0-9A-Fa-f]{2})';
const hslRegex = new RegExp(`${prefix}hsl\\s*\\(${float},${percent},${percent}\\)${suffix}`);
const hsvRegex = new RegExp(`${prefix}hsv\\s*\\(${float},${percent},${percent}\\)${suffix}`);
const hslaRegex = new RegExp(`${prefix}hsla\\s*\\(${float},${percent},${percent},${float}\\)${suffix}`);
const hsvaRegex = new RegExp(`${prefix}hsva\\s*\\(${float},${percent},${percent},${float}\\)${suffix}`);
const rgbRegex = new RegExp(`${prefix}rgb\\s*\\(${float},${float},${float}\\)${suffix}`);
const rgbaRegex = new RegExp(`${prefix}rgba\\s*\\(${float},${float},${float},${float}\\)${suffix}`);
const sHexRegex = new RegExp(`${prefix}#${hex}${hex}${hex}${suffix}`);
const hexRegex = new RegExp(`${prefix}#${dhex}${dhex}${dhex}${suffix}`);
const sHexaRegex = new RegExp(`${prefix}#${hex}${hex}${hex}${hex}${suffix}`);
const hexaRegex = new RegExp(`${prefix}#${dhex}${dhex}${dhex}${dhex}${suffix}`);
function parseHex(value) {
return parseInt(value, 16);
}
/**
* Convert color string to hsla array
* @param color format like hsl(180, 100%, 100%), hsla(180, 100%, 100%, 1)
* @returns
*/
export function hsla(color) {
try {
let i;
if ((i = hslaRegex.exec(color))) {
return [
roundDeg(i[1]),
roundPercent(i[5]),
roundPercent(i[9]),
roundAlpha(i[13])
];
}
else if ((i = hslRegex.exec(color))) {
return [roundDeg(i[1]), roundPercent(i[5]), roundPercent(i[9]), 1];
}
throw new Error(`[seemly/hsla]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
/**
* Convert color string to hsva array
* @param color format like hsv(180, 100%, 100%), hsva(180, 100%, 100%, 1)
* @returns
*/
export function hsva(color) {
try {
let i;
if ((i = hsvaRegex.exec(color))) {
return [
roundDeg(i[1]),
roundPercent(i[5]),
roundPercent(i[9]),
roundAlpha(i[13])
];
}
else if ((i = hsvRegex.exec(color))) {
return [roundDeg(i[1]), roundPercent(i[5]), roundPercent(i[9]), 1];
}
throw new Error(`[seemly/hsva]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
/**
* Convert color string to rgba array.
* @param color format like #000[0], #000000[00], rgb(0, 0, 0),
* rgba(0, 0, 0, 0), hsl(a) color, hsv(a) color and color keywords and
* transparent
* @returns
*/
export function rgba(color) {
try {
let i;
if ((i = hexRegex.exec(color))) {
return [parseHex(i[1]), parseHex(i[2]), parseHex(i[3]), 1];
}
else if ((i = rgbRegex.exec(color))) {
return [roundChannel(i[1]), roundChannel(i[5]), roundChannel(i[9]), 1];
}
else if ((i = rgbaRegex.exec(color))) {
return [
roundChannel(i[1]),
roundChannel(i[5]),
roundChannel(i[9]),
roundAlpha(i[13])
];
}
else if ((i = sHexRegex.exec(color))) {
return [
parseHex(i[1] + i[1]),
parseHex(i[2] + i[2]),
parseHex(i[3] + i[3]),
1
];
}
else if ((i = hexaRegex.exec(color))) {
return [
parseHex(i[1]),
parseHex(i[2]),
parseHex(i[3]),
roundAlpha(parseHex(i[4]) / 255)
];
}
else if ((i = sHexaRegex.exec(color))) {
return [
parseHex(i[1] + i[1]),
parseHex(i[2] + i[2]),
parseHex(i[3] + i[3]),
roundAlpha(parseHex(i[4] + i[4]) / 255)
];
}
else if (color in colors) {
return rgba(colors[color]);
}
else if (hslRegex.test(color) || hslaRegex.test(color)) {
const [h, s, l, a] = hsla(color);
return [...hsl2rgb(h, s, l), a];
}
else if (hsvRegex.test(color) || hsvaRegex.test(color)) {
const [h, s, v, a] = hsva(color);
return [...hsv2rgb(h, s, v), a];
}
throw new Error(`[seemly/rgba]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
function normalizeAlpha(alphaValue) {
return alphaValue > 1 ? 1 : alphaValue < 0 ? 0 : alphaValue;
}
function stringifyRgb(r, g, b) {
return `rgb(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)})`;
}
function stringifyRgba(r, g, b, a) {
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, ${normalizeAlpha(a)})`;
}
function compositeChannel(v1, a1, v2, a2, a) {
return roundChannel((v1 * a1 * (1 - a2) + v2 * a2) / a);
}
export function composite(background, overlay) {
if (!Array.isArray(background))
background = rgba(background);
if (!Array.isArray(overlay))
overlay = rgba(overlay);
const a1 = background[3];
const a2 = overlay[3];
const alpha = roundAlpha(a1 + a2 - a1 * a2);
return stringifyRgba(compositeChannel(background[0], a1, overlay[0], a2, alpha), compositeChannel(background[1], a1, overlay[1], a2, alpha), compositeChannel(background[2], a1, overlay[2], a2, alpha), alpha);
}
export function changeColor(base, options) {
const [r, g, b, a = 1] = Array.isArray(base) ? base : rgba(base);
if (typeof options.alpha === 'number') {
return stringifyRgba(r, g, b, options.alpha);
}
return stringifyRgba(r, g, b, a);
}
export function scaleColor(base, options) {
const [r, g, b, a = 1] = Array.isArray(base) ? base : rgba(base);
const { lightness = 1, alpha = 1 } = options;
return toRgbaString([r * lightness, g * lightness, b * lightness, a * alpha]);
}
export function getAlpha(base) {
var _a;
const alpha = (_a = (Array.isArray(base) ? base : rgba(base))[3]) !== null && _a !== void 0 ? _a : 1;
return alpha;
}
export function getAlphaString(base) {
return `${getAlpha(base)}`;
}
export function roundAlpha(value) {
const v = Math.round(Number(value) * 100) / 100;
if (v > 1)
return 1;
if (v < 0)
return 0;
return v;
}
export function roundDeg(value) {
const v = Math.round(Number(value));
if (v >= 360)
return 0;
if (v < 0)
return 0;
return v;
}
export function roundChannel(value) {
const v = Math.round(Number(value));
if (v > 255)
return 255;
if (v < 0)
return 0;
return v;
}
export function roundPercent(value) {
const v = Math.round(Number(value));
if (v > 100)
return 100;
if (v < 0)
return 0;
return v;
}
export function toRgbString(base) {
const [r, g, b] = Array.isArray(base) ? base : rgba(base);
return stringifyRgb(r, g, b);
}
export function toRgbaString(base) {
const [r, g, b] = base;
if (3 in base) {
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, ${roundAlpha(base[3])})`;
}
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, 1)`;
}
export function toHsvString(base) {
return `hsv(${roundDeg(base[0])}, ${roundPercent(base[1])}%, ${roundPercent(base[2])}%)`;
}
export function toHsvaString(base) {
const [h, s, v] = base;
if (3 in base) {
return `hsva(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(v)}%, ${roundAlpha(base[3])})`;
}
return `hsva(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(v)}%, 1)`;
}
export function toHslString(base) {
return `hsl(${roundDeg(base[0])}, ${roundPercent(base[1])}%, ${roundPercent(base[2])}%)`;
}
export function toHslaString(base) {
const [h, s, l] = base;
if (3 in base) {
return `hsla(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(l)}%, ${roundAlpha(base[3])})`;
}
return `hsla(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(l)}%, 1)`;
}
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export function toHexaString(base) {
if (typeof base === 'string') {
let i;
if (i = hexRegex.exec(base)) {
return `${i[0]}FF`;
}
else if (i = hexaRegex.exec(base)) {
return i[0];
}
else if (i = sHexRegex.exec(base)) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}FF`;
}
else if (i = sHexaRegex.exec(base)) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}${i[4]}${i[4]}`;
}
throw new Error(`[seemly/toHexString]: Invalid hex value ${base}.`);
}
const hex = `#${base
.slice(0, 3)
.map((unit) => roundChannel(unit).toString(16).toUpperCase().padStart(2, '0'))
.join('')}`;
const a = base.length === 3
? 'FF'
: roundChannel(base[3] * 255)
.toString(16)
.padStart(2, '0')
.toUpperCase();
return hex + a;
}
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export function toHexString(base) {
if (typeof base === 'string') {
let i;
if (i = hexRegex.exec(base)) {
return i[0];
}
else if (i = hexaRegex.exec(base)) {
return i[0].slice(0, 7);
}
else if (i = (sHexRegex.exec(base) || sHexaRegex.exec(base))) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}`;
}
throw new Error(`[seemly/toHexString]: Invalid hex value ${base}.`);
}
return `#${base
.slice(0, 3)
.map((unit) => roundChannel(unit).toString(16).toUpperCase().padStart(2, '0'))
.join('')}`;
}
export { hsl2hsv, hsv2hsl, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb } from './convert';

View File

@@ -0,0 +1,20 @@
export declare function depx(value: string | number): number;
declare function pxfy<T extends string | number | undefined | null>(value: T): T extends string | number ? string : undefined;
export { pxfy };
export type Position = 'top' | 'right' | 'bottom' | 'left';
export interface Margin {
top: string;
right: string;
bottom: string;
left: string;
}
declare function getMargin(value: string): Margin;
declare function getMargin(value: string, position: Position): string;
export interface Gap {
row: string;
col: string;
}
declare function getGap(value: string): Gap;
declare function getGap(value: string, orient: 'row' | 'col'): string;
export { getMargin, getMargin as getPadding, getGap };
export { parseResponsiveProp, parseResponsivePropValue } from './responsive';

View File

@@ -0,0 +1,63 @@
export function depx(value) {
if (typeof value === 'string') {
if (value.endsWith('px')) {
return Number(value.slice(0, value.length - 2));
}
return Number(value);
}
return value;
}
function pxfy(value) {
if (value === undefined || value === null)
return undefined;
if (typeof value === 'number')
return `${value}px`;
if (value.endsWith('px'))
return value;
return `${value}px`;
}
export { pxfy };
function getMargin(value, position) {
const parts = value.trim().split(/\s+/g);
const margin = {
top: parts[0]
};
switch (parts.length) {
case 1:
margin.right = parts[0];
margin.bottom = parts[0];
margin.left = parts[0];
break;
case 2:
margin.right = parts[1];
margin.left = parts[1];
margin.bottom = parts[0];
break;
case 3:
margin.right = parts[1];
margin.bottom = parts[2];
margin.left = parts[1];
break;
case 4:
margin.right = parts[1];
margin.bottom = parts[2];
margin.left = parts[3];
break;
default:
throw new Error('[seemly/getMargin]:' + value + ' is not a valid value.');
}
if (position === undefined)
return margin;
return margin[position];
}
function getGap(value, orient) {
const [rowGap, colGap] = value.split(' ');
if (!orient)
return {
row: rowGap,
col: colGap || rowGap
};
return orient === 'row' ? rowGap : colGap;
}
export { getMargin, getMargin as getPadding, getGap };
export { parseResponsiveProp, parseResponsivePropValue } from './responsive';

View File

@@ -0,0 +1,11 @@
export declare function parseResponsiveProp(reponsiveProp: string | number): Record<string, string>;
declare function parseResponsivePropValue(reponsiveProp: undefined | null, activeKeyOrSize?: number | string | undefined): undefined;
declare function parseResponsivePropValue(// query by string
reponsiveProp: string | number, activeKey?: string | undefined): string | undefined;
declare function parseResponsivePropValue(// query by number
reponsiveProp: string | number, activeSize?: number | undefined): string | undefined;
declare function parseResponsivePropValue(// query by number
reponsiveProp: string | number, activeSize?: string[]): string | undefined;
declare function parseResponsivePropValue(// fallback
reponsiveProp: string | number | undefined | null, activeKeyOrSize?: number | string | string[] | undefined): string | undefined;
export { parseResponsivePropValue };

View File

@@ -0,0 +1,55 @@
export function parseResponsiveProp(reponsiveProp) {
if (typeof reponsiveProp === "number") {
return {
'': reponsiveProp.toString()
};
}
const params = {};
reponsiveProp.split(/ +/).forEach((pairLiteral) => {
if (pairLiteral === '')
return;
const [prefix, value] = pairLiteral.split(':');
if (value === undefined) {
params[''] = prefix;
}
else {
params[prefix] = value;
}
});
return params;
}
function parseResponsivePropValue(reponsiveProp, activeKeyOrSize) {
var _a;
if (reponsiveProp === undefined || reponsiveProp === null)
return undefined;
const classObj = parseResponsiveProp(reponsiveProp);
if (activeKeyOrSize === undefined)
return classObj[''];
if (typeof activeKeyOrSize === 'string') {
return (_a = classObj[activeKeyOrSize]) !== null && _a !== void 0 ? _a : classObj[''];
}
else if (Array.isArray(activeKeyOrSize)) {
for (let i = activeKeyOrSize.length - 1; i >= 0; --i) {
const key = activeKeyOrSize[i];
if (key in classObj)
return classObj[key];
}
return classObj[''];
}
else {
// Here we suppose all the keys are number formatted
let activeValue = undefined;
let activeKey = -1;
Object.keys(classObj).forEach((key) => {
const keyAsNum = Number(key);
if (!Number.isNaN(keyAsNum) &&
activeKeyOrSize >= keyAsNum &&
keyAsNum >= activeKey) {
activeKey = keyAsNum;
activeValue = classObj[key];
}
});
return activeValue;
}
}
export { parseResponsivePropValue };

View File

@@ -0,0 +1 @@
export declare function getPreciseEventTarget(event: Event): EventTarget | null;

View File

@@ -0,0 +1,3 @@
export function getPreciseEventTarget(event) {
return event.composedPath()[0] || null;
}

View File

@@ -0,0 +1 @@
export declare function getScrollParent(node: Node | null): HTMLElement | null;

View File

@@ -0,0 +1,28 @@
function getParentNode(node) {
// document type
if (node.nodeType === 9) {
return null;
}
return node.parentNode;
}
export function getScrollParent(node) {
if (node === null)
return null;
const parentNode = getParentNode(node);
if (parentNode === null) {
return null;
}
// Document
if (parentNode.nodeType === 9) {
return document.documentElement;
}
// Element
if (parentNode.nodeType === 1) {
// Firefox want us to check `-x` and `-y` variations as well
const { overflow, overflowX, overflowY } = getComputedStyle(parentNode);
if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
return parentNode;
}
}
return getScrollParent(parentNode);
}

View File

@@ -0,0 +1,3 @@
export declare function happensIn(e: {
target: EventTarget | null;
}, dataSetPropName: string): boolean;

View File

@@ -0,0 +1,11 @@
export function happensIn(e, dataSetPropName) {
let { target } = e;
while (target) {
if (target.dataset) {
if (target.dataset[dataSetPropName] !== undefined)
return true;
}
target = target.parentElement;
}
return false;
}

View File

@@ -0,0 +1,3 @@
type GetElement = () => HTMLElement;
declare function unwrapElement<T>(target: T | string | GetElement): T extends HTMLElement ? HTMLElement : HTMLElement | null;
export { unwrapElement };

View File

@@ -0,0 +1,8 @@
function unwrapElement(target) {
if (typeof target === 'string')
return document.querySelector(target);
if (typeof target === 'function')
return target();
return target;
}
export { unwrapElement };

View File

@@ -0,0 +1,9 @@
export { beforeNextFrameOnce } from './animation/next-frame-once';
export { beforeNextFrame } from './animation/next-frame';
export { getScrollParent } from './dom/get-scroll-parent';
export { unwrapElement } from './dom/unwrap-element';
export { happensIn } from './dom/happens-in';
export { getPreciseEventTarget } from './dom/get-precise-event-target';
export { depx, pxfy, getPadding, getMargin, getGap, parseResponsiveProp, parseResponsivePropValue, Position, Margin } from './css';
export { changeColor, rgba, composite, scaleColor, getAlphaString, getAlpha, hsv2hsl, hsl2hsv, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb, hsla, hsva, toHslString, toHslaString, toHsvString, toHsvaString, toRgbaString, toRgbString, toHexaString, toHexString, roundPercent, roundDeg, roundAlpha, roundChannel, ChangeColorOptions, ScaleColorOptions, RGB, RGBA, HSL, HSLA, HSV, HSVA } from './color';
export { createId, repeat, indexMap, sleep } from './misc/index';

View File

@@ -0,0 +1,9 @@
export { beforeNextFrameOnce } from './animation/next-frame-once';
export { beforeNextFrame } from './animation/next-frame';
export { getScrollParent } from './dom/get-scroll-parent';
export { unwrapElement } from './dom/unwrap-element';
export { happensIn } from './dom/happens-in';
export { getPreciseEventTarget } from './dom/get-precise-event-target';
export { depx, pxfy, getPadding, getMargin, getGap, parseResponsiveProp, parseResponsivePropValue } from './css';
export { changeColor, rgba, composite, scaleColor, getAlphaString, getAlpha, hsv2hsl, hsl2hsv, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb, hsla, hsva, toHslString, toHslaString, toHsvString, toHsvaString, toRgbaString, toRgbString, toHexaString, toHexString, roundPercent, roundDeg, roundAlpha, roundChannel } from './color';
export { createId, repeat, indexMap, sleep } from './misc/index';

View File

@@ -0,0 +1,6 @@
export declare function createId(length?: number): string;
export declare function repeat<T>(count: number, v: T): T[];
declare function indexMap(count: number): number[];
declare function indexMap<T>(count: number, createValue: (index: number) => T): T[];
export { indexMap };
export declare function sleep(ms: number): Promise<void>;

View File

@@ -0,0 +1,31 @@
export function createId(length = 8) {
return Math.random()
.toString(16)
.slice(2, 2 + length);
}
export function repeat(count, v) {
const ret = [];
for (let i = 0; i < count; ++i) {
ret.push(v);
}
return ret;
}
function indexMap(count, createValue) {
const ret = [];
if (!createValue) {
for (let i = 0; i < count; ++i) {
ret.push(i);
}
return ret;
}
for (let i = 0; i < count; ++i) {
ret.push(createValue(i));
}
return ret;
}
export { indexMap };
export async function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}

View File

@@ -0,0 +1,2 @@
export declare function warnOnce(location: string, message: string): void;
export declare function warn(location: string, message: string): void;

View File

@@ -0,0 +1,10 @@
const warnedMessages = new Set();
export function warnOnce(location, message) {
const mergedMessage = `[seemly/${location}]: ${message}`;
if (warnedMessages.has(mergedMessage))
return;
warnedMessages.add(mergedMessage);
}
export function warn(location, message) {
console.error(`[seemly/${location}]: ${message}`);
}

View File

@@ -0,0 +1,7 @@
declare function beforeNextFrameOnce(cb: () => void): void;
declare function beforeNextFrameOnce<T1>(cb: (arg1: T1) => void, arg1: T1): void;
declare function beforeNextFrameOnce<T1, T2>(cb: (arg1: T1, arg2: T2) => void, arg1: T1, arg2: T2): void;
declare function beforeNextFrameOnce<T1, T2, T3>(cb: (arg1: T1, arg2: T2, arg3: T3) => void, arg1: T1, arg2: T2, arg3: T3): void;
declare function beforeNextFrameOnce<T1, T2, T3, T4>(cb: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => void, arg1: T1, arg2: T2, arg3: T3, arg4: T4): void;
declare function beforeNextFrameOnce<T extends any[]>(cb: (...args: T) => void, ...params: T): void;
export { beforeNextFrameOnce };

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.beforeNextFrameOnce = beforeNextFrameOnce;
let onceCbs = [];
const paramsMap = new WeakMap();
function flushOnceCallbacks() {
onceCbs.forEach((cb) => cb(...paramsMap.get(cb)));
onceCbs = [];
}
function beforeNextFrameOnce(cb, ...params) {
paramsMap.set(cb, params);
if (onceCbs.includes(cb))
return;
onceCbs.push(cb) === 1 && requestAnimationFrame(flushOnceCallbacks);
}

View File

@@ -0,0 +1,7 @@
declare function beforeNextFrame(cb: () => void): void;
declare function beforeNextFrame<T1>(cb: (arg1: T1) => void, arg1: T1): void;
declare function beforeNextFrame<T1, T2>(cb: (arg1: T1, arg2: T2) => void, arg1: T1, arg2: T2): void;
declare function beforeNextFrame<T1, T2, T3>(cb: (arg1: T1, arg2: T2, arg3: T3) => void, arg1: T1, arg2: T2, arg3: T3): void;
declare function beforeNextFrame<T1, T2, T3, T4>(cb: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => void, arg1: T1, arg2: T2, arg3: T3, arg4: T4): void;
declare function beforeNextFrame<T extends any[]>(cb: (...args: T) => void, ...args: T): void;
export { beforeNextFrame };

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.beforeNextFrame = beforeNextFrame;
let cbs = [];
let params = [];
function flushCallbacks() {
cbs.forEach((cb, i) => cb(...params[i]));
cbs = [];
params = [];
}
function beforeNextFrame(cb, ...args) {
cbs.push(cb) === 1 && requestAnimationFrame(flushCallbacks);
params.push(args);
}

View File

@@ -0,0 +1,152 @@
declare const _default: {
readonly aliceblue: "#F0F8FF";
readonly antiquewhite: "#FAEBD7";
readonly aqua: "#0FF";
readonly aquamarine: "#7FFFD4";
readonly azure: "#F0FFFF";
readonly beige: "#F5F5DC";
readonly bisque: "#FFE4C4";
readonly black: "#000";
readonly blanchedalmond: "#FFEBCD";
readonly blue: "#00F";
readonly blueviolet: "#8A2BE2";
readonly brown: "#A52A2A";
readonly burlywood: "#DEB887";
readonly cadetblue: "#5F9EA0";
readonly chartreuse: "#7FFF00";
readonly chocolate: "#D2691E";
readonly coral: "#FF7F50";
readonly cornflowerblue: "#6495ED";
readonly cornsilk: "#FFF8DC";
readonly crimson: "#DC143C";
readonly cyan: "#0FF";
readonly darkblue: "#00008B";
readonly darkcyan: "#008B8B";
readonly darkgoldenrod: "#B8860B";
readonly darkgray: "#A9A9A9";
readonly darkgrey: "#A9A9A9";
readonly darkgreen: "#006400";
readonly darkkhaki: "#BDB76B";
readonly darkmagenta: "#8B008B";
readonly darkolivegreen: "#556B2F";
readonly darkorange: "#FF8C00";
readonly darkorchid: "#9932CC";
readonly darkred: "#8B0000";
readonly darksalmon: "#E9967A";
readonly darkseagreen: "#8FBC8F";
readonly darkslateblue: "#483D8B";
readonly darkslategray: "#2F4F4F";
readonly darkslategrey: "#2F4F4F";
readonly darkturquoise: "#00CED1";
readonly darkviolet: "#9400D3";
readonly deeppink: "#FF1493";
readonly deepskyblue: "#00BFFF";
readonly dimgray: "#696969";
readonly dimgrey: "#696969";
readonly dodgerblue: "#1E90FF";
readonly firebrick: "#B22222";
readonly floralwhite: "#FFFAF0";
readonly forestgreen: "#228B22";
readonly fuchsia: "#F0F";
readonly gainsboro: "#DCDCDC";
readonly ghostwhite: "#F8F8FF";
readonly gold: "#FFD700";
readonly goldenrod: "#DAA520";
readonly gray: "#808080";
readonly grey: "#808080";
readonly green: "#008000";
readonly greenyellow: "#ADFF2F";
readonly honeydew: "#F0FFF0";
readonly hotpink: "#FF69B4";
readonly indianred: "#CD5C5C";
readonly indigo: "#4B0082";
readonly ivory: "#FFFFF0";
readonly khaki: "#F0E68C";
readonly lavender: "#E6E6FA";
readonly lavenderblush: "#FFF0F5";
readonly lawngreen: "#7CFC00";
readonly lemonchiffon: "#FFFACD";
readonly lightblue: "#ADD8E6";
readonly lightcoral: "#F08080";
readonly lightcyan: "#E0FFFF";
readonly lightgoldenrodyellow: "#FAFAD2";
readonly lightgray: "#D3D3D3";
readonly lightgrey: "#D3D3D3";
readonly lightgreen: "#90EE90";
readonly lightpink: "#FFB6C1";
readonly lightsalmon: "#FFA07A";
readonly lightseagreen: "#20B2AA";
readonly lightskyblue: "#87CEFA";
readonly lightslategray: "#778899";
readonly lightslategrey: "#778899";
readonly lightsteelblue: "#B0C4DE";
readonly lightyellow: "#FFFFE0";
readonly lime: "#0F0";
readonly limegreen: "#32CD32";
readonly linen: "#FAF0E6";
readonly magenta: "#F0F";
readonly maroon: "#800000";
readonly mediumaquamarine: "#66CDAA";
readonly mediumblue: "#0000CD";
readonly mediumorchid: "#BA55D3";
readonly mediumpurple: "#9370DB";
readonly mediumseagreen: "#3CB371";
readonly mediumslateblue: "#7B68EE";
readonly mediumspringgreen: "#00FA9A";
readonly mediumturquoise: "#48D1CC";
readonly mediumvioletred: "#C71585";
readonly midnightblue: "#191970";
readonly mintcream: "#F5FFFA";
readonly mistyrose: "#FFE4E1";
readonly moccasin: "#FFE4B5";
readonly navajowhite: "#FFDEAD";
readonly navy: "#000080";
readonly oldlace: "#FDF5E6";
readonly olive: "#808000";
readonly olivedrab: "#6B8E23";
readonly orange: "#FFA500";
readonly orangered: "#FF4500";
readonly orchid: "#DA70D6";
readonly palegoldenrod: "#EEE8AA";
readonly palegreen: "#98FB98";
readonly paleturquoise: "#AFEEEE";
readonly palevioletred: "#DB7093";
readonly papayawhip: "#FFEFD5";
readonly peachpuff: "#FFDAB9";
readonly peru: "#CD853F";
readonly pink: "#FFC0CB";
readonly plum: "#DDA0DD";
readonly powderblue: "#B0E0E6";
readonly purple: "#800080";
readonly rebeccapurple: "#663399";
readonly red: "#F00";
readonly rosybrown: "#BC8F8F";
readonly royalblue: "#4169E1";
readonly saddlebrown: "#8B4513";
readonly salmon: "#FA8072";
readonly sandybrown: "#F4A460";
readonly seagreen: "#2E8B57";
readonly seashell: "#FFF5EE";
readonly sienna: "#A0522D";
readonly silver: "#C0C0C0";
readonly skyblue: "#87CEEB";
readonly slateblue: "#6A5ACD";
readonly slategray: "#708090";
readonly slategrey: "#708090";
readonly snow: "#FFFAFA";
readonly springgreen: "#00FF7F";
readonly steelblue: "#4682B4";
readonly tan: "#D2B48C";
readonly teal: "#008080";
readonly thistle: "#D8BFD8";
readonly tomato: "#FF6347";
readonly turquoise: "#40E0D0";
readonly violet: "#EE82EE";
readonly wheat: "#F5DEB3";
readonly white: "#FFF";
readonly whitesmoke: "#F5F5F5";
readonly yellow: "#FF0";
readonly yellowgreen: "#9ACD32";
readonly transparent: "#0000";
};
export default _default;

View File

@@ -0,0 +1,154 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// src: https://www.w3schools.com/colors/colors_names.asp
exports.default = {
aliceblue: "#F0F8FF",
antiquewhite: "#FAEBD7",
aqua: "#0FF",
aquamarine: "#7FFFD4",
azure: "#F0FFFF",
beige: "#F5F5DC",
bisque: "#FFE4C4",
black: "#000",
blanchedalmond: "#FFEBCD",
blue: "#00F",
blueviolet: "#8A2BE2",
brown: "#A52A2A",
burlywood: "#DEB887",
cadetblue: "#5F9EA0",
chartreuse: "#7FFF00",
chocolate: "#D2691E",
coral: "#FF7F50",
cornflowerblue: "#6495ED",
cornsilk: "#FFF8DC",
crimson: "#DC143C",
cyan: "#0FF",
darkblue: "#00008B",
darkcyan: "#008B8B",
darkgoldenrod: "#B8860B",
darkgray: "#A9A9A9",
darkgrey: "#A9A9A9",
darkgreen: "#006400",
darkkhaki: "#BDB76B",
darkmagenta: "#8B008B",
darkolivegreen: "#556B2F",
darkorange: "#FF8C00",
darkorchid: "#9932CC",
darkred: "#8B0000",
darksalmon: "#E9967A",
darkseagreen: "#8FBC8F",
darkslateblue: "#483D8B",
darkslategray: "#2F4F4F",
darkslategrey: "#2F4F4F",
darkturquoise: "#00CED1",
darkviolet: "#9400D3",
deeppink: "#FF1493",
deepskyblue: "#00BFFF",
dimgray: "#696969",
dimgrey: "#696969",
dodgerblue: "#1E90FF",
firebrick: "#B22222",
floralwhite: "#FFFAF0",
forestgreen: "#228B22",
fuchsia: "#F0F",
gainsboro: "#DCDCDC",
ghostwhite: "#F8F8FF",
gold: "#FFD700",
goldenrod: "#DAA520",
gray: "#808080",
grey: "#808080",
green: "#008000",
greenyellow: "#ADFF2F",
honeydew: "#F0FFF0",
hotpink: "#FF69B4",
indianred: "#CD5C5C",
indigo: "#4B0082",
ivory: "#FFFFF0",
khaki: "#F0E68C",
lavender: "#E6E6FA",
lavenderblush: "#FFF0F5",
lawngreen: "#7CFC00",
lemonchiffon: "#FFFACD",
lightblue: "#ADD8E6",
lightcoral: "#F08080",
lightcyan: "#E0FFFF",
lightgoldenrodyellow: "#FAFAD2",
lightgray: "#D3D3D3",
lightgrey: "#D3D3D3",
lightgreen: "#90EE90",
lightpink: "#FFB6C1",
lightsalmon: "#FFA07A",
lightseagreen: "#20B2AA",
lightskyblue: "#87CEFA",
lightslategray: "#778899",
lightslategrey: "#778899",
lightsteelblue: "#B0C4DE",
lightyellow: "#FFFFE0",
lime: "#0F0",
limegreen: "#32CD32",
linen: "#FAF0E6",
magenta: "#F0F",
maroon: "#800000",
mediumaquamarine: "#66CDAA",
mediumblue: "#0000CD",
mediumorchid: "#BA55D3",
mediumpurple: "#9370DB",
mediumseagreen: "#3CB371",
mediumslateblue: "#7B68EE",
mediumspringgreen: "#00FA9A",
mediumturquoise: "#48D1CC",
mediumvioletred: "#C71585",
midnightblue: "#191970",
mintcream: "#F5FFFA",
mistyrose: "#FFE4E1",
moccasin: "#FFE4B5",
navajowhite: "#FFDEAD",
navy: "#000080",
oldlace: "#FDF5E6",
olive: "#808000",
olivedrab: "#6B8E23",
orange: "#FFA500",
orangered: "#FF4500",
orchid: "#DA70D6",
palegoldenrod: "#EEE8AA",
palegreen: "#98FB98",
paleturquoise: "#AFEEEE",
palevioletred: "#DB7093",
papayawhip: "#FFEFD5",
peachpuff: "#FFDAB9",
peru: "#CD853F",
pink: "#FFC0CB",
plum: "#DDA0DD",
powderblue: "#B0E0E6",
purple: "#800080",
rebeccapurple: "#663399",
red: "#F00",
rosybrown: "#BC8F8F",
royalblue: "#4169E1",
saddlebrown: "#8B4513",
salmon: "#FA8072",
sandybrown: "#F4A460",
seagreen: "#2E8B57",
seashell: "#FFF5EE",
sienna: "#A0522D",
silver: "#C0C0C0",
skyblue: "#87CEEB",
slateblue: "#6A5ACD",
slategray: "#708090",
slategrey: "#708090",
snow: "#FFFAFA",
springgreen: "#00FF7F",
steelblue: "#4682B4",
tan: "#D2B48C",
teal: "#008080",
thistle: "#D8BFD8",
tomato: "#FF6347",
turquoise: "#40E0D0",
violet: "#EE82EE",
wheat: "#F5DEB3",
white: "#FFF",
whitesmoke: "#F5F5F5",
yellow: "#FF0",
yellowgreen: "#9ACD32",
transparent: "#0000"
};

View File

@@ -0,0 +1,43 @@
import { RGB, HSV, HSL } from '.';
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [h, s, v] 360, 100, 100
*/
export declare function hsl2hsv(h: number, s: number, l: number): HSV;
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [h, s, l] 360, 100, 100
*/
export declare function hsv2hsl(h: number, s: number, v: number): HSL;
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [r, g, b] 255, 255, 255
*/
export declare function hsv2rgb(h: number, s: number, v: number): RGB;
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export declare function rgb2hsv(r: number, g: number, b: number): HSV;
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
export declare function rgb2hsl(r: number, g: number, b: number): HSL;
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [255, 255, 255]
*/
export declare function hsl2rgb(h: number, s: number, l: number): RGB;

View File

@@ -0,0 +1,88 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hsl2hsv = hsl2hsv;
exports.hsv2hsl = hsv2hsl;
exports.hsv2rgb = hsv2rgb;
exports.rgb2hsv = rgb2hsv;
exports.rgb2hsl = rgb2hsl;
exports.hsl2rgb = hsl2rgb;
// All the algorithms credit to https://stackoverflow.com/questions/36721830/convert-hsl-to-rgb-and-hex/54014428#54014428
// original author: Kamil Kiełczewski
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [h, s, v] 360, 100, 100
*/
function hsl2hsv(h, s, l) {
s /= 100;
l /= 100;
const v = s * Math.min(l, 1 - l) + l;
return [h, v ? (2 - (2 * l) / v) * 100 : 0, v * 100];
}
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [h, s, l] 360, 100, 100
*/
function hsv2hsl(h, s, v) {
s /= 100;
v /= 100;
const l = v - (v * s) / 2;
const m = Math.min(l, 1 - l);
return [h, m ? ((v - l) / m) * 100 : 0, l * 100];
}
/**
* @param h 360
* @param s 100
* @param v 100
* @returns [r, g, b] 255, 255, 255
*/
function hsv2rgb(h, s, v) {
s /= 100;
v /= 100;
let f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
return [f(5) * 255, f(3) * 255, f(1) * 255];
}
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
function rgb2hsv(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
let v = Math.max(r, g, b), c = v - Math.min(r, g, b);
let h = c && (v == r ? (g - b) / c : v == g ? 2 + (b - r) / c : 4 + (r - g) / c);
return [60 * (h < 0 ? h + 6 : h), v && (c / v) * 100, v * 100];
}
/**
* @param r 255
* @param g 255
* @param b 255
* @returns [360, 100, 100]
*/
function rgb2hsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
let v = Math.max(r, g, b), c = v - Math.min(r, g, b), f = 1 - Math.abs(v + v - c - 1);
let h = c && (v == r ? (g - b) / c : v == g ? 2 + (b - r) / c : 4 + (r - g) / c);
return [60 * (h < 0 ? h + 6 : h), f ? (c / f) * 100 : 0, (v + v - c) * 50];
}
/**
* @param h 360
* @param s 100
* @param l 100
* @returns [255, 255, 255]
*/
function hsl2rgb(h, s, l) {
s /= 100;
l /= 100;
let a = s * Math.min(l, 1 - l);
let f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return [f(0) * 255, f(8) * 255, f(4) * 255];
}

View File

@@ -0,0 +1,61 @@
export type RGBA = [number, number, number, number];
export type RGB = [number, number, number];
export type HSLA = [number, number, number, number];
export type HSVA = [number, number, number, number];
export type HSL = [number, number, number];
export type HSV = [number, number, number];
/**
* Convert color string to hsla array
* @param color format like hsl(180, 100%, 100%), hsla(180, 100%, 100%, 1)
* @returns
*/
export declare function hsla(color: string): HSLA;
/**
* Convert color string to hsva array
* @param color format like hsv(180, 100%, 100%), hsva(180, 100%, 100%, 1)
* @returns
*/
export declare function hsva(color: string): HSLA;
/**
* Convert color string to rgba array.
* @param color format like #000[0], #000000[00], rgb(0, 0, 0),
* rgba(0, 0, 0, 0), hsl(a) color, hsv(a) color and color keywords and
* transparent
* @returns
*/
export declare function rgba(color: string): RGBA;
export declare function composite(background: string | RGB | RGBA, overlay: string | RGB | RGBA): string;
export interface ChangeColorOptions {
alpha?: number;
}
export declare function changeColor(base: string | RGB | RGBA, options: ChangeColorOptions): string;
export interface ScaleColorOptions {
lightness?: number;
alpha?: number;
}
export declare function scaleColor(base: string | RGB | RGBA, options: ScaleColorOptions): string;
export declare function getAlpha(base: string | RGB | RGBA): number;
export declare function getAlphaString(base: string | RGB | RGBA): string;
export declare function roundAlpha(value: number | string): number;
export declare function roundDeg(value: number | string): number;
export declare function roundChannel(value: number | string): number;
export declare function roundPercent(value: number | string): number;
export declare function toRgbString(base: string | RGB | RGBA): string;
export declare function toRgbaString(base: RGBA | RGB): string;
export declare function toHsvString(base: HSVA | HSV): string;
export declare function toHsvaString(base: HSVA | HSV): string;
export declare function toHslString(base: HSVA | HSV): string;
export declare function toHslaString(base: HSLA | HSL): string;
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export declare function toHexaString(base: RGBA | RGB | string): string;
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
export declare function toHexString(base: RGBA | RGB | string): string;
export { hsl2hsv, hsv2hsl, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb } from './convert';

View File

@@ -0,0 +1,329 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hsl2rgb = exports.rgb2hsl = exports.rgb2hsv = exports.hsv2rgb = exports.hsv2hsl = exports.hsl2hsv = void 0;
exports.hsla = hsla;
exports.hsva = hsva;
exports.rgba = rgba;
exports.composite = composite;
exports.changeColor = changeColor;
exports.scaleColor = scaleColor;
exports.getAlpha = getAlpha;
exports.getAlphaString = getAlphaString;
exports.roundAlpha = roundAlpha;
exports.roundDeg = roundDeg;
exports.roundChannel = roundChannel;
exports.roundPercent = roundPercent;
exports.toRgbString = toRgbString;
exports.toRgbaString = toRgbaString;
exports.toHsvString = toHsvString;
exports.toHsvaString = toHsvaString;
exports.toHslString = toHslString;
exports.toHslaString = toHslaString;
exports.toHexaString = toHexaString;
exports.toHexString = toHexString;
const colors_1 = require("./colors");
const convert_1 = require("./convert");
const prefix = '^\\s*';
const suffix = '\\s*$';
const percent = '\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))%\\s*'; // 4 offset
const float = '\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))\\s*'; // 4 offset
const hex = '([0-9A-Fa-f])';
const dhex = '([0-9A-Fa-f]{2})';
const hslRegex = new RegExp(`${prefix}hsl\\s*\\(${float},${percent},${percent}\\)${suffix}`);
const hsvRegex = new RegExp(`${prefix}hsv\\s*\\(${float},${percent},${percent}\\)${suffix}`);
const hslaRegex = new RegExp(`${prefix}hsla\\s*\\(${float},${percent},${percent},${float}\\)${suffix}`);
const hsvaRegex = new RegExp(`${prefix}hsva\\s*\\(${float},${percent},${percent},${float}\\)${suffix}`);
const rgbRegex = new RegExp(`${prefix}rgb\\s*\\(${float},${float},${float}\\)${suffix}`);
const rgbaRegex = new RegExp(`${prefix}rgba\\s*\\(${float},${float},${float},${float}\\)${suffix}`);
const sHexRegex = new RegExp(`${prefix}#${hex}${hex}${hex}${suffix}`);
const hexRegex = new RegExp(`${prefix}#${dhex}${dhex}${dhex}${suffix}`);
const sHexaRegex = new RegExp(`${prefix}#${hex}${hex}${hex}${hex}${suffix}`);
const hexaRegex = new RegExp(`${prefix}#${dhex}${dhex}${dhex}${dhex}${suffix}`);
function parseHex(value) {
return parseInt(value, 16);
}
/**
* Convert color string to hsla array
* @param color format like hsl(180, 100%, 100%), hsla(180, 100%, 100%, 1)
* @returns
*/
function hsla(color) {
try {
let i;
if ((i = hslaRegex.exec(color))) {
return [
roundDeg(i[1]),
roundPercent(i[5]),
roundPercent(i[9]),
roundAlpha(i[13])
];
}
else if ((i = hslRegex.exec(color))) {
return [roundDeg(i[1]), roundPercent(i[5]), roundPercent(i[9]), 1];
}
throw new Error(`[seemly/hsla]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
/**
* Convert color string to hsva array
* @param color format like hsv(180, 100%, 100%), hsva(180, 100%, 100%, 1)
* @returns
*/
function hsva(color) {
try {
let i;
if ((i = hsvaRegex.exec(color))) {
return [
roundDeg(i[1]),
roundPercent(i[5]),
roundPercent(i[9]),
roundAlpha(i[13])
];
}
else if ((i = hsvRegex.exec(color))) {
return [roundDeg(i[1]), roundPercent(i[5]), roundPercent(i[9]), 1];
}
throw new Error(`[seemly/hsva]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
/**
* Convert color string to rgba array.
* @param color format like #000[0], #000000[00], rgb(0, 0, 0),
* rgba(0, 0, 0, 0), hsl(a) color, hsv(a) color and color keywords and
* transparent
* @returns
*/
function rgba(color) {
try {
let i;
if ((i = hexRegex.exec(color))) {
return [parseHex(i[1]), parseHex(i[2]), parseHex(i[3]), 1];
}
else if ((i = rgbRegex.exec(color))) {
return [roundChannel(i[1]), roundChannel(i[5]), roundChannel(i[9]), 1];
}
else if ((i = rgbaRegex.exec(color))) {
return [
roundChannel(i[1]),
roundChannel(i[5]),
roundChannel(i[9]),
roundAlpha(i[13])
];
}
else if ((i = sHexRegex.exec(color))) {
return [
parseHex(i[1] + i[1]),
parseHex(i[2] + i[2]),
parseHex(i[3] + i[3]),
1
];
}
else if ((i = hexaRegex.exec(color))) {
return [
parseHex(i[1]),
parseHex(i[2]),
parseHex(i[3]),
roundAlpha(parseHex(i[4]) / 255)
];
}
else if ((i = sHexaRegex.exec(color))) {
return [
parseHex(i[1] + i[1]),
parseHex(i[2] + i[2]),
parseHex(i[3] + i[3]),
roundAlpha(parseHex(i[4] + i[4]) / 255)
];
}
else if (color in colors_1.default) {
return rgba(colors_1.default[color]);
}
else if (hslRegex.test(color) || hslaRegex.test(color)) {
const [h, s, l, a] = hsla(color);
return [...(0, convert_1.hsl2rgb)(h, s, l), a];
}
else if (hsvRegex.test(color) || hsvaRegex.test(color)) {
const [h, s, v, a] = hsva(color);
return [...(0, convert_1.hsv2rgb)(h, s, v), a];
}
throw new Error(`[seemly/rgba]: Invalid color value ${color}.`);
}
catch (e) {
throw e;
}
}
function normalizeAlpha(alphaValue) {
return alphaValue > 1 ? 1 : alphaValue < 0 ? 0 : alphaValue;
}
function stringifyRgb(r, g, b) {
return `rgb(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)})`;
}
function stringifyRgba(r, g, b, a) {
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, ${normalizeAlpha(a)})`;
}
function compositeChannel(v1, a1, v2, a2, a) {
return roundChannel((v1 * a1 * (1 - a2) + v2 * a2) / a);
}
function composite(background, overlay) {
if (!Array.isArray(background))
background = rgba(background);
if (!Array.isArray(overlay))
overlay = rgba(overlay);
const a1 = background[3];
const a2 = overlay[3];
const alpha = roundAlpha(a1 + a2 - a1 * a2);
return stringifyRgba(compositeChannel(background[0], a1, overlay[0], a2, alpha), compositeChannel(background[1], a1, overlay[1], a2, alpha), compositeChannel(background[2], a1, overlay[2], a2, alpha), alpha);
}
function changeColor(base, options) {
const [r, g, b, a = 1] = Array.isArray(base) ? base : rgba(base);
if (typeof options.alpha === 'number') {
return stringifyRgba(r, g, b, options.alpha);
}
return stringifyRgba(r, g, b, a);
}
function scaleColor(base, options) {
const [r, g, b, a = 1] = Array.isArray(base) ? base : rgba(base);
const { lightness = 1, alpha = 1 } = options;
return toRgbaString([r * lightness, g * lightness, b * lightness, a * alpha]);
}
function getAlpha(base) {
var _a;
const alpha = (_a = (Array.isArray(base) ? base : rgba(base))[3]) !== null && _a !== void 0 ? _a : 1;
return alpha;
}
function getAlphaString(base) {
return `${getAlpha(base)}`;
}
function roundAlpha(value) {
const v = Math.round(Number(value) * 100) / 100;
if (v > 1)
return 1;
if (v < 0)
return 0;
return v;
}
function roundDeg(value) {
const v = Math.round(Number(value));
if (v >= 360)
return 0;
if (v < 0)
return 0;
return v;
}
function roundChannel(value) {
const v = Math.round(Number(value));
if (v > 255)
return 255;
if (v < 0)
return 0;
return v;
}
function roundPercent(value) {
const v = Math.round(Number(value));
if (v > 100)
return 100;
if (v < 0)
return 0;
return v;
}
function toRgbString(base) {
const [r, g, b] = Array.isArray(base) ? base : rgba(base);
return stringifyRgb(r, g, b);
}
function toRgbaString(base) {
const [r, g, b] = base;
if (3 in base) {
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, ${roundAlpha(base[3])})`;
}
return `rgba(${roundChannel(r)}, ${roundChannel(g)}, ${roundChannel(b)}, 1)`;
}
function toHsvString(base) {
return `hsv(${roundDeg(base[0])}, ${roundPercent(base[1])}%, ${roundPercent(base[2])}%)`;
}
function toHsvaString(base) {
const [h, s, v] = base;
if (3 in base) {
return `hsva(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(v)}%, ${roundAlpha(base[3])})`;
}
return `hsva(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(v)}%, 1)`;
}
function toHslString(base) {
return `hsl(${roundDeg(base[0])}, ${roundPercent(base[1])}%, ${roundPercent(base[2])}%)`;
}
function toHslaString(base) {
const [h, s, l] = base;
if (3 in base) {
return `hsla(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(l)}%, ${roundAlpha(base[3])})`;
}
return `hsla(${roundDeg(h)}, ${roundPercent(s)}%, ${roundPercent(l)}%, 1)`;
}
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
function toHexaString(base) {
if (typeof base === 'string') {
let i;
if (i = hexRegex.exec(base)) {
return `${i[0]}FF`;
}
else if (i = hexaRegex.exec(base)) {
return i[0];
}
else if (i = sHexRegex.exec(base)) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}FF`;
}
else if (i = sHexaRegex.exec(base)) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}${i[4]}${i[4]}`;
}
throw new Error(`[seemly/toHexString]: Invalid hex value ${base}.`);
}
const hex = `#${base
.slice(0, 3)
.map((unit) => roundChannel(unit).toString(16).toUpperCase().padStart(2, '0'))
.join('')}`;
const a = base.length === 3
? 'FF'
: roundChannel(base[3] * 255)
.toString(16)
.padStart(2, '0')
.toUpperCase();
return hex + a;
}
/**
*
* @param base [255, 255, 255, 255], [255, 255, 255], any hex string
* @returns
*/
function toHexString(base) {
if (typeof base === 'string') {
let i;
if (i = hexRegex.exec(base)) {
return i[0];
}
else if (i = hexaRegex.exec(base)) {
return i[0].slice(0, 7);
}
else if (i = (sHexRegex.exec(base) || sHexaRegex.exec(base))) {
return `#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}`;
}
throw new Error(`[seemly/toHexString]: Invalid hex value ${base}.`);
}
return `#${base
.slice(0, 3)
.map((unit) => roundChannel(unit).toString(16).toUpperCase().padStart(2, '0'))
.join('')}`;
}
var convert_2 = require("./convert");
Object.defineProperty(exports, "hsl2hsv", { enumerable: true, get: function () { return convert_2.hsl2hsv; } });
Object.defineProperty(exports, "hsv2hsl", { enumerable: true, get: function () { return convert_2.hsv2hsl; } });
Object.defineProperty(exports, "hsv2rgb", { enumerable: true, get: function () { return convert_2.hsv2rgb; } });
Object.defineProperty(exports, "rgb2hsv", { enumerable: true, get: function () { return convert_2.rgb2hsv; } });
Object.defineProperty(exports, "rgb2hsl", { enumerable: true, get: function () { return convert_2.rgb2hsl; } });
Object.defineProperty(exports, "hsl2rgb", { enumerable: true, get: function () { return convert_2.hsl2rgb; } });

View File

@@ -0,0 +1,20 @@
export declare function depx(value: string | number): number;
declare function pxfy<T extends string | number | undefined | null>(value: T): T extends string | number ? string : undefined;
export { pxfy };
export type Position = 'top' | 'right' | 'bottom' | 'left';
export interface Margin {
top: string;
right: string;
bottom: string;
left: string;
}
declare function getMargin(value: string): Margin;
declare function getMargin(value: string, position: Position): string;
export interface Gap {
row: string;
col: string;
}
declare function getGap(value: string): Gap;
declare function getGap(value: string, orient: 'row' | 'col'): string;
export { getMargin, getMargin as getPadding, getGap };
export { parseResponsiveProp, parseResponsivePropValue } from './responsive';

View File

@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseResponsivePropValue = exports.parseResponsiveProp = void 0;
exports.depx = depx;
exports.pxfy = pxfy;
exports.getMargin = getMargin;
exports.getPadding = getMargin;
exports.getGap = getGap;
function depx(value) {
if (typeof value === 'string') {
if (value.endsWith('px')) {
return Number(value.slice(0, value.length - 2));
}
return Number(value);
}
return value;
}
function pxfy(value) {
if (value === undefined || value === null)
return undefined;
if (typeof value === 'number')
return `${value}px`;
if (value.endsWith('px'))
return value;
return `${value}px`;
}
function getMargin(value, position) {
const parts = value.trim().split(/\s+/g);
const margin = {
top: parts[0]
};
switch (parts.length) {
case 1:
margin.right = parts[0];
margin.bottom = parts[0];
margin.left = parts[0];
break;
case 2:
margin.right = parts[1];
margin.left = parts[1];
margin.bottom = parts[0];
break;
case 3:
margin.right = parts[1];
margin.bottom = parts[2];
margin.left = parts[1];
break;
case 4:
margin.right = parts[1];
margin.bottom = parts[2];
margin.left = parts[3];
break;
default:
throw new Error('[seemly/getMargin]:' + value + ' is not a valid value.');
}
if (position === undefined)
return margin;
return margin[position];
}
function getGap(value, orient) {
const [rowGap, colGap] = value.split(' ');
if (!orient)
return {
row: rowGap,
col: colGap || rowGap
};
return orient === 'row' ? rowGap : colGap;
}
var responsive_1 = require("./responsive");
Object.defineProperty(exports, "parseResponsiveProp", { enumerable: true, get: function () { return responsive_1.parseResponsiveProp; } });
Object.defineProperty(exports, "parseResponsivePropValue", { enumerable: true, get: function () { return responsive_1.parseResponsivePropValue; } });

View File

@@ -0,0 +1,11 @@
export declare function parseResponsiveProp(reponsiveProp: string | number): Record<string, string>;
declare function parseResponsivePropValue(reponsiveProp: undefined | null, activeKeyOrSize?: number | string | undefined): undefined;
declare function parseResponsivePropValue(// query by string
reponsiveProp: string | number, activeKey?: string | undefined): string | undefined;
declare function parseResponsivePropValue(// query by number
reponsiveProp: string | number, activeSize?: number | undefined): string | undefined;
declare function parseResponsivePropValue(// query by number
reponsiveProp: string | number, activeSize?: string[]): string | undefined;
declare function parseResponsivePropValue(// fallback
reponsiveProp: string | number | undefined | null, activeKeyOrSize?: number | string | string[] | undefined): string | undefined;
export { parseResponsivePropValue };

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseResponsiveProp = parseResponsiveProp;
exports.parseResponsivePropValue = parseResponsivePropValue;
function parseResponsiveProp(reponsiveProp) {
if (typeof reponsiveProp === "number") {
return {
'': reponsiveProp.toString()
};
}
const params = {};
reponsiveProp.split(/ +/).forEach((pairLiteral) => {
if (pairLiteral === '')
return;
const [prefix, value] = pairLiteral.split(':');
if (value === undefined) {
params[''] = prefix;
}
else {
params[prefix] = value;
}
});
return params;
}
function parseResponsivePropValue(reponsiveProp, activeKeyOrSize) {
var _a;
if (reponsiveProp === undefined || reponsiveProp === null)
return undefined;
const classObj = parseResponsiveProp(reponsiveProp);
if (activeKeyOrSize === undefined)
return classObj[''];
if (typeof activeKeyOrSize === 'string') {
return (_a = classObj[activeKeyOrSize]) !== null && _a !== void 0 ? _a : classObj[''];
}
else if (Array.isArray(activeKeyOrSize)) {
for (let i = activeKeyOrSize.length - 1; i >= 0; --i) {
const key = activeKeyOrSize[i];
if (key in classObj)
return classObj[key];
}
return classObj[''];
}
else {
// Here we suppose all the keys are number formatted
let activeValue = undefined;
let activeKey = -1;
Object.keys(classObj).forEach((key) => {
const keyAsNum = Number(key);
if (!Number.isNaN(keyAsNum) &&
activeKeyOrSize >= keyAsNum &&
keyAsNum >= activeKey) {
activeKey = keyAsNum;
activeValue = classObj[key];
}
});
return activeValue;
}
}

View File

@@ -0,0 +1 @@
export declare function getPreciseEventTarget(event: Event): EventTarget | null;

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPreciseEventTarget = getPreciseEventTarget;
function getPreciseEventTarget(event) {
return event.composedPath()[0] || null;
}

View File

@@ -0,0 +1 @@
export declare function getScrollParent(node: Node | null): HTMLElement | null;

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getScrollParent = getScrollParent;
function getParentNode(node) {
// document type
if (node.nodeType === 9) {
return null;
}
return node.parentNode;
}
function getScrollParent(node) {
if (node === null)
return null;
const parentNode = getParentNode(node);
if (parentNode === null) {
return null;
}
// Document
if (parentNode.nodeType === 9) {
return document.documentElement;
}
// Element
if (parentNode.nodeType === 1) {
// Firefox want us to check `-x` and `-y` variations as well
const { overflow, overflowX, overflowY } = getComputedStyle(parentNode);
if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
return parentNode;
}
}
return getScrollParent(parentNode);
}

View File

@@ -0,0 +1,3 @@
export declare function happensIn(e: {
target: EventTarget | null;
}, dataSetPropName: string): boolean;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.happensIn = happensIn;
function happensIn(e, dataSetPropName) {
let { target } = e;
while (target) {
if (target.dataset) {
if (target.dataset[dataSetPropName] !== undefined)
return true;
}
target = target.parentElement;
}
return false;
}

View File

@@ -0,0 +1,3 @@
type GetElement = () => HTMLElement;
declare function unwrapElement<T>(target: T | string | GetElement): T extends HTMLElement ? HTMLElement : HTMLElement | null;
export { unwrapElement };

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unwrapElement = unwrapElement;
function unwrapElement(target) {
if (typeof target === 'string')
return document.querySelector(target);
if (typeof target === 'function')
return target();
return target;
}

View File

@@ -0,0 +1,9 @@
export { beforeNextFrameOnce } from './animation/next-frame-once';
export { beforeNextFrame } from './animation/next-frame';
export { getScrollParent } from './dom/get-scroll-parent';
export { unwrapElement } from './dom/unwrap-element';
export { happensIn } from './dom/happens-in';
export { getPreciseEventTarget } from './dom/get-precise-event-target';
export { depx, pxfy, getPadding, getMargin, getGap, parseResponsiveProp, parseResponsivePropValue, Position, Margin } from './css';
export { changeColor, rgba, composite, scaleColor, getAlphaString, getAlpha, hsv2hsl, hsl2hsv, hsv2rgb, rgb2hsv, rgb2hsl, hsl2rgb, hsla, hsva, toHslString, toHslaString, toHsvString, toHsvaString, toRgbaString, toRgbString, toHexaString, toHexString, roundPercent, roundDeg, roundAlpha, roundChannel, ChangeColorOptions, ScaleColorOptions, RGB, RGBA, HSL, HSLA, HSV, HSVA } from './color';
export { createId, repeat, indexMap, sleep } from './misc/index';

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sleep = exports.indexMap = exports.repeat = exports.createId = exports.roundChannel = exports.roundAlpha = exports.roundDeg = exports.roundPercent = exports.toHexString = exports.toHexaString = exports.toRgbString = exports.toRgbaString = exports.toHsvaString = exports.toHsvString = exports.toHslaString = exports.toHslString = exports.hsva = exports.hsla = exports.hsl2rgb = exports.rgb2hsl = exports.rgb2hsv = exports.hsv2rgb = exports.hsl2hsv = exports.hsv2hsl = exports.getAlpha = exports.getAlphaString = exports.scaleColor = exports.composite = exports.rgba = exports.changeColor = exports.parseResponsivePropValue = exports.parseResponsiveProp = exports.getGap = exports.getMargin = exports.getPadding = exports.pxfy = exports.depx = exports.getPreciseEventTarget = exports.happensIn = exports.unwrapElement = exports.getScrollParent = exports.beforeNextFrame = exports.beforeNextFrameOnce = void 0;
var next_frame_once_1 = require("./animation/next-frame-once");
Object.defineProperty(exports, "beforeNextFrameOnce", { enumerable: true, get: function () { return next_frame_once_1.beforeNextFrameOnce; } });
var next_frame_1 = require("./animation/next-frame");
Object.defineProperty(exports, "beforeNextFrame", { enumerable: true, get: function () { return next_frame_1.beforeNextFrame; } });
var get_scroll_parent_1 = require("./dom/get-scroll-parent");
Object.defineProperty(exports, "getScrollParent", { enumerable: true, get: function () { return get_scroll_parent_1.getScrollParent; } });
var unwrap_element_1 = require("./dom/unwrap-element");
Object.defineProperty(exports, "unwrapElement", { enumerable: true, get: function () { return unwrap_element_1.unwrapElement; } });
var happens_in_1 = require("./dom/happens-in");
Object.defineProperty(exports, "happensIn", { enumerable: true, get: function () { return happens_in_1.happensIn; } });
var get_precise_event_target_1 = require("./dom/get-precise-event-target");
Object.defineProperty(exports, "getPreciseEventTarget", { enumerable: true, get: function () { return get_precise_event_target_1.getPreciseEventTarget; } });
var css_1 = require("./css");
Object.defineProperty(exports, "depx", { enumerable: true, get: function () { return css_1.depx; } });
Object.defineProperty(exports, "pxfy", { enumerable: true, get: function () { return css_1.pxfy; } });
Object.defineProperty(exports, "getPadding", { enumerable: true, get: function () { return css_1.getPadding; } });
Object.defineProperty(exports, "getMargin", { enumerable: true, get: function () { return css_1.getMargin; } });
Object.defineProperty(exports, "getGap", { enumerable: true, get: function () { return css_1.getGap; } });
Object.defineProperty(exports, "parseResponsiveProp", { enumerable: true, get: function () { return css_1.parseResponsiveProp; } });
Object.defineProperty(exports, "parseResponsivePropValue", { enumerable: true, get: function () { return css_1.parseResponsivePropValue; } });
var color_1 = require("./color");
Object.defineProperty(exports, "changeColor", { enumerable: true, get: function () { return color_1.changeColor; } });
Object.defineProperty(exports, "rgba", { enumerable: true, get: function () { return color_1.rgba; } });
Object.defineProperty(exports, "composite", { enumerable: true, get: function () { return color_1.composite; } });
Object.defineProperty(exports, "scaleColor", { enumerable: true, get: function () { return color_1.scaleColor; } });
Object.defineProperty(exports, "getAlphaString", { enumerable: true, get: function () { return color_1.getAlphaString; } });
Object.defineProperty(exports, "getAlpha", { enumerable: true, get: function () { return color_1.getAlpha; } });
Object.defineProperty(exports, "hsv2hsl", { enumerable: true, get: function () { return color_1.hsv2hsl; } });
Object.defineProperty(exports, "hsl2hsv", { enumerable: true, get: function () { return color_1.hsl2hsv; } });
Object.defineProperty(exports, "hsv2rgb", { enumerable: true, get: function () { return color_1.hsv2rgb; } });
Object.defineProperty(exports, "rgb2hsv", { enumerable: true, get: function () { return color_1.rgb2hsv; } });
Object.defineProperty(exports, "rgb2hsl", { enumerable: true, get: function () { return color_1.rgb2hsl; } });
Object.defineProperty(exports, "hsl2rgb", { enumerable: true, get: function () { return color_1.hsl2rgb; } });
Object.defineProperty(exports, "hsla", { enumerable: true, get: function () { return color_1.hsla; } });
Object.defineProperty(exports, "hsva", { enumerable: true, get: function () { return color_1.hsva; } });
Object.defineProperty(exports, "toHslString", { enumerable: true, get: function () { return color_1.toHslString; } });
Object.defineProperty(exports, "toHslaString", { enumerable: true, get: function () { return color_1.toHslaString; } });
Object.defineProperty(exports, "toHsvString", { enumerable: true, get: function () { return color_1.toHsvString; } });
Object.defineProperty(exports, "toHsvaString", { enumerable: true, get: function () { return color_1.toHsvaString; } });
Object.defineProperty(exports, "toRgbaString", { enumerable: true, get: function () { return color_1.toRgbaString; } });
Object.defineProperty(exports, "toRgbString", { enumerable: true, get: function () { return color_1.toRgbString; } });
Object.defineProperty(exports, "toHexaString", { enumerable: true, get: function () { return color_1.toHexaString; } });
Object.defineProperty(exports, "toHexString", { enumerable: true, get: function () { return color_1.toHexString; } });
Object.defineProperty(exports, "roundPercent", { enumerable: true, get: function () { return color_1.roundPercent; } });
Object.defineProperty(exports, "roundDeg", { enumerable: true, get: function () { return color_1.roundDeg; } });
Object.defineProperty(exports, "roundAlpha", { enumerable: true, get: function () { return color_1.roundAlpha; } });
Object.defineProperty(exports, "roundChannel", { enumerable: true, get: function () { return color_1.roundChannel; } });
var index_1 = require("./misc/index");
Object.defineProperty(exports, "createId", { enumerable: true, get: function () { return index_1.createId; } });
Object.defineProperty(exports, "repeat", { enumerable: true, get: function () { return index_1.repeat; } });
Object.defineProperty(exports, "indexMap", { enumerable: true, get: function () { return index_1.indexMap; } });
Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return index_1.sleep; } });

View File

@@ -0,0 +1,6 @@
export declare function createId(length?: number): string;
export declare function repeat<T>(count: number, v: T): T[];
declare function indexMap(count: number): number[];
declare function indexMap<T>(count: number, createValue: (index: number) => T): T[];
export { indexMap };
export declare function sleep(ms: number): Promise<void>;

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createId = createId;
exports.repeat = repeat;
exports.indexMap = indexMap;
exports.sleep = sleep;
function createId(length = 8) {
return Math.random()
.toString(16)
.slice(2, 2 + length);
}
function repeat(count, v) {
const ret = [];
for (let i = 0; i < count; ++i) {
ret.push(v);
}
return ret;
}
function indexMap(count, createValue) {
const ret = [];
if (!createValue) {
for (let i = 0; i < count; ++i) {
ret.push(i);
}
return ret;
}
for (let i = 0; i < count; ++i) {
ret.push(createValue(i));
}
return ret;
}
async function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}

View File

@@ -0,0 +1,2 @@
export declare function warnOnce(location: string, message: string): void;
export declare function warn(location: string, message: string): void;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.warnOnce = warnOnce;
exports.warn = warn;
const warnedMessages = new Set();
function warnOnce(location, message) {
const mergedMessage = `[seemly/${location}]: ${message}`;
if (warnedMessages.has(mergedMessage))
return;
warnedMessages.add(mergedMessage);
}
function warn(location, message) {
console.error(`[seemly/${location}]: ${message}`);
}

View File

@@ -0,0 +1,33 @@
{
"name": "seemly",
"version": "0.3.10",
"description": "Utils for user interface.",
"main": "lib/index.js",
"module": "es/index.js",
"sideEffects": false,
"files": [
"lib",
"es"
],
"author": "07akioni",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-typescript": "^7.12.7",
"babel-jest": "^28.0.2",
"jest": "^27.0.4",
"typescript": "^5.6.2",
"@types/jest": "^27.0.1"
},
"jest": {
"testEnvironment": "jsdom"
},
"scripts": {
"build": "pnpm run clean && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
"clean": "rm -rf es lib",
"test-dts": "tsc -p tsconfig.json",
"test": "pnpm run test-dts && jest src/**/*.spec.ts",
"release": "pnpm run build && pnpm publish"
}
}