@vnejs/plugins.views.screens.mainmenu 0.1.6 → 0.1.7

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.
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ import { regPlugin } from "@vnejs/shared";
2
+ import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/plugins.views.screens.mainmenu.contract";
3
+ import { MainMenuController } from "./modules/controller.js";
4
+ import { MainMenu } from "./modules/mainmenu.js";
5
+ import { MainMenuView } from "./modules/view.js";
6
+ regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [MainMenuController, MainMenu, MainMenuView]);
@@ -0,0 +1,29 @@
1
+ import { ModuleController } from "@vnejs/module.components";
2
+ import type { MainMenuItem } from "@vnejs/plugins.views.screens.mainmenu.contract";
3
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
4
+ import type { MainMenuClickPayload, MainMenuPluginState } from "../utils/mainmenu.js";
5
+ export declare class MainMenuController extends ModuleController<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams, MainMenuPluginState> {
6
+ name: string;
7
+ emitAccept: () => undefined;
8
+ bgName: string;
9
+ bgTimeout: ReturnType<typeof setTimeout> | null;
10
+ bgIndex: number;
11
+ updateEvent: "vne:mainmenu:update";
12
+ controls: {
13
+ abstract_arrow_up: () => undefined;
14
+ abstract_arrow_bottom: () => undefined;
15
+ abstract_accept: () => undefined;
16
+ abstract_interact: () => undefined;
17
+ };
18
+ controlsIndex: number;
19
+ subscribe: () => void;
20
+ beforeShow: () => Promise<void>;
21
+ afterShow: () => void;
22
+ afterHide: () => void;
23
+ onAccept: () => Promise<undefined>;
24
+ onClick: ({ index }?: MainMenuClickPayload) => Promise<undefined>;
25
+ updateBg: () => Promise<unknown[] | undefined>;
26
+ intervalTickFunc: () => Promise<void>;
27
+ recalcNewBgIndex: (oldIndex?: number) => void;
28
+ click: (items: MainMenuItem[], index: number | null) => false | undefined;
29
+ }
@@ -0,0 +1,67 @@
1
+ import { isNotDisabledNotHided, omitOnClick } from "@vnejs/helpers";
2
+ import { ModuleController } from "@vnejs/module.components";
3
+ const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
4
+ export class MainMenuController extends ModuleController {
5
+ name = "mainmenu.controller";
6
+ emitAccept = () => void this.emit(this.EVENTS.MAINMENU.ACCEPT);
7
+ bgName = this.PARAMS.MAINMENU.BACKGROUND;
8
+ bgTimeout = null;
9
+ bgIndex = -1;
10
+ updateEvent = this.EVENTS.MAINMENU.UPDATE;
11
+ controls = {
12
+ [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: () => void this.decCurrentItem(),
13
+ [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: () => void this.incCurrentItem(),
14
+ [this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => void this.emitAccept(),
15
+ [this.CONST.CONTROLS.BUTTONS.INTERACT]: () => void this.emitAccept(),
16
+ };
17
+ controlsIndex = this.PARAMS.MAINMENU.ZINDEX;
18
+ subscribe = () => {
19
+ this.on(this.EVENTS.MAINMENU.SHOW, this.onShow);
20
+ this.on(this.EVENTS.MAINMENU.HIDE, this.onHide);
21
+ this.on(this.EVENTS.MAINMENU.CLICK, this.onClick);
22
+ this.on(this.EVENTS.MAINMENU.ACCEPT, this.onAccept);
23
+ this.on(this.EVENTS.LOCS.CHANGED, this.updateView);
24
+ this.on(this.EVENTS.STATE.SET, this.onHideForce);
25
+ this.on(this.EVENTS.STATE.CLEAR, this.onHideForce);
26
+ this.on(this.EVENTS.STATE.CLEAR, this.loadBgMedia);
27
+ this.on(this.EVENTS.SYSTEM.STARTED, this.loadBgMedia);
28
+ this.on(this.EVENTS.MEMORY.CLEARED, this.updateBg);
29
+ };
30
+ beforeShow = async () => {
31
+ const items = (await this.emitOne(this.EVENTS.MAINMENU.ITEMS)).map(omitOnClick);
32
+ this.updateState({
33
+ items,
34
+ realItems: items.filter((item) => isNotDisabledNotHided(item)),
35
+ bgSrc: (await this.loadBgMedia()).src,
36
+ });
37
+ this.maxCurrentItem = this.state.realItems.length - 1;
38
+ };
39
+ afterShow = () => {
40
+ if (this.PARAMS.MAINMENU.BACKGROUNDS.length && this.PARAMS.MAINMENU.BACKGROUNDS_INTERVAL) {
41
+ this.recalcNewBgIndex();
42
+ this.bgTimeout = setTimeout(this.intervalTickFunc, this.PARAMS.MAINMENU.BACKGROUNDS_INTERVAL);
43
+ }
44
+ };
45
+ afterHide = () => {
46
+ this.setDefaultState();
47
+ clearTimeout(this.bgTimeout ?? undefined);
48
+ };
49
+ onAccept = async () => void this.click((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)), this.currentItem);
50
+ onClick = async ({ index } = {}) => void this.click((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)), index ?? null);
51
+ updateBg = async () => this.updateStateAndViewFast({ bgSrc: (await this.loadBgMedia()).src });
52
+ intervalTickFunc = async () => {
53
+ if (!this.state.isShow)
54
+ return;
55
+ this.recalcNewBgIndex(this.bgIndex);
56
+ this.bgName = this.PARAMS.MAINMENU.BACKGROUNDS[this.bgIndex];
57
+ await this.waitRerender();
58
+ await this.updateBg();
59
+ this.bgTimeout = setTimeout(this.intervalTickFunc, this.PARAMS.MAINMENU.BACKGROUNDS_INTERVAL);
60
+ };
61
+ recalcNewBgIndex = (oldIndex) => {
62
+ do
63
+ this.bgIndex = getRandomInt(0, this.PARAMS.MAINMENU.BACKGROUNDS.length - 1);
64
+ while (this.bgIndex === oldIndex);
65
+ };
66
+ click = (items, index) => index !== null && void items[index]?.onClick?.();
67
+ }
@@ -0,0 +1,20 @@
1
+ import type { MainMenuItemFactory } from "@vnejs/plugins.views.screens.mainmenu.contract";
2
+ import { Module } from "@vnejs/module";
3
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
4
+ export declare class MainMenu extends Module<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams> {
5
+ name: string;
6
+ isShow: boolean;
7
+ subscribe: () => void;
8
+ init: () => Promise<[unknown[] | undefined, unknown[] | undefined]>;
9
+ onLineExec: () => Promise<unknown[]> | undefined;
10
+ onLineLoad: () => Promise<(unknown[] | undefined)[]>;
11
+ onShow: () => void;
12
+ onHide: () => void;
13
+ onItems: () => Promise<import("@vnejs/plugins.views.screens.mainmenu.contract").MainMenuItem[]>;
14
+ onMemoryCleared: () => false | undefined;
15
+ preload: () => Promise<(unknown[] | undefined)[]>;
16
+ getItemByFunc: (func: MainMenuItemFactory) => import("@vnejs/plugins.views.screens.mainmenu.contract").MainMenuItem;
17
+ emitNext: () => undefined;
18
+ emitLabelGet: (label: string) => Promise<unknown[]> | undefined;
19
+ emitEvent: (event: string) => Promise<unknown[]> | undefined;
20
+ }
@@ -0,0 +1,37 @@
1
+ import { Module } from "@vnejs/module";
2
+ export class MainMenu extends Module {
3
+ name = "mainmenu";
4
+ isShow = false;
5
+ subscribe = () => {
6
+ this.on(this.EVENTS.MAINMENU.SHOW, this.onShow);
7
+ this.on(this.EVENTS.MAINMENU.HIDE, this.onHide);
8
+ this.on(this.EVENTS.MAINMENU.ITEMS, this.onItems);
9
+ this.on(this.EVENTS.MEMORY.CLEARED, this.onMemoryCleared);
10
+ };
11
+ init = () => Promise.all([
12
+ this.emit(this.EVENTS.SCENARIO.LINE_EXEC_REG, { module: this.name, handler: this.onLineExec }),
13
+ this.emit(this.EVENTS.SCENARIO.LINE_LOAD_REG, { module: this.name, handler: this.onLineLoad }),
14
+ ]);
15
+ onLineExec = () => this.emit(this.EVENTS.MAINMENU.SHOW);
16
+ onLineLoad = () => this.preload();
17
+ onShow = () => {
18
+ this.isShow = true;
19
+ this.preload();
20
+ };
21
+ onHide = () => {
22
+ this.isShow = false;
23
+ };
24
+ onItems = async () => {
25
+ await this.waitIsReady();
26
+ return Promise.all(this.PARAMS.MAINMENU.ITEMS.map(this.getItemByFunc));
27
+ };
28
+ onMemoryCleared = () => this.isShow && void this.preload();
29
+ preload = () => Promise.all([
30
+ ...this.PARAMS.MAINMENU.PRELOAD_LABELS.map(this.emitLabelGet),
31
+ ...this.PARAMS.MAINMENU.PRELOAD_EVENTS.map(this.emitEvent),
32
+ ]);
33
+ getItemByFunc = (func) => func(this);
34
+ emitNext = () => void this.emit(this.EVENTS.SCENARIO.NEXT, { module: this.name });
35
+ emitLabelGet = (label) => this.emit(this.EVENTS.SCENARIO.LABEL_GET, { label });
36
+ emitEvent = (event) => this.emit(event);
37
+ }
@@ -0,0 +1,11 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
3
+ import type { MainMenuPluginState } from "../utils/mainmenu.js";
4
+ export declare class MainMenuView extends ModuleView<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams, MainMenuPluginState> {
5
+ name: string;
6
+ locLabel: string;
7
+ animationTime: number;
8
+ updateEvent: "vne:mainmenu:update";
9
+ renderFunc: import("@vnejs/module.components").ViewRenderFunc<MainMenuPluginState>;
10
+ updateHandler: (state?: MainMenuPluginState | undefined) => Promise<void>;
11
+ }
@@ -0,0 +1,10 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+ import { render } from "../view/index.js";
3
+ export class MainMenuView extends ModuleView {
4
+ name = "mainmenu.view";
5
+ locLabel = this.PARAMS.MAINMENU.LOC_LABEL;
6
+ animationTime = this.PARAMS.MAINMENU.TRANSITION;
7
+ updateEvent = this.EVENTS.MAINMENU.UPDATE;
8
+ renderFunc = render;
9
+ updateHandler = this.onUpdateStoreComponent;
10
+ }
@@ -0,0 +1,13 @@
1
+ import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
2
+ import type { SettingsKeys as LayerSettingsKeys, PluginName as LayerPluginName } from "@vnejs/plugins.canvas.layer.contract";
3
+ import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/plugins.controls.contract";
4
+ import type { PluginName as MemoryPluginName, SubscribeEvents as MemorySubscribeEvents } from "@vnejs/plugins.core.memory.contract";
5
+ import type { PluginName as ScenarioPluginName, SubscribeEvents as ScenarioSubscribeEvents } from "@vnejs/plugins.core.scenario.contract";
6
+ import type { PluginName as StatePluginName, SubscribeEvents as StateSubscribeEvents } from "@vnejs/plugins.core.state.contract";
7
+ import type { PluginName as SystemPluginName, SubscribeEvents as SystemSubscribeEvents } from "@vnejs/plugins.core.system.contract";
8
+ import type { PluginName as LocsPluginName, SubscribeEvents as LocsSubscribeEvents } from "@vnejs/plugins.text.locs.contract";
9
+ import type { Params, PluginName, SubscribeEvents } from "@vnejs/plugins.views.screens.mainmenu.contract";
10
+ export type MainMenuPluginEvents = ModuleComponentsEvents & Record<PluginName, SubscribeEvents> & Record<ScenarioPluginName, ScenarioSubscribeEvents> & Record<StatePluginName, StateSubscribeEvents> & Record<SystemPluginName, SystemSubscribeEvents> & Record<MemoryPluginName, MemorySubscribeEvents> & Record<LocsPluginName, LocsSubscribeEvents>;
11
+ export type MainMenuPluginConstants = ModuleComponentsConstants & Record<ControlsPluginName, ControlsConstants>;
12
+ export type MainMenuPluginSettings = ModuleComponentsSettings & Record<LayerPluginName, LayerSettingsKeys>;
13
+ export type MainMenuPluginParams = ModuleComponentsParams & Record<PluginName, Params>;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { Module } from "@vnejs/module";
2
+ import type { MainMenuItem } from "@vnejs/plugins.views.screens.mainmenu.contract";
3
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
4
+ export type MainMenuViewItem = Omit<MainMenuItem, "onClick">;
5
+ export type MainMenuPluginState = {
6
+ isShow: boolean;
7
+ isForce: boolean;
8
+ items?: MainMenuViewItem[];
9
+ realItems?: MainMenuViewItem[];
10
+ locs?: Record<string, string>;
11
+ bgSrc?: string;
12
+ currentItem?: number | null;
13
+ };
14
+ export type MainMenuClickPayload = {
15
+ index?: number;
16
+ };
17
+ export type MainMenuViewContext = {
18
+ emit: Module<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams, MainMenuPluginState>["emit"];
19
+ EVENTS: MainMenuPluginEvents;
20
+ PARAMS: MainMenuPluginParams;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { MainMenuViewContext, MainMenuViewItem } from "../../utils/mainmenu.js";
2
+ type MainMenuControlsProps = MainMenuViewContext & {
3
+ locs?: Record<string, string>;
4
+ currentItem?: number | null;
5
+ realItems?: MainMenuViewItem[];
6
+ items?: MainMenuViewItem[];
7
+ };
8
+ export declare const MainMenuControls: ({ locs, currentItem, realItems, items, emit, EVENTS, PARAMS }: MainMenuControlsProps) => import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useMemo } from "react";
3
+ import { TextControls } from "@vnejs/uis.react";
4
+ export const MainMenuControls = ({ locs = {}, currentItem = null, realItems = [], items = [], emit, EVENTS, PARAMS }) => {
5
+ const mapItems = useCallback(({ locKey, isDisabled, isHided }, i) => ({ text: locs[locKey], isDisabled, isNotRender: isHided, value: i }), [locs]);
6
+ const findSelectedIndex = useCallback((value) => realItems[currentItem ?? -1]?.locKey === value?.locKey, [realItems, currentItem]);
7
+ const onClick = useCallback((index) => void emit(EVENTS.MAINMENU.CLICK, { index: Number(index) }), [emit, EVENTS.MAINMENU.CLICK]);
8
+ const texts = useMemo(() => items.map(mapItems), [items, mapItems]);
9
+ const selectedIndex = useMemo(() => items.findIndex(findSelectedIndex), [items, findSelectedIndex]);
10
+ const propsControls = useMemo(() => ({ ...PARAMS.MAINMENU.VIEW_PROPS.controls.props, texts, onClick, selectedIndex }), [PARAMS.MAINMENU.VIEW_PROPS.controls.props, texts, onClick, selectedIndex]);
11
+ return _jsx(TextControls, { ...propsControls });
12
+ };
@@ -0,0 +1 @@
1
+ export * from "./MainMenuControls.js";
@@ -0,0 +1 @@
1
+ export * from "./MainMenuControls.js";
@@ -0,0 +1,3 @@
1
+ import type { ViewRenderFunc } from "@vnejs/module.components";
2
+ import type { MainMenuPluginState } from "../utils/mainmenu.js";
3
+ export declare const render: ViewRenderFunc<MainMenuPluginState>;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PositionBox, Screen, createRenderFunc, useMemo, useStoreState } from "@vnejs/uis.react";
3
+ import { MainMenuControls } from "./components/index.js";
4
+ const MainMenu = ({ store, onMount, PARAMS, emit, EVENTS }) => {
5
+ const { isShow = false, isForce = false, items = [], bgSrc = "", currentItem = null, realItems = [], locs = {}, } = useStoreState(store, onMount);
6
+ const viewProps = useMemo(() => ({ emit, EVENTS, PARAMS }), [emit, EVENTS, PARAMS]);
7
+ const propsScreen = useMemo(() => ({ ...PARAMS.MAINMENU.VIEW_PROPS.screen, bgSrc, isShow, isForce }), [bgSrc, isShow, isForce, PARAMS.MAINMENU.VIEW_PROPS.screen]);
8
+ const propsControls = useMemo(() => ({ ...viewProps, items, realItems, currentItem, locs }), [viewProps, items, realItems, currentItem, locs]);
9
+ return (_jsx(Screen, { ...propsScreen, children: _jsx(PositionBox, { ...PARAMS.MAINMENU.VIEW_PROPS.controls.position, children: _jsx(MainMenuControls, { ...propsControls }) }) }));
10
+ };
11
+ export const render = createRenderFunc(MainMenu);
package/package.json CHANGED
@@ -1,17 +1,52 @@
1
1
  {
2
2
  "name": "@vnejs/plugins.views.screens.mainmenu",
3
- "version": "0.1.6",
4
- "main": "index.js",
3
+ "version": "0.1.7",
4
+ "description": "",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src",
18
+ "tsconfig.json"
19
+ ],
5
20
  "scripts": {
6
21
  "test": "echo \"Error: no test specified\" && exit 1",
22
+ "build": "npx @vnejs/monorepo package",
7
23
  "publish:major:plugin": "npm run publish:major",
8
24
  "publish:minor:plugin": "npm run publish:minor",
9
25
  "publish:patch:plugin": "npm run publish:patch",
10
- "publish:major": "npm version major && npm publish --access public",
11
- "publish:minor": "npm version minor && npm publish --access public",
12
- "publish:patch": "npm version patch && npm publish --access public"
26
+ "publish:major": "npx @vnejs/monorepo publish major --access public",
27
+ "publish:minor": "npx @vnejs/monorepo publish minor --access public",
28
+ "publish:patch": "npx @vnejs/monorepo publish patch --access public"
13
29
  },
