@luna-editor/engine 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Player.d.ts +1 -1
- package/dist/Player.js +504 -77
- package/dist/api/conversationBranch.d.ts +4 -0
- package/dist/api/conversationBranch.js +83 -0
- package/dist/components/BackgroundLayer.d.ts +19 -0
- package/dist/components/BackgroundLayer.js +218 -0
- package/dist/components/ClickWaitIndicator.d.ts +10 -0
- package/dist/components/ClickWaitIndicator.js +31 -0
- package/dist/components/ConversationBranchBox.d.ts +2 -0
- package/dist/components/ConversationBranchBox.js +29 -0
- package/dist/components/DialogueBox.js +16 -1
- package/dist/components/FontSettingsPanel.d.ts +10 -0
- package/dist/components/FontSettingsPanel.js +30 -0
- package/dist/components/FullscreenTextBox.d.ts +6 -0
- package/dist/components/FullscreenTextBox.js +70 -0
- package/dist/components/GameScreen.d.ts +1 -0
- package/dist/components/GameScreen.js +363 -81
- package/dist/components/PluginComponentProvider.d.ts +2 -2
- package/dist/components/PluginComponentProvider.js +3 -3
- package/dist/components/TimeWaitIndicator.d.ts +15 -0
- package/dist/components/TimeWaitIndicator.js +17 -0
- package/dist/contexts/AudioContext.d.ts +1 -0
- package/dist/contexts/AudioContext.js +1 -0
- package/dist/contexts/DataContext.js +69 -11
- package/dist/hooks/useBacklog.js +3 -0
- package/dist/hooks/useConversationBranch.d.ts +16 -0
- package/dist/hooks/useConversationBranch.js +125 -0
- package/dist/hooks/useFontLoader.d.ts +23 -0
- package/dist/hooks/useFontLoader.js +153 -0
- package/dist/hooks/useFullscreenText.d.ts +17 -0
- package/dist/hooks/useFullscreenText.js +120 -0
- package/dist/hooks/usePlayerLogic.d.ts +10 -3
- package/dist/hooks/usePlayerLogic.js +115 -18
- package/dist/hooks/usePluginEvents.d.ts +4 -1
- package/dist/hooks/usePluginEvents.js +16 -11
- package/dist/hooks/usePreloadImages.js +27 -7
- package/dist/hooks/useSoundPlayer.d.ts +15 -0
- package/dist/hooks/useSoundPlayer.js +209 -0
- package/dist/hooks/useTypewriter.d.ts +6 -2
- package/dist/hooks/useTypewriter.js +42 -6
- package/dist/hooks/useVoice.js +4 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/plugin/PluginManager.d.ts +66 -2
- package/dist/plugin/PluginManager.js +349 -79
- package/dist/sdk.d.ts +178 -21
- package/dist/sdk.js +27 -2
- package/dist/types.d.ts +288 -4
- package/dist/utils/branchBlockConverter.d.ts +2 -0
- package/dist/utils/branchBlockConverter.js +21 -0
- package/dist/utils/branchNavigator.d.ts +14 -0
- package/dist/utils/branchNavigator.js +55 -0
- package/dist/utils/facePositionCalculator.js +0 -1
- package/dist/utils/variableManager.d.ts +18 -0
- package/dist/utils/variableManager.js +159 -0
- package/package.json +1 -1
- package/dist/components/ConversationLogUI.d.ts +0 -2
- package/dist/components/ConversationLogUI.js +0 -115
- package/dist/hooks/useConversationLog.d.ts +0 -14
- package/dist/hooks/useConversationLog.js +0 -82
- package/dist/hooks/useUIVisibility.d.ts +0 -9
- package/dist/hooks/useUIVisibility.js +0 -19
- package/dist/plugin/luna-react.d.ts +0 -41
- package/dist/plugin/luna-react.js +0 -99
package/dist/sdk.d.ts
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { BackgroundData, BacklogEntry, BranchChoiceHistory, Character, ConversationBranchState, DisplayedCharacter, EntityState, ScenarioBlock, ScenarioBlockType, WorkFont } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* ブロックオプションの定義
|
|
5
|
+
* プラグインがシナリオブロックに追加できるカスタムオプションを定義
|
|
6
|
+
*/
|
|
7
|
+
export interface BlockOptionDefinition {
|
|
8
|
+
/** オプションのキー(プラグイン固有のプレフィックス推奨: "myplugin_option_name") */
|
|
9
|
+
key: string;
|
|
10
|
+
/** 表示名 */
|
|
11
|
+
name: string;
|
|
12
|
+
/** 対象のブロックタイプ(nullまたは未指定で全タイプ対象) */
|
|
13
|
+
targetBlockTypes?: ScenarioBlockType[] | null;
|
|
14
|
+
/** オプションの入力タイプ */
|
|
15
|
+
type: "select" | "text" | "number" | "boolean";
|
|
16
|
+
/** select型の場合の選択肢 */
|
|
17
|
+
options?: BlockOptionChoice[];
|
|
18
|
+
/** select以外の場合のデフォルト値 */
|
|
19
|
+
default?: string | number | boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* select型オプションの選択肢
|
|
23
|
+
*/
|
|
24
|
+
export interface BlockOptionChoice {
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
27
|
+
/** デフォルト選択かどうか */
|
|
28
|
+
isDefault?: boolean;
|
|
29
|
+
}
|
|
3
30
|
export interface LunaPlugin {
|
|
4
31
|
name: string;
|
|
5
32
|
version: string;
|
|
6
33
|
description: string;
|
|
34
|
+
/** プラグインが定義するブロックオプション */
|
|
35
|
+
blockOptions?: BlockOptionDefinition[];
|
|
7
36
|
/** プラグインインストール時の処理(オプション) */
|
|
8
37
|
onInstall?(api: PluginInstallAPI): Promise<void>;
|
|
9
38
|
/** プラグインアンインストール時の処理(オプション) */
|
|
@@ -24,12 +53,12 @@ export interface ScenarioPlaybackData {
|
|
|
24
53
|
scenarioName: string;
|
|
25
54
|
/** 現在のブロック */
|
|
26
55
|
currentBlock: ScenarioBlock | null;
|
|
27
|
-
/**
|
|
28
|
-
displayText?: string;
|
|
56
|
+
/** 表示中のテキスト(改行は自動的に<br />に変換されます) */
|
|
57
|
+
displayText?: string | React.ReactNode;
|
|
29
58
|
/** テキストアニメーション中かどうか */
|
|
30
59
|
isTyping?: boolean;
|
|
31
60
|
/** 表示中のキャラクター */
|
|
32
|
-
displayedCharacters?:
|
|
61
|
+
displayedCharacters?: DisplayedCharacter[];
|
|
33
62
|
}
|
|
34
63
|
/**
|
|
35
64
|
* バックログデータ
|
|
@@ -73,6 +102,17 @@ export interface PluginAssetsData {
|
|
|
73
102
|
*/
|
|
74
103
|
getAssetUrl: (pluginName: string, filename: string) => string;
|
|
75
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* フォントデータ
|
|
107
|
+
*/
|
|
108
|
+
export interface FontsData {
|
|
109
|
+
/** 利用可能なフォント一覧 */
|
|
110
|
+
fonts: WorkFont[];
|
|
111
|
+
/** 選択されているフォントファミリー */
|
|
112
|
+
selectedFontFamily: string | undefined;
|
|
113
|
+
/** フォントが読み込み完了しているかどうか */
|
|
114
|
+
isLoaded: boolean;
|
|
115
|
+
}
|
|
76
116
|
/**
|
|
77
117
|
* 全データコンテキスト
|
|
78
118
|
*/
|
|
@@ -85,6 +125,16 @@ export interface DataContext {
|
|
|
85
125
|
settings: PlayerSettingsData;
|
|
86
126
|
/** プラグインアセット */
|
|
87
127
|
pluginAssets: PluginAssetsData;
|
|
128
|
+
/** 会話分岐データ */
|
|
129
|
+
branchData?: ConversationBranchState;
|
|
130
|
+
/** 分岐履歴 */
|
|
131
|
+
branchHistory?: BranchChoiceHistory[];
|
|
132
|
+
/** 現在の背景データ(単一、後方互換性用) */
|
|
133
|
+
background?: BackgroundData | null;
|
|
134
|
+
/** 現在の背景データ(複数、背景グループ対応) */
|
|
135
|
+
backgrounds?: BackgroundData[];
|
|
136
|
+
/** フォント設定 */
|
|
137
|
+
fonts?: FontsData;
|
|
88
138
|
}
|
|
89
139
|
/**
|
|
90
140
|
* データ購読コールバック
|
|
@@ -173,6 +223,63 @@ export interface DataAPI {
|
|
|
173
223
|
* @param settings - 更新する設定値(部分更新可能)
|
|
174
224
|
*/
|
|
175
225
|
updateSettings(settings: Partial<PlayerSettingsData>): void;
|
|
226
|
+
/**
|
|
227
|
+
* BGM音量を設定
|
|
228
|
+
* @param volume - 音量(0-1の範囲)
|
|
229
|
+
*/
|
|
230
|
+
setBgmVolume(volume: number): void;
|
|
231
|
+
/**
|
|
232
|
+
* SE音量を設定
|
|
233
|
+
* @param volume - 音量(0-1の範囲)
|
|
234
|
+
*/
|
|
235
|
+
setSeVolume(volume: number): void;
|
|
236
|
+
/**
|
|
237
|
+
* ボイス音量を設定
|
|
238
|
+
* @param volume - 音量(0-1の範囲)
|
|
239
|
+
*/
|
|
240
|
+
setVoiceVolume(volume: number): void;
|
|
241
|
+
/**
|
|
242
|
+
* 全カテゴリの音量を一括設定
|
|
243
|
+
* @param volumes - カテゴリ別音量設定
|
|
244
|
+
*/
|
|
245
|
+
setVolumes(volumes: {
|
|
246
|
+
bgm?: number;
|
|
247
|
+
se?: number;
|
|
248
|
+
voice?: number;
|
|
249
|
+
}): void;
|
|
250
|
+
/**
|
|
251
|
+
* 現在のブロックのオプション値を型安全に取得
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* // プラグイン側で型を定義
|
|
256
|
+
* type MyBlockOptions = {
|
|
257
|
+
* ultemist_bubble_style: "normal" | "monologue" | "star";
|
|
258
|
+
* ultemist_effect_type: "none" | "shake" | "fade";
|
|
259
|
+
* };
|
|
260
|
+
*
|
|
261
|
+
* // コンポーネントで使用
|
|
262
|
+
* const bubbleStyle = dataAPI.getBlockOption<MyBlockOptions, "ultemist_bubble_style">("ultemist_bubble_style");
|
|
263
|
+
* // 型: "normal" | "monologue" | "star" | undefined
|
|
264
|
+
*
|
|
265
|
+
* // または簡易版(キーのみ指定)
|
|
266
|
+
* const bubbleStyle = dataAPI.getBlockOption<MyBlockOptions>("ultemist_bubble_style");
|
|
267
|
+
* ```
|
|
268
|
+
*
|
|
269
|
+
* @param key - オプションのキー
|
|
270
|
+
* @returns オプションの値、または未設定の場合undefined
|
|
271
|
+
*/
|
|
272
|
+
getBlockOption<T extends Record<string, unknown>, K extends keyof T = keyof T>(key: K): T[K] | undefined;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* ブロックオプション登録API
|
|
276
|
+
*/
|
|
277
|
+
export interface BlockOptionsAPI {
|
|
278
|
+
/**
|
|
279
|
+
* ブロックオプションを登録
|
|
280
|
+
* @param definition - ブロックオプションの定義
|
|
281
|
+
*/
|
|
282
|
+
register(definition: BlockOptionDefinition): void;
|
|
176
283
|
}
|
|
177
284
|
export interface PluginAPI {
|
|
178
285
|
style: StyleAPI;
|
|
@@ -184,9 +291,18 @@ export interface PluginAPI {
|
|
|
184
291
|
components: ComponentAPI;
|
|
185
292
|
data: DataAPI;
|
|
186
293
|
ui: UIAPI;
|
|
294
|
+
blockOptions: BlockOptionsAPI;
|
|
187
295
|
React: typeof React;
|
|
188
296
|
setNextCharacterSpeakHandler(callback: (context: CharacterSpeakContext) => void): void;
|
|
189
297
|
getConfig?(): unknown;
|
|
298
|
+
selectChoice?(choiceId: string): void;
|
|
299
|
+
getBranchState?(): ConversationBranchState | null;
|
|
300
|
+
/**
|
|
301
|
+
* ビルトインのクリック音を上書き
|
|
302
|
+
* プラグインが独自のクリック音を再生する場合に呼び出す
|
|
303
|
+
* onBlockChangeフック内で呼び出すことで、そのブロック遷移でのビルトインクリック音を抑制する
|
|
304
|
+
*/
|
|
305
|
+
overrideClickSound?(): void;
|
|
190
306
|
}
|
|
191
307
|
export interface StyleAPI {
|
|
192
308
|
elements: {
|
|
@@ -196,6 +312,8 @@ export interface StyleAPI {
|
|
|
196
312
|
gameScreen: StyleElement;
|
|
197
313
|
characterSprite: StyleElement;
|
|
198
314
|
background: StyleElement;
|
|
315
|
+
fullscreenTextOverlay: StyleElement;
|
|
316
|
+
fullscreenTextContainer: StyleElement;
|
|
199
317
|
};
|
|
200
318
|
injectCSS(css: string): void;
|
|
201
319
|
enableTailwind(): void;
|
|
@@ -230,7 +348,7 @@ export interface AttributeDefinition {
|
|
|
230
348
|
name: string;
|
|
231
349
|
type: "text" | "textarea" | "number" | "select" | "entity";
|
|
232
350
|
label: string;
|
|
233
|
-
default?:
|
|
351
|
+
default?: string | number | boolean;
|
|
234
352
|
required?: boolean;
|
|
235
353
|
placeholder?: string;
|
|
236
354
|
min?: number;
|
|
@@ -277,7 +395,7 @@ export interface ObjectAttributeDefinition {
|
|
|
277
395
|
displayName: string;
|
|
278
396
|
dataType: "string" | "number" | "boolean" | "text";
|
|
279
397
|
isRequired: boolean;
|
|
280
|
-
defaultValue?:
|
|
398
|
+
defaultValue?: string | number | boolean;
|
|
281
399
|
sortOrder?: number;
|
|
282
400
|
}
|
|
283
401
|
/** 簡易的なオブジェクトタイプ情報 */
|
|
@@ -299,16 +417,23 @@ export interface PluginHooks {
|
|
|
299
417
|
onScenarioReady(callback: (context: ScenarioReadyContext) => void): void;
|
|
300
418
|
onBlockChange(callback: (context: BlockChangeContext) => void): void;
|
|
301
419
|
onCharacterEnter(callback: (context: CharacterContext) => void): void;
|
|
302
|
-
onCharacterExit(callback: (context: CharacterContext) => void): void;
|
|
303
420
|
onDialogueShow(callback: (context: DialogueContext) => void): void;
|
|
304
421
|
onActionExecute(callback: (context: ActionExecutionContext) => void): void;
|
|
305
422
|
onScenarioStart(callback: (context: ScenarioContext) => void): void;
|
|
306
423
|
onScenarioEnd(callback: (context: ScenarioContext) => void): void;
|
|
424
|
+
onBranchStart?(callback: (context: BranchStartContext) => void): void;
|
|
425
|
+
onChoiceSelected?(callback: (context: ChoiceSelectedContext) => void): void;
|
|
426
|
+
onBranchEnd?(callback: () => void): void;
|
|
427
|
+
onBranchBlockChange?(callback: (context: BranchBlockChangeContext) => void): void;
|
|
307
428
|
}
|
|
429
|
+
/** 遷移の種類 */
|
|
430
|
+
export type TransitionSource = "click" | "auto" | "time_wait";
|
|
308
431
|
export interface BlockChangeContext {
|
|
309
432
|
previousBlock?: ScenarioBlock;
|
|
310
433
|
currentBlock: ScenarioBlock;
|
|
311
434
|
blockIndex: number;
|
|
435
|
+
/** 遷移の種類(クリック、自動、時間待ち) */
|
|
436
|
+
transitionSource?: TransitionSource;
|
|
312
437
|
}
|
|
313
438
|
export interface CharacterContext {
|
|
314
439
|
character: Character;
|
|
@@ -363,6 +488,22 @@ export interface ScenarioReadyContext {
|
|
|
363
488
|
currentBlockIndex: number;
|
|
364
489
|
currentBlock: ScenarioBlock;
|
|
365
490
|
}
|
|
491
|
+
export interface BranchStartContext {
|
|
492
|
+
branchBlockId: string;
|
|
493
|
+
choices: Array<{
|
|
494
|
+
id: string;
|
|
495
|
+
text: string;
|
|
496
|
+
order: number;
|
|
497
|
+
}>;
|
|
498
|
+
}
|
|
499
|
+
export interface ChoiceSelectedContext {
|
|
500
|
+
choiceId: string;
|
|
501
|
+
choiceText: string;
|
|
502
|
+
}
|
|
503
|
+
export interface BranchBlockChangeContext {
|
|
504
|
+
blockIndex: number;
|
|
505
|
+
block: ScenarioBlock;
|
|
506
|
+
}
|
|
366
507
|
export interface EffectAPI {
|
|
367
508
|
show(options: EffectOptions): string;
|
|
368
509
|
hide(effectId: string): void;
|
|
@@ -377,8 +518,8 @@ export interface EffectOptions {
|
|
|
377
518
|
animation?: "fade" | "slide" | "bounce" | "none";
|
|
378
519
|
}
|
|
379
520
|
export interface StorageAPI {
|
|
380
|
-
get<T =
|
|
381
|
-
set<T =
|
|
521
|
+
get<T = unknown>(key: string): T | null;
|
|
522
|
+
set<T = unknown>(key: string, value: T): void;
|
|
382
523
|
remove(key: string): void;
|
|
383
524
|
clear(): void;
|
|
384
525
|
}
|
|
@@ -387,6 +528,12 @@ export interface AssetAPI {
|
|
|
387
528
|
preload(filenames: string[]): Promise<void>;
|
|
388
529
|
playSound(filename: string, options?: SoundOptions): void;
|
|
389
530
|
stopSound(filename: string): void;
|
|
531
|
+
/**
|
|
532
|
+
* 作品のサウンドをIDで再生
|
|
533
|
+
* @param soundId - 作品に登録されたサウンドのID
|
|
534
|
+
* @param options - 再生オプション(音量、ループなど)
|
|
535
|
+
*/
|
|
536
|
+
playWorkSound(soundId: string, options?: SoundOptions): void;
|
|
390
537
|
}
|
|
391
538
|
export interface SoundOptions {
|
|
392
539
|
volume?: number;
|
|
@@ -403,7 +550,10 @@ export declare enum ComponentType {
|
|
|
403
550
|
LoadMenu = "LoadMenu",
|
|
404
551
|
SettingsMenu = "SettingsMenu",
|
|
405
552
|
GameMenu = "GameMenu",
|
|
406
|
-
Config = "Config"
|
|
553
|
+
Config = "Config",
|
|
554
|
+
ConversationBranch = "ConversationBranch",
|
|
555
|
+
Background = "Background",
|
|
556
|
+
FullscreenTextBox = "FullscreenTextBox"
|
|
407
557
|
}
|
|
408
558
|
/**
|
|
409
559
|
* コンポーネント登録API
|
|
@@ -412,24 +562,17 @@ export declare enum ComponentType {
|
|
|
412
562
|
export interface ComponentAPI {
|
|
413
563
|
registerComponent(type: ComponentType, component: React.ComponentType): void;
|
|
414
564
|
}
|
|
415
|
-
export type { BacklogEntry };
|
|
416
|
-
export interface DisplayedCharacter {
|
|
417
|
-
objectId: string;
|
|
418
|
-
stateId?: string;
|
|
419
|
-
position?: {
|
|
420
|
-
x: number;
|
|
421
|
-
y: number;
|
|
422
|
-
};
|
|
423
|
-
scale?: number;
|
|
424
|
-
}
|
|
565
|
+
export type { BacklogEntry, DisplayedCharacter } from "./types";
|
|
425
566
|
export interface PlayerSettings {
|
|
426
567
|
textSpeed: number;
|
|
427
568
|
autoPlaySpeed: number;
|
|
428
569
|
bgmVolume: number;
|
|
429
570
|
seVolume: number;
|
|
430
571
|
voiceVolume: number;
|
|
572
|
+
/** 選択されたフォントファミリー */
|
|
573
|
+
selectedFontFamily?: string;
|
|
431
574
|
}
|
|
432
|
-
export type {
|
|
575
|
+
export type { ActionNode, BackgroundData, BackgroundGroupData, BackgroundGroupItem, BackgroundMediaType, BlockOptions, Character, EntityState, FontType, ScenarioBlock, ScenarioBlockType, WorkFont, } from "./types";
|
|
433
576
|
export declare function definePlugin(plugin: LunaPlugin): LunaPlugin;
|
|
434
577
|
export declare function defineComponent(type: ComponentType, component: React.ComponentType): {
|
|
435
578
|
type: ComponentType;
|
|
@@ -515,3 +658,17 @@ export declare function useScreenSizeAtom(): [
|
|
|
515
658
|
];
|
|
516
659
|
export { OverlayUI } from "./components/OverlayUI";
|
|
517
660
|
export { aspectRatio, BasisHeight, BasisWidth } from "./constants/screen-size";
|
|
661
|
+
/**
|
|
662
|
+
* テキスト内の改行文字(\n)を<br />タグに変換してReact要素を返す
|
|
663
|
+
* プラグインがDialogueBoxなどのコンポーネントでテキストを表示する際に使用
|
|
664
|
+
*
|
|
665
|
+
* @param text 表示するテキスト(改行文字を含む可能性がある)
|
|
666
|
+
* @returns 改行が<br />タグに変換されたReact要素
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```tsx
|
|
670
|
+
* const content = dataAPI.get("playback", "displayText") || "";
|
|
671
|
+
* return <div>{renderTextWithLineBreaks(content)}</div>;
|
|
672
|
+
* ```
|
|
673
|
+
*/
|
|
674
|
+
export declare function renderTextWithLineBreaks(text: string): React.ReactElement | string;
|
package/dist/sdk.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
// SDK exports for plugin development
|
|
3
2
|
// This file contains all types and utilities needed for plugin development
|
|
4
3
|
import React from "react";
|
|
@@ -15,6 +14,9 @@ export var ComponentType;
|
|
|
15
14
|
ComponentType["SettingsMenu"] = "SettingsMenu";
|
|
16
15
|
ComponentType["GameMenu"] = "GameMenu";
|
|
17
16
|
ComponentType["Config"] = "Config";
|
|
17
|
+
ComponentType["ConversationBranch"] = "ConversationBranch";
|
|
18
|
+
ComponentType["Background"] = "Background";
|
|
19
|
+
ComponentType["FullscreenTextBox"] = "FullscreenTextBox";
|
|
18
20
|
})(ComponentType || (ComponentType = {}));
|
|
19
21
|
// Component types are already exported as part of the interfaces above
|
|
20
22
|
// Plugin utility function
|
|
@@ -47,7 +49,6 @@ export function calculateFaceRelativePosition(options) {
|
|
|
47
49
|
case "chin":
|
|
48
50
|
baseY = facePosition.y + facePosition.height * 0.3;
|
|
49
51
|
break;
|
|
50
|
-
case "center":
|
|
51
52
|
default:
|
|
52
53
|
// Use face center as is
|
|
53
54
|
break;
|
|
@@ -62,3 +63,27 @@ export { React };
|
|
|
62
63
|
export { OverlayUI } from "./components/OverlayUI";
|
|
63
64
|
// Screen size constants
|
|
64
65
|
export { aspectRatio, BasisHeight, BasisWidth } from "./constants/screen-size";
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Text Utilities - テキスト処理ユーティリティ
|
|
68
|
+
// ============================================================================
|
|
69
|
+
/**
|
|
70
|
+
* テキスト内の改行文字(\n)を<br />タグに変換してReact要素を返す
|
|
71
|
+
* プラグインがDialogueBoxなどのコンポーネントでテキストを表示する際に使用
|
|
72
|
+
*
|
|
73
|
+
* @param text 表示するテキスト(改行文字を含む可能性がある)
|
|
74
|
+
* @returns 改行が<br />タグに変換されたReact要素
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* const content = dataAPI.get("playback", "displayText") || "";
|
|
79
|
+
* return <div>{renderTextWithLineBreaks(content)}</div>;
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function renderTextWithLineBreaks(text) {
|
|
83
|
+
if (!text.includes("\n")) {
|
|
84
|
+
return text;
|
|
85
|
+
}
|
|
86
|
+
return React.createElement(React.Fragment, null, text
|
|
87
|
+
.split("\n")
|
|
88
|
+
.map((line, index, array) => React.createElement("span", { key: index }, line, index < array.length - 1 && React.createElement("br"))));
|
|
89
|
+
}
|