Skip to content

Commit

Permalink
Merge pull request #49 from NarraLeaf/dev_nomen
Browse files Browse the repository at this point in the history
narraleaf-react-0.1.7
  • Loading branch information
helloyork authored Nov 16, 2024
2 parents 982a71f + 0403207 commit 8e66399
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 44 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# Changelog

## [0.1.6]
## [0.1.7]

### _Feature_

- Shorthand for `character.say`

### Added

- Tag function signature for `character.say`

### Fixed

- Position utils position incorrect

## [0.1.6] - 2024/11/13

### _Feature_

Expand Down
40 changes: 35 additions & 5 deletions src/game/nlcore/elements/character.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {LogicAction} from "../game";
import {ContentNode} from "@core/action/tree/actionTree";
import {Color} from "@core/types";
import {deepMerge, DeepPartial} from "@lib/util/data";
import {crossCombine, deepMerge, DeepPartial} from "@lib/util/data";
import {Actionable} from "@core/action/actionable";
import {Chained, Proxied} from "@core/action/chain";
import {Sentence, SentencePrompt, SentenceUserConfig} from "@core/elements/character/sentence";
import {Sentence, SentencePrompt, SentenceUserConfig, SingleWord} from "@core/elements/character/sentence";
import {CharacterAction} from "@core/action/actions/characterAction";

export type CharacterConfig = {} & Color;
Expand Down Expand Up @@ -54,20 +54,50 @@ export class Character extends Actionable<
* "Hello, ",
* new Word("world", {color: "#f00"}), // Some words can be colored
* ]));
* @example
* ```typescript
* character.say`Hello, ${Word.color("world", "#f00")}!`;
* ```
* @chainable
*/
public say(content: string, config?: SentenceUserConfig): Proxied<Character, Chained<LogicAction.Actions>>;
public say(content: Sentence): Proxied<Character, Chained<LogicAction.Actions>>;
public say(content: SentencePrompt, config?: SentenceUserConfig): Proxied<Character, Chained<LogicAction.Actions>>;
public say(content: SentencePrompt | Sentence, config?: SentenceUserConfig): Proxied<Character, Chained<LogicAction.Actions>> {
public say(texts: TemplateStringsArray, ...words: SingleWord[]): Proxied<Character, Chained<LogicAction.Actions>>;
public say(
contentOrText: SentencePrompt | Sentence | TemplateStringsArray,
configOrArg0?: SentenceUserConfig | Sentence | SingleWord,
...words: SingleWord[]
): Proxied<Character, Chained<LogicAction.Actions>> {
if (Array.isArray(contentOrText)
&& contentOrText.every(text => typeof text === "string")
&& [configOrArg0, ...words].length > 0
&& [configOrArg0, ...words].every(word => Sentence.isSingleWord(word))
) {
const plainTexts = contentOrText as string[];
const inserts = Sentence.format([configOrArg0, ...words] as SingleWord[]);

const sentence = new Sentence(crossCombine(plainTexts, inserts), {
character: this
});
const action = new CharacterAction<typeof CharacterAction.ActionTypes.say>(
this.chain(),
CharacterAction.ActionTypes.say,
new ContentNode<Sentence>().setContent(sentence)
);

return this.chain(action);
}
const config = (configOrArg0 || {}) as SentenceUserConfig;
const content = contentOrText as SentencePrompt | Sentence;
const sentence: Sentence =
Array.isArray(content) ?
new Sentence(content, {
...(config || {}),
...config,
character: this
}) :
(Sentence.isSentence(content) ? content : new Sentence(content, {
...(config || {}),
...config,
character: this
}))
.copy();
Expand Down
20 changes: 19 additions & 1 deletion src/game/nlcore/elements/character/sentence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {Character} from "@core/elements/character";
import {Word, WordConfig} from "@core/elements/character/word";
import {Color, Font} from "@core/types";
import type {ScriptCtx} from "@core/elements/script";
import {Pausing} from "@core/elements/character/pause";
import {Pause, Pausing} from "@core/elements/character/pause";

export type SentenceConfig = {
pause?: boolean | number;
Expand Down Expand Up @@ -85,6 +85,24 @@ export class Sentence {
return [Word.isWord(word) ? word : new Word<T | string | Pausing>(word, config)];
}


/**@internal */
static isSentencePrompt(input: any): input is SentencePrompt {
return Array.isArray(input) ?
input.every(Sentence.isSingleWord) :
Sentence.isSingleWord(input);
}

/**@internal */
static isSingleWord(obj: any): obj is SingleWord {
return (
typeof obj === "string"
|| Word.isWord(obj)
|| Pause.isPause(obj)
|| typeof obj === "function"
);
}

/**@internal */
readonly text: Word[];
/**@internal */
Expand Down
26 changes: 26 additions & 0 deletions src/game/nlcore/elements/character/word.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,27 @@ export class Word<T extends string | DynamicWord | Pausing = string | DynamicWor
return obj instanceof Word;
}

public static color(text: string | Word, color: color): Word {
if (Word.isWord(text)) {
return text.copy().inherit({color});
}
return new Word(text, {color});
}

public static bold(text: string | Word): Word {
if (Word.isWord(text)) {
return text.copy().inherit({bold: true});
}
return new Word(text, {bold: true});
}

public static italic(text: string | Word): Word {
if (Word.isWord(text)) {
return text.copy().inherit({italic: true});
}
return new Word(text, {italic: true});
}

/**@internal */
readonly text: T;
/**@internal */
Expand Down Expand Up @@ -58,4 +79,9 @@ export class Word<T extends string | DynamicWord | Pausing = string | DynamicWor
this.config.bold = this.config.bold || config.bold;
return this;
}

/**@internal */
copy(): Word<T> {
return new Word(this.text, this.config);
}
}
50 changes: 20 additions & 30 deletions src/game/player/lib/PlayerFrames.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import clsx from "clsx";
import {useRatio} from "@player/provider/ratio";
import Inspect from "@player/lib/Inspect";
import Isolated from "@player/lib/isolated";
import clsx from "clsx";