14
30
  "author": "",
15
31
  "license": "ISC",
16
- "description": ""
32
+ "dependencies": {
33
+ "@vnejs/plugins.views.screens.mainmenu.contract": "~0.0.1"
34
+ },
35
+ "peerDependencies": {
36
+ "@vnejs/helpers": "~0.1.0",
37
+ "@vnejs/module": "~0.0.1",
38
+ "@vnejs/module.components": "~0.0.1",
39
+ "@vnejs/plugins.canvas.layer.contract": "~0.0.1",
40
+ "@vnejs/plugins.controls.contract": "~0.0.1",
41
+ "@vnejs/plugins.core.memory.contract": "~0.0.1",
42
+ "@vnejs/plugins.core.scenario.contract": "~0.0.1",
43
+ "@vnejs/plugins.core.state.contract": "~0.0.1",
44
+ "@vnejs/plugins.core.system.contract": "~0.0.1",
45
+ "@vnejs/plugins.text.locs.contract": "~0.0.1",
46
+ "@vnejs/shared": "~0.0.9",
47
+ "@vnejs/uis.react": "~0.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@vnejs/configs.ts-common": "~0.0.1"
51
+ }
17
52
  }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { regPlugin } from "@vnejs/shared";
2
+ import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/plugins.views.screens.mainmenu.contract";
3
+
4
+ import { MainMenuController } from "./modules/controller.js";
5
+ import { MainMenu } from "./modules/mainmenu.js";
6
+ import { MainMenuView } from "./modules/view.js";
7
+
8
+ regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [MainMenuController, MainMenu, MainMenuView]);
@@ -1,24 +1,34 @@
1
- import { ModuleController } from "@vnejs/module.components";
2
1
  import { isNotDisabledNotHided, omitOnClick } from "@vnejs/helpers";
