完成世界书、骰子、apiconfig页面处理

This commit is contained in:
2026-04-30 01:35:10 +08:00
parent a3e3711b2b
commit ba9b925c32
4602 changed files with 785225 additions and 23 deletions

169
frontend/node_modules/khroma/src/channels/index.ts generated vendored Normal file
View File

@@ -0,0 +1,169 @@
/* IMPORT */
import _ from '~/utils';
import Type from '~/channels/type';
import {TYPE} from '~/constants';
import type {RGBA, HSLA, CHANNELS} from '~/types';
/* MAIN */
class Channels {
/* VARIABLES */
color?: string;
changed: boolean;
data: CHANNELS; //TSC: It should really be "Partial<CHANNELS>", but TS gets excessively noisy
type: Type;
/* CONSTRUCTOR */
constructor ( data: RGBA | HSLA | CHANNELS, color?: string ) {
this.color = color;
this.changed = false;
this.data = data as CHANNELS; //TSC
this.type = new Type ();
}
/* API */
set ( data: RGBA | HSLA | CHANNELS, color?: string ): this {
this.color = color;
this.changed = false;
this.data = data as CHANNELS; //TSC
this.type.type = TYPE.ALL;
return this;
}
/* HELPERS */
_ensureHSL (): void {
const data = this.data;
const {h, s, l} = data;
if ( h === undefined ) data.h = _.channel.rgb2hsl ( data, 'h' );
if ( s === undefined ) data.s = _.channel.rgb2hsl ( data, 's' );
if ( l === undefined ) data.l = _.channel.rgb2hsl ( data, 'l' );
}
_ensureRGB (): void {
const data = this.data;
const {r, g, b} = data;
if ( r === undefined ) data.r = _.channel.hsl2rgb ( data, 'r' );
if ( g === undefined ) data.g = _.channel.hsl2rgb ( data, 'g' );
if ( b === undefined ) data.b = _.channel.hsl2rgb ( data, 'b' );
}
/* GETTERS */
get r (): number {
const data = this.data;
const r = data.r;
if ( !this.type.is ( TYPE.HSL ) && r !== undefined ) return r;
this._ensureHSL ();
return _.channel.hsl2rgb ( data, 'r' );
}
get g (): number {
const data = this.data;
const g = data.g;
if ( !this.type.is ( TYPE.HSL ) && g !== undefined ) return g;
this._ensureHSL ();
return _.channel.hsl2rgb ( data, 'g' );
}
get b (): number {
const data = this.data;
const b = data.b;
if ( !this.type.is ( TYPE.HSL ) && b !== undefined ) return b;
this._ensureHSL ();
return _.channel.hsl2rgb ( data, 'b' );
}
get h (): number {
const data = this.data;
const h = data.h;
if ( !this.type.is ( TYPE.RGB ) && h !== undefined ) return h;
this._ensureRGB ();
return _.channel.rgb2hsl ( data, 'h' );
}
get s (): number {
const data = this.data;
const s = data.s;
if ( !this.type.is ( TYPE.RGB ) && s !== undefined ) return s;
this._ensureRGB ();
return _.channel.rgb2hsl ( data, 's' );
}
get l (): number {
const data = this.data;
const l = data.l;
if ( !this.type.is ( TYPE.RGB ) && l !== undefined ) return l;
this._ensureRGB ();
return _.channel.rgb2hsl ( data, 'l' );
}
get a (): number {
return this.data.a;
}
/* SETTERS */
set r ( r: number ) {
this.type.set ( TYPE.RGB );
this.changed = true;
this.data.r = r;
}
set g ( g: number ) {
this.type.set ( TYPE.RGB );
this.changed = true;
this.data.g = g;
}
set b ( b: number ) {
this.type.set ( TYPE.RGB );
this.changed = true;
this.data.b = b;
}
set h ( h: number ) {
this.type.set ( TYPE.HSL );
this.changed = true;
this.data.h = h;
}
set s ( s: number ) {
this.type.set ( TYPE.HSL );
this.changed = true;
this.data.s = s;
}
set l ( l: number ) {
this.type.set ( TYPE.HSL );
this.changed = true;
this.data.l = l;
}
set a ( a: number ) {
this.changed = true;
this.data.a = a;
}
}
/* EXPORT */
export default Channels;

46
frontend/node_modules/khroma/src/channels/type.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
/* IMPORT */
import {TYPE} from '~/constants';
/* MAIN */
class Type {
/* VARIABLES */
type: number = TYPE.ALL;
/* API */
get (): number {
return this.type;
}
set ( type: number ): void {
if ( this.type && this.type !== type ) throw new Error ( 'Cannot change both RGB and HSL channels at the same time' );
this.type = type;
}
reset (): void {
this.type = TYPE.ALL;
}
is ( type: number ): boolean {
return this.type === type;
}
}
/* EXPORT */
export default Type;

82
frontend/node_modules/khroma/src/color/hsl.ts generated vendored Normal file
View File