type ForwardSize = {
width?: React.CSSProperties["width"];
Expand All @@ -21,6 +21,7 @@ function BaseFrame(
children,
width,
height,
className,
}: Readonly<{
alignX?: "left" | "center" | "right",
alignY?: "top" | "center" | "bottom",
Expand All @@ -29,36 +30,25 @@ function BaseFrame(
) {
const {ratio} = useRatio();

const positions = {
top: alignY === "top" ? "0" : alignY === "center" ? "50%" : undefined,
left: alignX === "left" ? "0" : alignX === "center" ? "50%" : undefined,
right: alignX === "right" ? "0" : undefined,
bottom: alignY === "bottom" ? "0" : undefined,
};
const transform = {
x: alignX === "center" ? "-50%" : "0",
y: alignY === "center" ? "-50%" : "0",
};
const justifyContent = alignX === "left" ? "justify-start" : alignX === "right" ? "justify-end" : "justify-center";
const alignItems = alignY === "top" ? "items-start" : alignY === "bottom" ? "items-end" : "items-center";

return (
<>
<Inspect.Div
color={"gray"}
border={"dashed"}
className={clsx(
"absolute",
)}
style={{
...positions,
width,
height,
transform: `scale(${ratio.state.scale}) translate(${transform.x}, ${transform.y})`,
transformOrigin: `${alignX} ${alignY}`,
}}
>
{children}
</Inspect.Div>
</>
<Isolated className={clsx(
"flex absolute",
justifyContent,
alignItems,
className,
"pointer-events-none"
)} style={{
width,
height,
transform: `scale(${ratio.state.scale})`,
transformOrigin: `${alignX} ${alignY}`,
pointerEvents: "all"
}}>
{children}
</Isolated>
);
}

Expand Down
16 changes: 9 additions & 7 deletions src/game/player/lib/isolated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import clsx from "clsx";
import {useRatio} from "@player/provider/ratio";

export default function Isolated(
{children, className, props, ref}:
{children, className, props, style}:
Readonly<{
children: ReactNode,
className?: string,
props?: Record<any, any>,
ref?: React.MutableRefObject<HTMLDivElement | null>
children: ReactNode;
className?: string;
props?: Record<any, any>;
style?: React.CSSProperties;
}>
) {
const {ratio} = useRatio();
Expand All @@ -20,7 +20,7 @@ export default function Isolated(

return (
<div className={
clsx("inset-0 flex items-center justify-center", className)
clsx("inset-0", className)
} style={{
width: "100%",
height: "100%",
Expand All @@ -31,7 +31,9 @@ export default function Isolated(
...styles,
position: "relative",
overflow: "hidden",
}} {...(props || {})} ref={ref}>
...(props?.style || {}),
...(style || {}),
}} {...(props || {})}>
{children}
</div>
</div>
Expand Down
21 changes: 21 additions & 0 deletions src/util/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,3 +565,24 @@ export class Scheduler {
return this;
}
}

/**
* Cross combine two arrays
* @example
* ```typescript
* crossCombine([1, 2], ["a", "b"]); // [1, "a", 2, "b"]
* ```
*/
export function crossCombine<T, U>(a: T[], b: U[]): (T | U)[] {
const result: (T | U)[] = [];

for (let i = 0; i < Math.max(a.length, b.length); i++) {
if (i < a.length) {
result.push(a[i]);
}
if (i < b.length) {
result.push(b[i]);
}
}
return result;
}

0 comments on commit 8e66399

Please sign in to comment.