2
+ import { ModuleController } from "@vnejs/module.components";
3
+ import type { MainMenuItem } from "@vnejs/plugins.views.screens.mainmenu.contract";
4
+
5
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
6
+ import type { MainMenuClickPayload, MainMenuPluginState } from "../utils/mainmenu.js";
3
7
 
4
- const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
8
+ const getRandomInt = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min;
5
9
 
6
- export class MainMenuController extends ModuleController {
10
+ export class MainMenuController extends ModuleController<
11
+ MainMenuPluginEvents,
12
+ MainMenuPluginConstants,
13
+ MainMenuPluginSettings,
14
+ MainMenuPluginParams,
15
+ MainMenuPluginState
16
+ > {
7
17
  name = "mainmenu.controller";
8
18
 
9
- emitAccept = () => this.emit(this.EVENTS.MAINMENU.ACCEPT);
19
+ emitAccept = () => void this.emit(this.EVENTS.MAINMENU.ACCEPT);
10
20
 
11
21
  bgName = this.PARAMS.MAINMENU.BACKGROUND;
12
22
 
13
- bgTimeout = null;
23
+ bgTimeout: ReturnType<typeof setTimeout> | null = null;
14
24
  bgIndex = -1;
15
25
 
16
26
  updateEvent = this.EVENTS.MAINMENU.UPDATE;
17
27
  controls = {
18
- [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: this.decCurrentItem,
19
- [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: this.incCurrentItem,
20
- [this.CONST.CONTROLS.BUTTONS.ACCEPT]: this.emitAccept,
21
- [this.CONST.CONTROLS.BUTTONS.INTERACT]: this.emitAccept,
28
+ [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: () => void this.decCurrentItem(),
29
+ [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: () => void this.incCurrentItem(),
30
+ [this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => void this.emitAccept(),
31
+ [this.CONST.CONTROLS.BUTTONS.INTERACT]: () => void this.emitAccept(),
22
32
  };
23
33
  controlsIndex = this.PARAMS.MAINMENU.ZINDEX;
24
34
 
@@ -41,11 +51,15 @@ export class MainMenuController extends ModuleController {
41
51
  };
42
52
 
43
53
  beforeShow = async () => {
44
- const items = (await this.emitOne(this.EVENTS.MAINMENU.ITEMS)).map(omitOnClick);
54
+ const items = ((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)) as MainMenuItem[]).map(omitOnClick);
45
55
 
46
- this.updateState({ items, realItems: items.filter(isNotDisabledNotHided), bgSrc: (await this.loadBgMedia()).src });
56
+ this.updateState({
57
+ items,
58
+ realItems: items.filter((item) => isNotDisabledNotHided(item)),
59
+ bgSrc: (await this.loadBgMedia()).src,
60
+ });
47
61
 
48
- this.maxCurrentItem = this.state.realItems.length - 1;
62
+ this.maxCurrentItem = this.state.realItems!.length - 1;
49
63
  };
50
64
  afterShow = () => {
51
65
  if (this.PARAMS.MAINMENU.BACKGROUNDS.length && this.PARAMS.MAINMENU.BACKGROUNDS_INTERVAL) {
@@ -56,11 +70,11 @@ export class MainMenuController extends ModuleController {
56
70
  afterHide = () => {
57
71
  this.setDefaultState();
58
72
 
59
- clearTimeout(this.bgTimeout);
73
+ clearTimeout(this.bgTimeout ?? undefined);
60
74
  };
61
75
 
62
- onAccept = async () => this.click((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)).filter(isNotDisabledNotHided), this.currentItem);
63
- onClick = async ({ index } = {}) => this.click(await this.emitOne(this.EVENTS.MAINMENU.ITEMS), index);
76
+ onAccept = async () => void this.click((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)) as MainMenuItem[], this.currentItem);
77
+ onClick = async ({ index }: MainMenuClickPayload = {}) => void this.click((await this.emitOne(this.EVENTS.MAINMENU.ITEMS)) as MainMenuItem[], index ?? null);
64
78
 
65
79
  updateBg = async () => this.updateStateAndViewFast({ bgSrc: (await this.loadBgMedia()).src });
66
80
 
@@ -76,10 +90,10 @@ export class MainMenuController extends ModuleController {
76
90
  this.bgTimeout = setTimeout(this.intervalTickFunc, this.PARAMS.MAINMENU.BACKGROUNDS_INTERVAL);
77
91
  };
78
92
 
79
- recalcNewBgIndex = (oldIndex) => {
93
+ recalcNewBgIndex = (oldIndex?: number) => {
80
94
  do this.bgIndex = getRandomInt(0, this.PARAMS.MAINMENU.BACKGROUNDS.length - 1);
81
95
  while (this.bgIndex === oldIndex);
82
96
  };
83
97
 
84
- click = (items, index) => index !== null && items[index]?.onClick?.();
98
+ click = (items: MainMenuItem[], index: number | null) => index !== null && void items[index]?.onClick?.();
85
99
  }
@@ -1,8 +1,13 @@
1
+ import type { MainMenuItemFactory } from "@vnejs/plugins.views.screens.mainmenu.contract";
1
2
  import { Module } from "@vnejs/module";
2
3
 
3
- export class MainMenu extends Module {
4
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
5
+
6
+ export class MainMenu extends Module<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams> {
4
7
  name = "mainmenu";
5
8
 
9
+ isShow = false;
10
+
6
11
  subscribe = () => {
7
12
  this.on(this.EVENTS.MAINMENU.SHOW, this.onShow);
8
13
  this.on(this.EVENTS.MAINMENU.HIDE, this.onHide);
@@ -32,13 +37,17 @@ export class MainMenu extends Module {
32
37
 
33
38
  return Promise.all(this.PARAMS.MAINMENU.ITEMS.map(this.getItemByFunc));
34
39
  };
35
- onMemoryCleared = () => this.isShow && this.preload();
40
+ onMemoryCleared = () => this.isShow && void this.preload();
36
41
 
37
- preload = () => Promise.all([...this.PARAMS.MAINMENU.PRELOAD_LABELS.map(this.emitLabelGet), ...this.PARAMS.MAINMENU.PRELOAD_EVENTS.map(this.emitEvent)]);
42
+ preload = () =>
43
+ Promise.all([
44
+ ...this.PARAMS.MAINMENU.PRELOAD_LABELS.map(this.emitLabelGet),
45
+ ...this.PARAMS.MAINMENU.PRELOAD_EVENTS.map(this.emitEvent),
46
+ ]);
38
47
 
39
- getItemByFunc = (func) => func(this);
48
+ getItemByFunc = (func: MainMenuItemFactory) => func(this);
40
49
 
41
50
  emitNext = () => void this.emit(this.EVENTS.SCENARIO.NEXT, { module: this.name });
42
- emitLabelGet = (label) => this.emit(this.EVENTS.SCENARIO.LABEL_GET, { label });
43
- emitEvent = (event) => this.emit(event);
51
+ emitLabelGet = (label: string) => this.emit(this.EVENTS.SCENARIO.LABEL_GET, { label });
52
+ emitEvent = (event: string) => this.emit(event);
44
53
  }
@@ -0,0 +1,22 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+
3
+ import { render } from "../view/index.js";
4
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
5
+ import type { MainMenuPluginState } from "../utils/mainmenu.js";
6
+
7
+ export class MainMenuView extends ModuleView<
8
+ MainMenuPluginEvents,
9
+ MainMenuPluginConstants,
10
+ MainMenuPluginSettings,
11
+ MainMenuPluginParams,
12
+ MainMenuPluginState
13
+ > {
14
+ name = "mainmenu.view";
15
+
16
+ locLabel = this.PARAMS.MAINMENU.LOC_LABEL;
17
+ animationTime = this.PARAMS.MAINMENU.TRANSITION;
18
+ updateEvent = this.EVENTS.MAINMENU.UPDATE;
19
+
20
+ renderFunc = render;
21
+ updateHandler = this.onUpdateStoreComponent;
22
+ }
package/src/types.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
2
+ import type { SettingsKeys as LayerSettingsKeys, PluginName as LayerPluginName } from "@vnejs/plugins.canvas.layer.contract";
3
+ import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/plugins.controls.contract";
4
+ import type { PluginName as MemoryPluginName, SubscribeEvents as MemorySubscribeEvents } from "@vnejs/plugins.core.memory.contract";
5
+ import type { PluginName as ScenarioPluginName, SubscribeEvents as ScenarioSubscribeEvents } from "@vnejs/plugins.core.scenario.contract";
6
+ import type { PluginName as StatePluginName, SubscribeEvents as StateSubscribeEvents } from "@vnejs/plugins.core.state.contract";
7
+ import type { PluginName as SystemPluginName, SubscribeEvents as SystemSubscribeEvents } from "@vnejs/plugins.core.system.contract";
8
+ import type { PluginName as LocsPluginName, SubscribeEvents as LocsSubscribeEvents } from "@vnejs/plugins.text.locs.contract";
9
+ import type { Params, PluginName, SubscribeEvents } from "@vnejs/plugins.views.screens.mainmenu.contract";
10
+
11
+ export type MainMenuPluginEvents = ModuleComponentsEvents &
12
+ Record<PluginName, SubscribeEvents> &
13
+ Record<ScenarioPluginName, ScenarioSubscribeEvents> &
14
+ Record<StatePluginName, StateSubscribeEvents> &
15
+ Record<SystemPluginName, SystemSubscribeEvents> &
16
+ Record<MemoryPluginName, MemorySubscribeEvents> &
17
+ Record<LocsPluginName, LocsSubscribeEvents>;
18
+
19
+ export type MainMenuPluginConstants = ModuleComponentsConstants & Record<ControlsPluginName, ControlsConstants>;
20
+
21
+ export type MainMenuPluginSettings = ModuleComponentsSettings & Record<LayerPluginName, LayerSettingsKeys>;
22
+
23
+ export type MainMenuPluginParams = ModuleComponentsParams & Record<PluginName, Params>;
@@ -0,0 +1,27 @@
1
+ import type { Module } from "@vnejs/module";
2
+
3
+ import type { MainMenuItem } from "@vnejs/plugins.views.screens.mainmenu.contract";
4
+
5
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
6
+
7
+ export type MainMenuViewItem = Omit<MainMenuItem, "onClick">;
8
+
9
+ export type MainMenuPluginState = {
10
+ isShow: boolean;
11
+ isForce: boolean;
12
+ items?: MainMenuViewItem[];
13
+ realItems?: MainMenuViewItem[];
14
+ locs?: Record<string, string>;
15
+ bgSrc?: string;
16
+ currentItem?: number | null;
17
+ };
18
+
19
+ export type MainMenuClickPayload = {
20
+ index?: number;
21
+ };
22
+
23
+ export type MainMenuViewContext = {
24
+ emit: Module<MainMenuPluginEvents, MainMenuPluginConstants, MainMenuPluginSettings, MainMenuPluginParams, MainMenuPluginState>["emit"];
25
+ EVENTS: MainMenuPluginEvents;
26
+ PARAMS: MainMenuPluginParams;
27
+ };
@@ -0,0 +1,31 @@
1
+ import { useCallback, useMemo } from "react";
2
+
3
+ import { TextControls } from "@vnejs/uis.react";
4
+
5
+ import type { MainMenuViewContext, MainMenuViewItem } from "../../utils/mainmenu.js";
6
+
7
+ type MainMenuControlsProps = MainMenuViewContext & {
8
+ locs?: Record<string, string>;
9
+ currentItem?: number | null;
10
+ realItems?: MainMenuViewItem[];
11
+ items?: MainMenuViewItem[];
12
+ };
13
+
14
+ export const MainMenuControls = ({ locs = {}, currentItem = null, realItems = [], items = [], emit, EVENTS, PARAMS }: MainMenuControlsProps) => {
15
+ const mapItems = useCallback(
16
+ ({ locKey, isDisabled, isHided }: MainMenuViewItem, i: number) => ({ text: locs[locKey], isDisabled, isNotRender: isHided, value: i }),
17
+ [locs],
18
+ );
19
+ const findSelectedIndex = useCallback((value: MainMenuViewItem) => realItems[currentItem ?? -1]?.locKey === value?.locKey, [realItems, currentItem]);
20
+ const onClick = useCallback((index?: unknown) => void emit(EVENTS.MAINMENU.CLICK, { index: Number(index) }), [emit, EVENTS.MAINMENU.CLICK]);
21
+
22
+ const texts = useMemo(() => items.map(mapItems), [items, mapItems]);
23
+ const selectedIndex = useMemo(() => items.findIndex(findSelectedIndex), [items, findSelectedIndex]);
24
+
25
+ const propsControls = useMemo(
26
+ () => ({ ...PARAMS.MAINMENU.VIEW_PROPS.controls.props, texts, onClick, selectedIndex }),
27
+ [PARAMS.MAINMENU.VIEW_PROPS.controls.props, texts, onClick, selectedIndex],
28
+ );
29
+
30
+ return <TextControls {...propsControls} />;
31
+ };
@@ -0,0 +1 @@
1
+ export * from "./MainMenuControls.js";
@@ -0,0 +1,47 @@
1
+ import type { ViewRenderFunc } from "@vnejs/module.components";
2
+ import type { ReactComponentProps } from "@vnejs/uis.react";
3
+ import { PositionBox, Screen, createRenderFunc, useMemo, useStoreState } from "@vnejs/uis.react";
4
+
5
+ import type { MainMenuPluginConstants, MainMenuPluginEvents, MainMenuPluginParams, MainMenuPluginSettings } from "../types.js";
6
+ import type { MainMenuPluginState, MainMenuViewContext } from "../utils/mainmenu.js";
7
+ import { MainMenuControls } from "./components/index.js";
8
+
9
+ type MainMenuComponentProps = ReactComponentProps<
10
+ MainMenuPluginEvents,
11
+ MainMenuPluginConstants,
12
+ MainMenuPluginSettings,
13
+ MainMenuPluginParams,
14
+ MainMenuPluginState
15
+ >;
16
+
17
+ const MainMenu = ({ store, onMount, PARAMS, emit, EVENTS }: MainMenuComponentProps) => {
18
+ const {
19
+ isShow = false,
20
+ isForce = false,
21
+ items = [],
22
+ bgSrc = "",
23
+ currentItem = null,
24
+ realItems = [],
25
+ locs = {},
26
+ } = useStoreState<MainMenuPluginState>(store, onMount);
27
+
28
+ const viewProps = useMemo<MainMenuViewContext>(() => ({ emit, EVENTS, PARAMS }), [emit, EVENTS, PARAMS]);
29
+ const propsScreen = useMemo(
30
+ () => ({ ...PARAMS.MAINMENU.VIEW_PROPS.screen, bgSrc, isShow, isForce }),
31
+ [bgSrc, isShow, isForce, PARAMS.MAINMENU.VIEW_PROPS.screen],
32
+ );
33
+ const propsControls = useMemo(
34
+ () => ({ ...viewProps, items, realItems, currentItem, locs }),
35
+ [viewProps, items, realItems, currentItem, locs],
36
+ );
37
+
38
+ return (
39
+ <Screen {...propsScreen}>
40
+ <PositionBox {...PARAMS.MAINMENU.VIEW_PROPS.controls.position}>
41
+ <MainMenuControls {...propsControls} />
42
+ </PositionBox>
43
+ </Screen>
44
+ );
45
+ };
46
+
47
+ export const render: ViewRenderFunc<MainMenuPluginState> = createRenderFunc(MainMenu);
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@vnejs/configs.ts-common/tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "jsx": "react-jsx"
7
+ },
8
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
9
+ "exclude": ["dist", "node_modules"]
10
+ }
package/const/events.js DELETED
@@ -1,9 +0,0 @@
1
- export const SUBSCRIBE_EVENTS = {
2
- HIDE: "vne:mainmenu:hide",
3
- SHOW: "vne:mainmenu:show",
4
- ITEMS: "vne:mainmenu:items",
5
-
6
- CLICK: "vne:mainmenu:click",
7
- ACCEPT: "vne:mainmenu:accept",
8
- UPDATE: "vne:mainmenu:update",
9
- };
package/const/params.js DELETED
@@ -1,18 +0,0 @@
1
- export const PRELOAD_LABELS = [];
2
- export const PRELOAD_EVENTS = [];
3
-
4
- export const ITEMS = [];
5
-
6
- export const BACKGROUND = "loading";
7
-
8
- export const BACKGROUNDS = [];
9
- export const BACKGROUNDS_INTERVAL = 0;
10
-
11
- export const TRANSITION = 500;
12
- export const ZINDEX = 3000;
13
- export const LOC_LABEL = "mainMenu";
14
-
15
- export const VIEW_PROPS = {
16
- screen: { withBackgroundDark: false, withBackgroundBlur: false, zIndex: ZINDEX, transition: TRANSITION },
17
- controls: { position: { bottom: 240, left: 240 }, props: { textSize: 96, flexGap: 60, flexDirection: "column" } },
18
- };
package/index.js DELETED
@@ -1,10 +0,0 @@
1
- import { regPlugin } from "@vnejs/shared";
2
-
3
- import { SUBSCRIBE_EVENTS } from "./const/events";
4
- import * as params from "./const/params";
5
-
6
- import { MainMenuController } from "./modules/controller";
7
- import { MainMenu } from "./modules/mainmenu";
8
- import { MainMenuView } from "./modules/view";
9
-
10
- regPlugin("MAINMENU", { events: SUBSCRIBE_EVENTS, params }, [MainMenuController, MainMenu, MainMenuView]);
package/modules/view.js DELETED
@@ -1,14 +0,0 @@
1
- import { ModuleView } from "@vnejs/module.components";
2
-
3
- import { render } from "../view";
4
-
5
- export class MainMenuView extends ModuleView {
6
- name = "mainmenu.view";
7
-
8
- locLabel = this.PARAMS.MAINMENU.LOC_LABEL;
9
- animationTime = this.PARAMS.MAINMENU.TRANSITION;
10
- updateEvent = this.EVENTS.MAINMENU.UPDATE;
11
-
12
- renderFunc = render;
13
- updateHandler = this.onUpdateStoreComponent;
14
- }
package/view/index.jsx DELETED
@@ -1,42 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
2
- import { createRoot } from "react-dom/client";
3
-
4
- import { PositionBox, Screen, TextControls } from "@vnejs/uis.react";
5
-
6
- const EMPTY_ARRAY = [];
7
- const EMPTY_OBJ = {};
8
-
9
- const MainMenuControls = ({ locs = EMPTY_OBJ, currentItem = null, realItems = EMPTY_ARRAY, items = EMPTY_ARRAY, ...props } = EMPTY_OBJ) => {
10
- const mapItems = useCallback(({ locKey, isDisabled, isHided }, i) => ({ text: locs[locKey], isDisabled, isNotRender: isHided, value: i }), [locs]);
11
- const findSelectedIndex = useCallback((value) => realItems[currentItem]?.locKey === value?.locKey, [realItems, currentItem]);
12
- const onClick = useCallback((index) => props.emit(props.EVENTS.MAINMENU.CLICK, { index }), EMPTY_ARRAY);
13
-
14
- const texts = useMemo(() => items.map(mapItems), [items, mapItems]);
15
- const selectedIndex = useMemo(() => items.findIndex(findSelectedIndex), [items, findSelectedIndex]);
16
-
17
- const propsControls = useMemo(() => ({ ...props.PARAMS.MAINMENU.VIEW_PROPS.controls.props, texts, onClick, selectedIndex }), [texts, selectedIndex]);
18
-
19
- return <TextControls {...propsControls} />;
20
- };
21
-
22
- const MainMenu = ({ store, onMount, ...props } = EMPTY_OBJ) => {
23
- const [state, setState] = useState(EMPTY_OBJ);
24
-
25
- const { isShow = false, isForce = false, items = EMPTY_ARRAY, bgSrc = "", currentItem = null, realItems = EMPTY_ARRAY, locs = EMPTY_OBJ } = state;
26
-
27
- useEffect(() => store.subscribe(setState), EMPTY_ARRAY);
28
- useEffect(() => void onMount(), EMPTY_ARRAY);
29
-
30
- const propsScreen = useMemo(() => ({ ...props.PARAMS.MAINMENU.VIEW_PROPS.screen, bgSrc, isShow, isForce }), [bgSrc, isShow, isForce]);
31
- const propsControls = useMemo(() => ({ ...props, items, realItems, currentItem, locs }), [items, realItems, currentItem, locs]);
32
-
33
- return (
34
- <Screen {...propsScreen}>
35
- <PositionBox {...props.PARAMS.MAINMENU.VIEW_PROPS.controls.position}>
36
- <MainMenuControls {...propsControls} />
37
- </PositionBox>
38
- </Screen>
39
- );
40
- };
41
-
42
- export const render = (props, root) => createRoot(root).render(<MainMenu {...props} />);