@@ -0,0 +1,82 @@
/* IMPORT */
import _ from '~/utils';
import ChannelsReusable from '~/channels/reusable';
import type {Channels} from '~/types';
/* MAIN */
const HSL = {
/* VARIABLES */
re: /^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,
hueRe: /^(.+?)(deg|grad|rad|turn)$/i,
/* HELPERS */
_hue2deg: ( hue: string ): number => {
const match = hue.match ( HSL.hueRe );
if ( match ) {
const [, number, unit] = match;
switch ( unit ) {
case 'grad': return _.channel.clamp.h ( parseFloat ( number ) * .9 );
case 'rad': return _.channel.clamp.h ( parseFloat ( number ) * 180 / Math.PI );
case 'turn': return _.channel.clamp.h ( parseFloat ( number ) * 360 );
}
}
return _.channel.clamp.h ( parseFloat ( hue ) );
},
/* API */
parse: ( color: string ): Channels | void => {
const charCode = color.charCodeAt ( 0 );
if ( charCode !== 104 && charCode !== 72 ) return; // 'h'/'H'
const match = color.match ( HSL.re );
if ( !match ) return;
const [, h, s, l, a, isAlphaPercentage] = match;
return ChannelsReusable.set ({
h: HSL._hue2deg ( h ),
s: _.channel.clamp.s ( parseFloat ( s ) ),
l: _.channel.clamp.l ( parseFloat ( l ) ),
a: a ? _.channel.clamp.a ( isAlphaPercentage ? parseFloat ( a ) / 100 : parseFloat ( a ) ) : 1
}, color );
},
stringify: ( channels: Channels ): string => {
const {h, s, l, a} = channels;
if ( a < 1 ) { // HSLA
return `hsla(${_.lang.round ( h )}, ${_.lang.round ( s )}%, ${_.lang.round ( l )}%, ${a})`;
} else { // HSL
return `hsl(${_.lang.round ( h )}, ${_.lang.round ( s )}%, ${_.lang.round ( l )}%)`;
}
}
};
/* EXPORT */
export default HSL;

67
frontend/node_modules/khroma/src/color/index.ts generated vendored Normal file
View File

@@ -0,0 +1,67 @@
/* IMPORT */
import _ from '~/utils';
import Hex from '~/color/hex';
import HSL from '~/color/hsl';
import Keyword from '~/color/keyword';
import RGB from '~/color/rgb';
import {TYPE} from '~/constants';
import type {Channels} from '~/types';
/* MAIN */
const Color = {
/* VARIABLES */
format: {
keyword: Keyword,
hex: Hex,
rgb: RGB,
rgba: RGB,
hsl: HSL,
hsla: HSL
},
/* API */
parse: ( color: string | Channels ): Channels => {
if ( typeof color !== 'string' ) return color;
const channels = Hex.parse ( color ) || RGB.parse ( color ) || HSL.parse ( color ) || Keyword.parse ( color ); // Color providers ordered with performance in mind
if ( channels ) return channels;
throw new Error ( `Unsupported color format: "${color}"` );
},
stringify: ( channels: Channels ): string => {
// SASS returns a keyword if possible, but we avoid doing that as it's slower and doesn't really add any value
if ( !channels.changed && channels.color ) return channels.color;
if ( channels.type.is ( TYPE.HSL ) || channels.data.r === undefined ) {
return HSL.stringify ( channels );
} else if ( channels.a < 1 || !Number.isInteger ( channels.r ) || !Number.isInteger ( channels.g ) || !Number.isInteger ( channels.b ) ) {
return RGB.stringify ( channels );
} else {
return Hex.stringify ( channels );
}
}
};
/* EXPORT */
export default Color;

View File

@@ -0,0 +1,24 @@
/* IMPORT */
import _ from '~/utils';
import Color from '~/color';
import type {CHANNEL, Channels} from '~/types';
/* MAIN */
const adjustChannel = ( color: string | Channels, channel: CHANNEL, amount: number ): string => {
const channels = Color.parse ( color );
const amountCurrent = channels[channel];
const amountNext = _.channel.clamp[channel]( amountCurrent + amount );
if ( amountCurrent !== amountNext ) channels[channel] = amountNext;
return Color.stringify ( channels );
};
/* EXPORT */
export default adjustChannel;

17
frontend/node_modules/khroma/src/methods/blue.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import channel from '~/methods/channel';
import type {Channels} from '~/types';
/* MAIN */
const blue = ( color: string | Channels ): number => {
return channel ( color, 'b' );
};
/* EXPORT */
export default blue;

17
frontend/node_modules/khroma/src/methods/desaturate.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import adjustChannel from '~/methods/adjust_channel';
import type {Channels} from '~/types';
/* MAIN */
const desaturate = ( color: string | Channels, amount: number ): string => {
return adjustChannel ( color, 's', -amount );
};
/* EXPORT */
export default desaturate;

17
frontend/node_modules/khroma/src/methods/grayscale.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import change from '~/methods/change';
import type {Channels} from '~/types';
/* MAIN */
const grayscale = ( color: string | Channels ): string => {
return change ( color, { s: 0 } );
};
/* EXPORT */
export default grayscale;

