Skip to content

Commit

Permalink
Merge pull request #7 from NarraLeaf/dev_nomen
Browse files Browse the repository at this point in the history
narraleaf-react-0.0.1-beta.6
  • Loading branch information
helloyork authored Sep 18, 2024
2 parents c1a79ce + 5c7d594 commit 534e1d2
Show file tree
Hide file tree
Showing 30 changed files with 408 additions and 207 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![](./docs/nlr-logo-md.png)
![](./docs/nlr-logo-banner.png)

# NarraLeaf-React

Expand Down
Binary file added docs/nlr-logo-banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "narraleaf-react",
"version": "0.0.1-beta.5",
"version": "0.0.1-beta.6",
"description": "A React visual novel player framework",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand All @@ -12,7 +12,7 @@
"postbuild": "tsc-alias -p tsconfig.json",
"lint": "eslint \"./src/**/*.{ts,tsx,js,jsx}\"",
"lint:fix": "eslint --fix \"./src/**/*.{ts,tsx,js,jsx}\"",
"publish": "npm run lint && rimraf dist && webpack --config webpack.config.js && tsc-alias -p tsconfig.json",
"prepublish": "npm run lint && rimraf dist && webpack --config webpack.config.js && tsc-alias -p tsconfig.json",
"typedoc": "typedoc src/index.ts --out doc"
},
"devDependencies": {
Expand Down
19 changes: 5 additions & 14 deletions src/game/nlcore/elements/image.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from "react";
import type {TransformDefinitions} from "@core/elements/transform/type";
import {AnimationScope} from "framer-motion";
import {ContentNode} from "@core/action/tree/actionTree";
import {ImageAction} from "@core/action/actions";
import {Actionable} from "@core/action/actionable";
Expand Down Expand Up @@ -37,7 +36,7 @@ export type ImageEventTypes = {
"event:image.applyTransform": [Transform];
"event:image.mount": [];
"event:image.unmount": [];
"event:image.ready": [AnimationScope];
"event:image.ready": [React.MutableRefObject<HTMLImageElement | null>];
"event:image.elementLoaded": [];
"event:image.setTransition": [ITransition | null];
};
Expand Down Expand Up @@ -79,9 +78,11 @@ export class Image extends Actionable<ImageDataRaw> {
if (typeof arg0 === "string") {
this.name = arg0;
this.config = deepMerge<ImageConfig>(Image.defaultConfig, config || {});
if (this.config.position) this.config.position = PositionUtils.tryParsePosition(this.config.position);
} else {
this.name = "";
this.config = deepMerge<ImageConfig>(Image.defaultConfig, arg0);
if (this.config.position) this.config.position = PositionUtils.tryParsePosition(this.config.position);
}
this.state = deepMerge<ImageConfig>({}, this.config);
this.actions = [];
Expand Down Expand Up @@ -173,6 +174,7 @@ export class Image extends Actionable<ImageDataRaw> {
* @example
* ```ts
* // shake the image
*
* image.applyTransform(
* new Transform([
* {
Expand Down Expand Up @@ -287,17 +289,6 @@ export class Image extends Actionable<ImageDataRaw> {
});
}

toHTMLElementProps(): React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
return {
src: Utils.srcToString(this.config.src),
width: this.state.width,
height: this.state.height,
style: {
position: "absolute",
}
};
}

setScope(scope: React.RefObject<HTMLImageElement>): this {
this.ref = scope;
return this;
Expand All @@ -307,7 +298,7 @@ export class Image extends Actionable<ImageDataRaw> {
return this.ref;
}

copy(): Image {
public copy(): Image {
return new Image(this.name, this.config);
}

Expand Down
6 changes: 5 additions & 1 deletion src/game/nlcore/elements/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,14 @@ export class Scene extends Constructable<
const queue: Actions[] = [this.getActions()[0]];
const futureScene = new Set<Scene>();

if (Utils.backgroundToSrc(this.config.background)) {
this.srcManager.register(new Image({src: Utils.backgroundToSrc(this.config.background)}));
}

while (queue.length) {
const action = queue.shift()!;
if (action instanceof SceneAction) {
if (action.type === SceneActionTypes.jumpTo) {
if (action.type === SceneActionTypes.jumpTo) {
const jumpTo = action as SceneAction<typeof SceneActionTypes["jumpTo"]>;
const scene = jumpTo.contentNode.getContent()[0];

Expand Down
20 changes: 15 additions & 5 deletions src/game/nlcore/elements/text.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Game} from "../game";
import {ContentNode} from "@core/action/tree/actionTree";
import {Color} from "@core/types";
import {deepEqual, deepMerge, safeClone} from "@lib/util/data";
import {deepEqual, deepMerge, DeepPartial, safeClone} from "@lib/util/data";
import {CharacterAction} from "@core/action/actions";
import {Actionable} from "@core/action/actionable";

Expand Down Expand Up @@ -101,21 +101,31 @@ export class Word {
}
}

/* eslint-disable @typescript-eslint/no-empty-object-type */
export type CharacterConfig = {}
export enum CharacterMode {
// noinspection SpellCheckingInspection
"adv" = "adv",
"nvl" = "nvl"
}
export type CharacterConfig = {
mode: CharacterMode;
}
/* eslint-disable @typescript-eslint/no-empty-object-type */
export type CharacterStateData = {};

export class Character extends Actionable<
CharacterStateData
> {
static Modes = CharacterMode;
static defaultConfig: CharacterConfig = {
mode: CharacterMode.adv,
};
name: string | null;
config: CharacterConfig;

constructor(name: string | null, config: CharacterConfig = {}) {
constructor(name: string | null, config: DeepPartial<CharacterConfig> = {}) {
super(Actionable.IdPrefixes.Text);
this.name = name;
this.config = config;
this.config = deepMerge<CharacterConfig>({}, Character.defaultConfig, config);
}

/**
Expand Down
61 changes: 55 additions & 6 deletions src/game/nlcore/elements/transform/position.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {CSSProps} from "@core/elements/transition/type";

export enum CommonPositionType {
Left,
Center,
Right,
Left = "left",
Center = "center",
Right = "right",
}

export const CommonPositions = {
Expand Down Expand Up @@ -40,6 +40,10 @@ export type D2Position<X = any, Y = any> = {
yoffset: UnknownAble<number>;
}

export type RawPosition = CommonPositionType
| (Coord2DPosition & {xalign?: never; yalign?: never})
| (AlignPosition & {x: never; y: never});

export type Unknown = typeof PositionUtils.Unknown;
export type UnknownAble<T> = T | Unknown;

Expand Down Expand Up @@ -113,6 +117,51 @@ export class PositionUtils {
yoffset: PositionUtils.isUnknown(coord.yoffset) ? 0 : coord.yoffset,
};
}

static isRawCommonPositionType(arg: any): arg is CommonPositionType {
return Object.values(CommonPositionType).includes(arg);
}

static isRawCoord2DPosition(arg: any): arg is Coord2DPosition {
return typeof arg === "object" && (
"x" in arg || "y" in arg || "xoffset" in arg || "yoffset" in arg
);
}

static isRawAlignPosition(arg: any): arg is AlignPosition {
return typeof arg === "object" && (
"xalign" in arg || "yalign" in arg || "xoffset" in arg || "yoffset" in arg
);
}

static isRawPosition(arg: any): arg is IPosition {
return this.isRawCommonPositionType(arg) || this.isRawCoord2DPosition(arg) || this.isRawAlignPosition(arg);
}

static isPosition(arg: any): arg is IPosition {
return arg instanceof CommonPosition || arg instanceof Coord2D || arg instanceof Align;
}

static rawPositionToCoord2D(arg: any): Coord2D {
if (this.isRawCommonPositionType(arg)) {
return Coord2D.fromCommonPosition(new CommonPosition(arg));
} else if (this.isRawCoord2DPosition(arg)) {
return new Coord2D(arg);
} else if (this.isRawAlignPosition(arg)) {
return Coord2D.fromAlignPosition(arg);
}
throw new Error("Invalid position type");
}

static tryParsePosition(arg: any): IPosition {
if (this.isPosition(arg)) {
return arg;
}
if (this.isRawPosition(arg)) {
return this.rawPositionToCoord2D(arg);
}
throw new Error("Invalid position type");
}
}

export class CommonPosition implements IPosition {
Expand All @@ -124,11 +173,11 @@ export class CommonPosition implements IPosition {
* @example
* ```ts
* new CommonPosition(CommonPosition.Positions.Center);
* new CommonPosition("Center");
* new CommonPosition("center");
* ```
*/
constructor(position: CommonPositionType | keyof typeof CommonPositionType) {
this.position = typeof position === "number" ? position : CommonPositionType[position];
constructor(position: CommonPositionType) {
this.position = position;
}

static isCommonPositionType(arg: any): arg is CommonPosition {
Expand Down
31 changes: 20 additions & 11 deletions src/game/nlcore/elements/transform/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import type {AnimationPlaybackControls, DOMKeyframesDefinition, DynamicAnimation
import {deepMerge, DeepPartial, sleep, toHex} from "@lib/util/data";
import {GameState} from "@player/gameState";
import {TransformDefinitions} from "./type";
import {Align, CommonPosition, Coord2D, IPosition, PositionUtils} from "./position";
import {Align, CommonPosition, Coord2D, IPosition, PositionUtils, RawPosition} from "./position";
import {CSSProps} from "@core/elements/transition/type";
import {Utils} from "@core/common/Utils";
import { animate } from "framer-motion/dom";
import Sequence = TransformDefinitions.Sequence;
import SequenceProps = TransformDefinitions.SequenceProps;
import React from "react";

export type Transformers =
"position"
Expand Down Expand Up @@ -113,14 +115,17 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
return {backgroundImage: "url(" + url + ")"};
}

static mergePosition(a: IPosition | undefined, b: IPosition | undefined): Coord2D {
static mergePosition(a: RawPosition | undefined, b: RawPosition | undefined): Coord2D {
if (!a && !b) {
throw new Error("No position found.");
}
if (!a || !b) {
return PositionUtils.toCoord2D((a || b)!);
return PositionUtils.toCoord2D(PositionUtils.tryParsePosition(a || b)!);
}
return PositionUtils.mergePosition(a, b);
return PositionUtils.mergePosition(
PositionUtils.tryParsePosition(a),
PositionUtils.tryParsePosition(b)
);
}

static mergeState<T>(state: any, props: any): DeepPartial<T> {
Expand All @@ -139,11 +144,10 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
* return <div ref={scope} />
* ```
*/
public async animate<U extends Element = any>(
{scope, animate, overwrites}:
public async animate(
{scope, overwrites}:
{
scope: TransformDefinitions.FramerAnimationScope<U>,
animate: TransformDefinitions.FramerAnimate,
scope: React.MutableRefObject<HTMLImageElement | null>,
overwrites?: Partial<{ [K in Transformers]?: TransformHandler<any> }>
},
gameState: GameState,
Expand Down Expand Up @@ -171,6 +175,7 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
Object.assign(current["style"], initState);

state = Transform.mergeState(state, props);

const animation = animate(
current,
this.propToCSS(gameState, state, overwrites),
Expand Down Expand Up @@ -241,7 +246,12 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
"backgroundColor": (value: Background["background"]) => Transform.backgroundToCSS(value),
"backgroundOpacity": (value: number) => ({opacity: value}),
"opacity": (value: number) => ({opacity: value}),
"scale": () => ({}),
"scale": () => {
if (!("scale" in prop)) return {};
return {
width: `${(prop as any)["scale"] * 100}%`,
};
},
"rotation": () => ({}),
"display": () => ({}),
"src": () => ({}),
Expand Down Expand Up @@ -277,7 +287,7 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
return {
duration: duration ? (duration / 1000) : 0,
ease,
};
} satisfies DynamicAnimationOptions;
}

propToCSSTransform(state: GameState, prop: Record<string, any>): string {
Expand All @@ -287,7 +297,6 @@ export class Transform<T extends TransformDefinitions.Types = TransformDefinitio
const {invertY, invertX} = state.getLastScene()?.config || {};
const Transforms = [
`translate(${invertX ? "" : "-"}50%, ${invertY ? "" : "-"}50%)`,
(prop["scale"] !== undefined) && `scale(${prop["scale"]})`,
(prop["rotation"] !== undefined) && `rotate(${prop["rotation"]}deg)`,
];
return Transforms.filter(Boolean).join(" ");
Expand Down
3 changes: 2 additions & 1 deletion src/game/nlcore/elements/transition/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {EventDispatcher} from "@lib/util/data";
import {ElementProp, EventTypes, ITransition, TransitionEventTypes} from "./type";
import {animate, AnimationPlaybackControls, ValueAnimationTransition} from "framer-motion";
import {animate} from "framer-motion/dom";
import type {AnimationPlaybackControls, ValueAnimationTransition} from "framer-motion";


export class Base<T extends ElementProp> implements ITransition<T> {
Expand Down
2 changes: 1 addition & 1 deletion src/game/nlcore/elements/transition/fade.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ElementProp, ITransition, TransitionEventTypes} from "./type";
import {Base} from "./base";
import {animate} from "framer-motion";
import {animate} from "framer-motion/dom";
import {Scene} from "@core/elements/scene";
import {StaticImageData} from "@core/types";
import {Utils} from "@core/common/Utils";
Expand Down
2 changes: 1 addition & 1 deletion src/game/nlcore/elements/transition/fadeIn.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ElementProp, ITransition, TransitionEventTypes} from "@core/elements/transition/type";
import {Base} from "@core/elements/transition/base";
import {animate} from "framer-motion";
import {animate} from "framer-motion/dom";
import {Scene} from "@core/elements/scene";
import {StaticImageData} from "@core/types";
import {Utils} from "@core/common/Utils";
Expand Down
2 changes: 1 addition & 1 deletion src/game/nlcore/elements/transition/type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {EventDispatcher} from "@lib/util/data";
import React from "react";
import {DOMKeyframesDefinition} from "framer-motion";
import type {DOMKeyframesDefinition} from "framer-motion";

export type ElementProp<T extends Element = Element, U extends React.HTMLAttributes<T> = React.HTMLAttributes<T>> =
React.JSX.IntrinsicAttributes
Expand Down
2 changes: 1 addition & 1 deletion src/game/nlcore/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class Game {
},
img: {
slowLoadWarning: true,
slowLoadThreshold: 200,
slowLoadThreshold: 2000,
},
menu: {
use: DefaultElements.menu,
Expand Down
6 changes: 2 additions & 4 deletions src/game/nlcore/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {IPosition} from "@core/elements/transform/position";
import {IPosition, RawPosition} from "@core/elements/transform/position";

export type color = string | {
r: number;
Expand Down Expand Up @@ -43,11 +43,9 @@ export type Background = {

export type CommonImagePosition = "left" | "center" | "right";
export type CommonImage = {
height?: number;
width?: number;
scale?: number;
rotation?: number;
position?: IPosition;
position?: RawPosition | IPosition;
opacity?: number;
alt?: string;
}
Expand Down
Loading

0 comments on commit 534e1d2

Please sign in to comment.