17
frontend/node_modules/khroma/src/methods/green.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import channel from '~/methods/channel';
import type {Channels} from '~/types';
/* MAIN */
const green = ( color: string | Channels ): number => {
return channel ( color, 'g' );
};
/* EXPORT */
export default green;

25
frontend/node_modules/khroma/src/methods/hsla.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/* IMPORT */
import _ from '~/utils';
import ChannelsReusable from '~/channels/reusable';
import Color from '~/color';
/* MAIN */
const hsla = ( h: number, s: number, l: number, a: number = 1 ): string => {
const channels = ChannelsReusable.set ({
h: _.channel.clamp.h ( h ),
s: _.channel.clamp.s ( s ),
l: _.channel.clamp.l ( l ),
a: _.channel.clamp.a ( a )
});
return Color.stringify ( channels );
};
/* EXPORT */
export default hsla;

17
frontend/node_modules/khroma/src/methods/hue.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import channel from '~/methods/channel';
import type {Channels} from '~/types';
/* MAIN */
const hue = ( color: string | Channels ): number => {
return channel ( color, 'h' );
};
/* EXPORT */
export default hue;

17
frontend/node_modules/khroma/src/methods/is_dark.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import isLight from '~/methods/is_light';
import type {Channels} from '~/types';
/* MAIN */
const isDark = ( color: string | Channels ): boolean => {
return !isLight ( color );
};
/* EXPORT */
export default isDark;

17
frontend/node_modules/khroma/src/methods/lightness.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import channel from '~/methods/channel';
import type {Channels} from '~/types';
/* MAIN */
const lightness = ( color: string | Channels ): number => {
return channel ( color, 'l' );
};
/* EXPORT */
export default lightness;

17
frontend/node_modules/khroma/src/methods/opacify.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import adjustChannel from '~/methods/adjust_channel';
import type {Channels} from '~/types';
/* MAIN */
const opacify = ( color: string | Channels, amount: number ): string => {
return adjustChannel ( color, 'a', amount );
};
/* EXPORT */
export default opacify;

36
frontend/node_modules/khroma/src/methods/rgba.ts generated vendored Normal file
View File

@@ -0,0 +1,36 @@
/* IMPORT */
import _ from '~/utils';
import ChannelsReusable from '~/channels/reusable';
import Color from '~/color';
import change from '~/methods/change';
import type {Channels} from '~/types';
/* TYPES */
type IRgba = {
( color: string | Channels, opacity: number ): string,
( r: number, g: number, b: number, a?: number ): string
};
/* MAIN */
const rgba: IRgba = ( r: string | Channels | number, g: number, b: number = 0, a: number = 1 ): string => { //TSC: `b` shouldn't have a default value
if ( typeof r !== 'number' ) return change ( r, { a: g } );
const channels = ChannelsReusable.set ({
r: _.channel.clamp.r ( r ),
g: _.channel.clamp.g ( g ),
b: _.channel.clamp.b ( b ),
a: _.channel.clamp.a ( a )
});
return Color.stringify ( channels );
};
/* EXPORT */
export default rgba;

17
frontend/node_modules/khroma/src/methods/saturation.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/* IMPORT */
import channel from '~/methods/channel';
import type {Channels} from '~/types';
/* MAIN */
const saturation = ( color: string | Channels ): number => {
return channel ( color, 's' );
};
/* EXPORT */
export default saturation;

29
frontend/node_modules/khroma/src/methods/scale.ts generated vendored Normal file
View File

@@ -0,0 +1,29 @@
/* IMPORT */
import _ from '~/utils';
import Color from '~/color';
import adjust from '~/methods/adjust';
import type {CHANNELS, Channels} from '~/types';
/* MAIN */
const scale = ( color: string | Channels, channels: Partial<CHANNELS> ): string => {
const ch = Color.parse ( color );
const adjustments: Partial<CHANNELS> = {};
const delta = ( amount: number, weight: number, max: number ) => weight > 0 ? ( max - amount ) * weight / 100 : amount * weight / 100;
for ( const c in channels ) {
adjustments[c] = delta ( ch[c], channels[c], _.channel.max[c] );
}
return adjust ( color, adjustments );
};
/* EXPORT */
export default scale;

View File

@@ -0,0 +1,17 @@
/* IMPORT */
import adjustChannel from '~/methods/adjust_channel';
import type {Channels} from '~/types';
/* MAIN */
const transparentize = ( color: string | Channels, amount: number ): string => {
return adjustChannel ( color, 'a', -amount );
};
/* EXPORT */
export default transparentize;

20
frontend/node_modules/khroma/src/utils/unit.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/* MAIN */
const Unit = {
/* API */
dec2hex: ( dec: number ): string => {
const hex = Math.round ( dec ).toString ( 16 );
return hex.length > 1 ? hex : `0${hex}`;
}
};
/* EXPORT */
export default Unit;