@vnejs/plugins.views.scenario.choose 0.1.10 → 0.1.12

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,8 @@
1
+ import { regPlugin } from "@vnejs/shared";
2
+ import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/plugins.views.scenario.choose.contract";
3
+ import { Choose } from "./modules/choose.js";
4
+ import { ChooseController } from "./modules/controller.js";
5
+ import { ChooseExec } from "./modules/exec.js";
6
+ import { ChooseScenario } from "./modules/scenario.js";
7
+ import { ChooseView } from "./modules/view.js";
8
+ regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [Choose, ChooseController, ChooseExec, ChooseScenario, ChooseView]);
@@ -0,0 +1,19 @@
1
+ import { Module, type ModuleGlobalStateRegistry } from "@vnejs/module";
2
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
3
+ import type { ChooseEmitPayload, ChooseOption, ChooseOptionLine, ChoosePluginModelState, ChooseOptionPayload } from "../utils/choose.js";
4
+ export declare class Choose extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams, ChoosePluginModelState> {
5
+ name: string;
6
+ subscribe: () => void;
7
+ onChooseEmit: ({ options, args }?: ChooseEmitPayload) => Promise<void>;
8
+ onChooseOption: ({ index }?: ChooseOptionPayload) => Promise<void>;
9
+ onStateSet: (payload: ModuleGlobalStateRegistry) => Promise<unknown[] | undefined>;
10
+ onStateClear: () => Promise<unknown[]> | undefined;
11
+ getRealOptions: (options?: ChooseEmitPayload["options"]) => Promise<ChooseOption[]>;
12
+ mapOptions: ({ optionLine, index }: {
13
+ optionLine: ChooseOptionLine;
14
+ index: number;
15
+ }) => Promise<ChooseOption>;
16
+ getOptionText: (line: string, args: Record<string, unknown>) => Promise<unknown> | undefined;
17
+ getOptionCoords: (line: string) => number[] | undefined;
18
+ getDefaultState: () => ChoosePluginModelState;
19
+ }
@@ -0,0 +1,64 @@
1
+ import { splitLineKeywords } from "@vnejs/helpers";
2
+ import { Module } from "@vnejs/module";
3
+ export class Choose extends Module {
4
+ name = "choose";
5
+ subscribe = () => {
6
+ this.on(this.EVENTS.CHOOSE.EMIT, this.onChooseEmit);
7
+ this.on(this.EVENTS.CHOOSE.OPTION, this.onChooseOption);
8
+ this.on(this.EVENTS.STATE.SET, this.onStateSet);
9
+ this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
10
+ };
11
+ onChooseEmit = async ({ options = [], args = {} } = {}) => {
12
+ this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "emit", options, args } });
13
+ this.updateState({ isShow: true, options: await this.getRealOptions(options), args });
14
+ await this.emit(this.EVENTS.CHOOSE.SHOW);
15
+ };
16
+ onChooseOption = async ({ index = 0 } = {}) => {
17
+ this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "choose", index } });
18
+ this.globalState.scenario.curLine = this.state.options[index].index + 1;
19
+ await this.emit(this.EVENTS.CHOOSE.HIDE);
20
+ this.setDefaultState();
21
+ this.emit(this.EVENTS.SCENARIO.NEXT, { module: this.name });
22
+ };
23
+ onStateSet = async (payload) => {
24
+ const clonedState = (await this.emitOne(this.EVENTS.VENDORS.CLONE, this.getStateSlice(payload)));
25
+ if (this.state.isShow === clonedState.isShow)
26
+ return;
27
+ this.state.args = clonedState.args;
28
+ this.state.options = clonedState.options;
29
+ return this.emit(clonedState.isShow ? this.EVENTS.CHOOSE.SHOW : this.EVENTS.CHOOSE.HIDE, { isForce: true });
30
+ };
31
+ onStateClear = () => {
32
+ this.setDefaultState();
33
+ return this.emit(this.EVENTS.CHOOSE.HIDE, { isForce: true });
34
+ };
35
+ getRealOptions = async (options = []) => Promise.all(options.map(this.mapOptions));
36
+ mapOptions = async ({ optionLine, index }) => {
37
+ const args = optionLine.args ?? {};
38
+ const text = (await this.getOptionText(optionLine.line, args));
39
+ const result = { index, text, coords: this.getOptionCoords(optionLine.line), ...args };
40
+ await Promise.all(Object.keys(args).map(async (key) => {
41
+ if (typeof args[key] !== "string" || !String(args[key]).startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE))
42
+ return;
43
+ const { line = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
44
+ result[key] = await this.emitOne(this.EVENTS.CHOOSE.EXEC_GET, { line, module, keywords });
45
+ }));
46
+ return result;
47
+ };
48
+ getOptionText = (line, args) => {
49
+ const quotedText = line.slice(line.indexOf('"'), line.lastIndexOf('"') + 1);
50
+ const text = quotedText.slice(1, quotedText.length - 1);
51
+ return this.emitOne(this.EVENTS.TEXT.REPLACE, {
52
+ text,
53
+ args,
54
+ label: this.globalState.scenario.label,
55
+ state: this.globalState,
56
+ });
57
+ };
58
+ getOptionCoords = (line) => {
59
+ const lineText = line.slice("% option ".length);
60
+ const numbers = lineText.slice(lineText.lastIndexOf('"') + 2);
61
+ return numbers === "" ? undefined : numbers.split(" ").map(Number);
62
+ };
63
+ getDefaultState = () => ({ options: [], args: {}, isShow: false });
64
+ }
@@ -0,0 +1,19 @@
1
+ import { ModuleController } from "@vnejs/module.components";
2
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
3
+ import type { ChoosePluginControllerState } from "../utils/choose.js";
4
+ export declare class ChooseController extends ModuleController<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams, ChoosePluginControllerState> {
5
+ name: string;
6
+ maxCurrentItem: number;
7
+ updateEvent: "vne:choose:update";
8
+ controls: {
9
+ abstract_arrow_up: () => void;
10
+ abstract_arrow_bottom: () => void;
11
+ abstract_accept: () => void;
12
+ };
13
+ controlsIndex: number;
14
+ subscribe: () => void;
15
+ init: () => void;
16
+ beforeShow: () => Promise<void>;
17
+ afterHide: () => void;
18
+ onArrow: (cb: () => void) => void;
19
+ }
@@ -0,0 +1,34 @@
1
+ import { ModuleController } from "@vnejs/module.components";
2
+ export class ChooseController extends ModuleController {
3
+ name = "choose.controller";
4
+ maxCurrentItem = 0;
5
+ updateEvent = this.EVENTS.CHOOSE.UPDATE;
6
+ controls = {
7
+ [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: () => this.onArrow(this.decCurrentItem),
8
+ [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: () => this.onArrow(this.incCurrentItem),
9
+ [this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => {
10
+ if (this.currentItem !== null)
11
+ void this.emit(this.EVENTS.CHOOSE.OPTION, { index: this.currentItem });
12
+ },
13
+ };
14
+ controlsIndex = this.PARAMS.CHOOSE.ZINDEX;
15
+ subscribe = () => {
16
+ this.on(this.EVENTS.CHOOSE.SHOW, this.onShow);
17
+ this.on(this.EVENTS.CHOOSE.HIDE, this.onHide);
18
+ };
19
+ init = () => {
20
+ Object.assign(this.controls, this.PARAMS.CHOOSE.CONTROLS_EXTENSIONS);
21
+ };
22
+ beforeShow = async () => {
23
+ const state = (await this.emitOne(this.EVENTS.VENDORS.CLONE, this.globalState.choose));
24
+ this.updateState(state);
25
+ this.maxCurrentItem = this.state.options.length - 1;
26
+ await this.emit(this.EVENTS.CHOOSE.SHOW_BEFORE);
27
+ };
28
+ afterHide = () => this.setDefaultState();
29
+ onArrow = (cb) => {
30
+ cb();
31
+ while (this.currentItem !== null && this.state.options?.[this.currentItem]?.hided)
32
+ cb();
33
+ };
34
+ }
@@ -0,0 +1,10 @@
1
+ import { Module } from "@vnejs/module";
2
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
3
+ import type { ChooseExecGetPayload, ChooseExecRegPayload } from "../utils/choose.js";
4
+ export declare class ChooseExec extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams> {
5
+ name: string;
6
+ handlers: Record<string, (payload: ChooseExecGetPayload) => unknown>;
7
+ subscribe: () => void;
8
+ onChooseExecReg: ({ handler, module }?: ChooseExecRegPayload) => void;
9
+ onChooseExecGet: ({ module, line, keywords }?: ChooseExecGetPayload) => unknown;
10
+ }
@@ -0,0 +1,18 @@
1
+ import { Module } from "@vnejs/module";
2
+ export class ChooseExec extends Module {
3
+ name = "choose.exec";
4
+ handlers = {};
5
+ subscribe = () => {
6
+ this.on(this.EVENTS.CHOOSE.EXEC_REG, this.onChooseExecReg);
7
+ this.on(this.EVENTS.CHOOSE.EXEC_GET, this.onChooseExecGet);
8
+ };
9
+ onChooseExecReg = ({ handler, module = "" } = {}) => {
10
+ if (handler)
11
+ this.handlers[module] = handler;
12
+ };
13
+ onChooseExecGet = ({ module = "", line = "", keywords = [] } = {}) => {
14
+ if (typeof this.handlers[module] === "function")
15
+ return this.handlers[module]({ line, keywords });
16
+ return "";
17
+ };
18
+ }
@@ -0,0 +1,10 @@
1
+ import { Module } from "@vnejs/module";
2
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
3
+ export declare class ChooseScenario extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams> {
4
+ name: string;
5
+ execName: string;
6
+ init: () => Promise<unknown[]> | undefined;
7
+ onLineExec: ({ args }?: {
8
+ args?: Record<string, unknown>;
9
+ }) => Promise<void>;
10
+ }
@@ -0,0 +1,19 @@
1
+ import { Module } from "@vnejs/module";
2
+ export class ChooseScenario extends Module {
3
+ name = "choose.scenario";
4
+ execName = "choose";
5
+ init = () => this.emit(this.EVENTS.SCENARIO.LINE_EXEC_REG, { block: this.execName, handler: this.onLineExec });
6
+ onLineExec = async ({ args = {} } = {}) => {
7
+ const [{ curLine = 0, label }, optionsArr] = [this.globalState.scenario, []];
8
+ const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label }));
9
+ let indexShift = 1;
10
+ let curLineObj = lines[curLine + indexShift];
11
+ while (curLineObj && (curLineObj.indent ?? 0) >= (lines[curLine]?.indent ?? 0)) {
12
+ curLineObj.line.startsWith("% option") && curLineObj.indent === (lines[curLine]?.indent ?? 0) + 2 && optionsArr.push(curLine + indexShift);
13
+ indexShift++;
14
+ curLineObj = lines[curLine + indexShift];
15
+ }
16
+ const options = optionsArr.map((index) => ({ index, optionLine: lines[index] }));
17
+ await this.emit(this.EVENTS.CHOOSE.EMIT, { args, options });
18
+ };
19
+ }
@@ -0,0 +1,10 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
3
+ import type { ChoosePluginControllerState } from "../utils/choose.js";
4
+ export declare class ChooseView extends ModuleView<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams, ChoosePluginControllerState> {
5
+ name: string;
6
+ animationTime: number;
7
+ updateEvent: "vne:choose:update";
8
+ renderFunc: import("@vnejs/module.components").ViewRenderFunc<ChoosePluginControllerState>;
9
+ updateHandler: (state?: ChoosePluginControllerState | undefined) => Promise<void>;
10
+ }
@@ -0,0 +1,9 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+ import { render } from "../view/index.js";
3
+ export class ChooseView extends ModuleView {
4
+ name = "choose.view";
5
+ animationTime = this.PARAMS.CHOOSE.TRANSITION;
6
+ updateEvent = this.EVENTS.CHOOSE.UPDATE;
7
+ renderFunc = render;
8
+ updateHandler = this.onUpdateStoreComponent;
9
+ }
@@ -0,0 +1,12 @@
1
+ import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
2
+ import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/plugins.controls.contract";
3
+ import type { PluginName as LogsPluginName, SubscribeEvents as LogsSubscribeEvents } from "@vnejs/plugins.core.logs.contract";
4
+ import type { Constants as ScenarioConstants, PluginName as ScenarioPluginName, SubscribeEvents as ScenarioSubscribeEvents } from "@vnejs/plugins.core.scenario.contract";
5
+ import type { PluginName as StatePluginName, SubscribeEvents as StateSubscribeEvents } from "@vnejs/plugins.core.state.contract";
6
+ import type { PluginName as VendorsPluginName, SubscribeEvents as VendorsSubscribeEvents } from "@vnejs/plugins.core.vendors.contract";
7
+ import type { PluginName as TextPluginName, SubscribeEvents as TextSubscribeEvents } from "@vnejs/plugins.text.contract";
8
+ import type { Params, PluginName, SubscribeEvents } from "@vnejs/plugins.views.scenario.choose.contract";
9
+ export type ChoosePluginEvents = ModuleComponentsEvents & Record<PluginName, SubscribeEvents> & Record<ScenarioPluginName, ScenarioSubscribeEvents> & Record<StatePluginName, StateSubscribeEvents> & Record<VendorsPluginName, VendorsSubscribeEvents> & Record<LogsPluginName, LogsSubscribeEvents> & Record<TextPluginName, TextSubscribeEvents>;
10
+ export type ChoosePluginConstants = ModuleComponentsConstants & Record<ControlsPluginName, ControlsConstants> & Record<ScenarioPluginName, ScenarioConstants>;
11
+ export type ChoosePluginSettings = ModuleComponentsSettings;
12
+ export type ChoosePluginParams = ModuleComponentsParams & Record<PluginName, Params>;
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import type { ModuleControllerState } from "@vnejs/module.components";
2
+ export type ChooseOptionLine = {
3
+ line: string;
4
+ args?: Record<string, unknown>;
5
+ indent?: number;
6
+ };
7
+ export type ChooseOption = {
8
+ index: number;
9
+ text?: string;
10
+ coords?: number[];
11
+ hided?: boolean;
12
+ disabled?: boolean;
13
+ [key: string]: unknown;
14
+ };
15
+ export type ChoosePluginModelState = {
16
+ options: ChooseOption[];
17
+ args: Record<string, unknown>;
18
+ isShow: boolean;
19
+ };
20
+ export type ChoosePluginControllerState = ModuleControllerState & ChoosePluginModelState & {
21
+ currentItem?: number | null;
22
+ };
23
+ export type ChooseEmitPayload = {
24
+ options?: {
25
+ index: number;
26
+ optionLine: ChooseOptionLine;
27
+ }[];
28
+ args?: Record<string, unknown>;
29
+ };
30
+ export type ChooseOptionPayload = {
31
+ index?: number;
32
+ };
33
+ export type ChooseExecRegPayload = {
34
+ handler?: (payload: ChooseExecGetPayload) => unknown;
35
+ module?: string;
36
+ };
37
+ export type ChooseExecGetPayload = {
38
+ module?: string;
39
+ line?: string;
40
+ keywords?: string[];
41
+ };
42
+ export type ChooseReplacePayload = {
43
+ text?: string;
44
+ args?: Record<string, unknown>;
45
+ label?: string;
46
+ state?: Record<string, unknown>;
47
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { ViewRenderFunc } from "@vnejs/module.components";
2
+ import type { ChoosePluginControllerState } from "../utils/choose.js";
3
+ export declare const render: ViewRenderFunc<ChoosePluginControllerState>;
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createElement as _createElement } from "react";
3
+ import { PositionBox, Screen, Text, TextControls, createRenderFunc, useCallback, useIsForceHook, useMemo, useStoreState } from "@vnejs/uis.react";
4
+ const renderOptionWithCoords = ({ text, isDisabled, isNotRender, value, coords, props, currentItem, onClick }) => {
5
+ const [x = 0, y = 0] = coords ?? [];
6
+ const positionProps = { left: `${x}%`, top: `${y}%`, translateX: "-50%", translateY: "-50%", isNotRender };
7
+ const propsText = { ...props.PARAMS.CHOOSE.VIEW_PROPS.text, isDisabled, onClick, text, value, isSelected: currentItem === value };
8
+ return (_createElement(PositionBox, { ...positionProps, key: value },
9
+ _jsx(Text, { ...propsText })));
10
+ };
11
+ const Choose = ({ store, onMount, emit, EVENTS, PARAMS }) => {
12
+ const { isShow = false, isForce = false, options = [], currentItem = null } = useStoreState(store, onMount);
13
+ const onClick = useCallback((value) => void emit(EVENTS.CHOOSE.OPTION, { index: Number(value) }), [emit, EVENTS.CHOOSE.OPTION]);
14
+ const isRealForce = useIsForceHook(isForce);
15
+ const optionsMapped = useMemo(() => options.map(({ text, hided, coords, disabled }, i) => ({ text, i, coords, isNotRender: Boolean(hided), isDisabled: Boolean(disabled) })), [options]);
16
+ const textsInfo = useMemo(() => optionsMapped.map(({ i, ...obj }) => ({ value: i, isSelected: currentItem === i, ...obj })), [optionsMapped, currentItem]);
17
+ const optionsRegular = useMemo(() => textsInfo.filter((e) => !e.coords), [textsInfo]);
18
+ const optionsWithCoords = useMemo(() => textsInfo.filter((e) => e.coords), [textsInfo]);
19
+ const propsView = PARAMS.CHOOSE.VIEW_PROPS;
20
+ const propsScreen = useMemo(() => ({ ...propsView.screen, isDisableAutoread: true, isIgnoreOnScreenshot: false, isShow, isForce: isRealForce }), [isShow, isRealForce, propsView.screen]);
21
+ const propsControls = useMemo(() => ({ ...propsView.controls, texts: optionsRegular, onClick }), [optionsRegular, onClick, propsView.controls]);
22
+ const optionsWithCoordsWithProps = useMemo(() => optionsWithCoords.map((option) => ({ ...option, currentItem, onClick, props: { store, onMount, emit, EVENTS, PARAMS } })), [optionsWithCoords, currentItem, onClick, store, onMount, emit, EVENTS, PARAMS]);
23
+ return (_jsxs(Screen, { ...propsScreen, children: [optionsWithCoordsWithProps.map(renderOptionWithCoords), _jsx(PositionBox, { ...propsView.position, children: _jsx(TextControls, { ...propsControls }) })] }));
24
+ };
25
+ export const render = createRenderFunc(Choose);
package/package.json CHANGED
@@ -1,17 +1,51 @@
1
1
  {
2
2
  "name": "@vnejs/plugins.views.scenario.choose",
3
- "version": "0.1.10",
4
- "main": "index.js",
3
+ "version": "0.1.12",
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.scenario.choose.contract": "~0.0.1"
34
+ },
35
+ "peerDependencies": {
36
+ "@vnejs/helpers": "~0.1.0",
37
+ "@vnejs/plugins.controls.contract": "~0.0.1",
38
+ "@vnejs/module": "~0.0.1",
39
+ "@vnejs/module.components": "~0.0.1",
40
+ "@vnejs/plugins.core.logs.contract": "~0.0.1",
41
+ "@vnejs/plugins.core.scenario.contract": "~0.0.1",
42
+ "@vnejs/plugins.core.state.contract": "~0.0.1",
43
+ "@vnejs/plugins.core.vendors.contract": "~0.0.1",
44
+ "@vnejs/plugins.text.contract": "~0.0.1",
45
+ "@vnejs/shared": "~0.0.9",
46
+ "@vnejs/uis.react": "~0.1.0"
47
+ },
48
+ "devDependencies": {
49
+ "@vnejs/configs.ts-common": "~0.0.1"
50
+ }
17
51
  }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { regPlugin } from "@vnejs/shared";
2
+ import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/plugins.views.scenario.choose.contract";
3
+
4
+ import { Choose } from "./modules/choose.js";
5
+ import { ChooseController } from "./modules/controller.js";
6
+ import { ChooseExec } from "./modules/exec.js";
7
+ import { ChooseScenario } from "./modules/scenario.js";
8
+ import { ChooseView } from "./modules/view.js";
9
+
10
+ regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [Choose, ChooseController, ChooseExec, ChooseScenario, ChooseView]);
@@ -0,0 +1,97 @@
1
+ import { splitLineKeywords } from "@vnejs/helpers";
2
+ import { Module, type ModuleGlobalStateRegistry } from "@vnejs/module";
3
+
4
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
5
+ import type {
6
+ ChooseEmitPayload,
7
+ ChooseExecGetPayload,
8
+ ChooseOption,
9
+ ChooseOptionLine,
10
+ ChoosePluginModelState,
11
+ ChooseOptionPayload,
12
+ ChooseReplacePayload,
13
+ } from "../utils/choose.js";
14
+
15
+ export class Choose extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams, ChoosePluginModelState> {
16
+ name = "choose";
17
+
18
+ subscribe = () => {
19
+ this.on(this.EVENTS.CHOOSE.EMIT, this.onChooseEmit);
20
+ this.on(this.EVENTS.CHOOSE.OPTION, this.onChooseOption);
21
+
22
+ this.on(this.EVENTS.STATE.SET, this.onStateSet);
23
+ this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
24
+ };
25
+
26
+ onChooseEmit = async ({ options = [], args = {} }: ChooseEmitPayload = {}) => {
27
+ this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "emit", options, args } });
28
+ this.updateState({ isShow: true, options: await this.getRealOptions(options), args });
29
+ await this.emit(this.EVENTS.CHOOSE.SHOW);
30
+ };
31
+
32
+ onChooseOption = async ({ index = 0 }: ChooseOptionPayload = {}) => {
33
+ this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "choose", index } });
34
+ this.globalState.scenario.curLine = this.state.options[index].index + 1;
35
+ await this.emit(this.EVENTS.CHOOSE.HIDE);
36
+ this.setDefaultState();
37
+ this.emit(this.EVENTS.SCENARIO.NEXT, { module: this.name });
38
+ };
39
+
40
+ onStateSet = async (payload: ModuleGlobalStateRegistry) => {
41
+ const clonedState = (await this.emitOne(this.EVENTS.VENDORS.CLONE, this.getStateSlice(payload))) as ChoosePluginModelState;
42
+
43
+ if (this.state.isShow === clonedState.isShow) return;
44
+
45
+ this.state.args = clonedState.args;
46
+ this.state.options = clonedState.options;
47
+
48
+ return this.emit(clonedState.isShow ? this.EVENTS.CHOOSE.SHOW : this.EVENTS.CHOOSE.HIDE, { isForce: true });
49
+ };
50
+
51
+ onStateClear = () => {
52
+ this.setDefaultState();
53
+
54
+ return this.emit(this.EVENTS.CHOOSE.HIDE, { isForce: true });
55
+ };
56
+
57
+ getRealOptions = async (options: ChooseEmitPayload["options"] = []) => Promise.all(options.map(this.mapOptions));
58
+
59
+ mapOptions = async ({ optionLine, index }: { optionLine: ChooseOptionLine; index: number }) => {
60
+ const args = optionLine.args ?? {};
61
+ const text = (await this.getOptionText(optionLine.line, args)) as string;
62
+ const result: ChooseOption = { index, text, coords: this.getOptionCoords(optionLine.line), ...args };
63
+
64
+ await Promise.all(
65
+ Object.keys(args).map(async (key) => {
66
+ if (typeof args[key] !== "string" || !String(args[key]).startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE)) return;
67
+
68
+ const { line = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
69
+
70
+ result[key] = await this.emitOne(this.EVENTS.CHOOSE.EXEC_GET, { line, module, keywords } satisfies ChooseExecGetPayload);
71
+ }),
72
+ );
73
+
74
+ return result;
75
+ };
76
+
77
+ getOptionText = (line: string, args: Record<string, unknown>) => {
78
+ const quotedText = line.slice(line.indexOf('"'), line.lastIndexOf('"') + 1);
79
+ const text = quotedText.slice(1, quotedText.length - 1);
80
+
81
+ return this.emitOne(this.EVENTS.TEXT.REPLACE, {
82
+ text,
83
+ args,
84
+ label: this.globalState.scenario.label,
85
+ state: this.globalState,
86
+ } satisfies ChooseReplacePayload);
87
+ };
88
+
89
+ getOptionCoords = (line: string) => {
90
+ const lineText = line.slice("% option ".length);
91
+ const numbers = lineText.slice(lineText.lastIndexOf('"') + 2);
92
+
93
+ return numbers === "" ? undefined : numbers.split(" ").map(Number);
94
+ };
95
+
96
+ getDefaultState = (): ChoosePluginModelState => ({ options: [], args: {}, isShow: false });
97
+ }
@@ -0,0 +1,51 @@
1
+ import { ModuleController } from "@vnejs/module.components";
2
+
3
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
4
+ import type { ChoosePluginControllerState } from "../utils/choose.js";
5
+
6
+ export class ChooseController extends ModuleController<
7
+ ChoosePluginEvents,
8
+ ChoosePluginConstants,
9
+ ChoosePluginSettings,
10
+ ChoosePluginParams,
11
+ ChoosePluginControllerState
12
+ > {
13
+ name = "choose.controller";
14
+
15
+ maxCurrentItem = 0;
16
+ updateEvent = this.EVENTS.CHOOSE.UPDATE;
17
+
18
+ controls = {
19
+ [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: () => this.onArrow(this.decCurrentItem),
20
+ [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: () => this.onArrow(this.incCurrentItem),
21
+ [this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => {
22
+ if (this.currentItem !== null) void this.emit(this.EVENTS.CHOOSE.OPTION, { index: this.currentItem });
23
+ },
24
+ };
25
+ controlsIndex = this.PARAMS.CHOOSE.ZINDEX;
26
+
27
+ subscribe = () => {
28
+ this.on(this.EVENTS.CHOOSE.SHOW, this.onShow);
29
+ this.on(this.EVENTS.CHOOSE.HIDE, this.onHide);
30
+ };
31
+
32
+ init = () => {
33
+ Object.assign(this.controls, this.PARAMS.CHOOSE.CONTROLS_EXTENSIONS);
34
+ };
35
+
36
+ beforeShow = async () => {
37
+ const state = (await this.emitOne(this.EVENTS.VENDORS.CLONE, this.globalState.choose)) as ChoosePluginControllerState;
38
+
39
+ this.updateState(state);
40
+ this.maxCurrentItem = this.state.options.length - 1;
41
+
42
+ await this.emit(this.EVENTS.CHOOSE.SHOW_BEFORE);
43
+ };
44
+
45
+ afterHide = () => this.setDefaultState();
46
+
47
+ onArrow = (cb: () => void) => {
48
+ cb();
49
+ while (this.currentItem !== null && this.state.options?.[this.currentItem]?.hided) cb();
50
+ };
51
+ }
@@ -0,0 +1,24 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
4
+ import type { ChooseExecGetPayload, ChooseExecRegPayload } from "../utils/choose.js";
5
+
6
+ export class ChooseExec extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams> {
7
+ name = "choose.exec";
8
+
9
+ handlers: Record<string, (payload: ChooseExecGetPayload) => unknown> = {};
10
+
11
+ subscribe = () => {
12
+ this.on(this.EVENTS.CHOOSE.EXEC_REG, this.onChooseExecReg);
13
+ this.on(this.EVENTS.CHOOSE.EXEC_GET, this.onChooseExecGet);
14
+ };
15
+
16
+ onChooseExecReg = ({ handler, module = "" }: ChooseExecRegPayload = {}) => {
17
+ if (handler) this.handlers[module] = handler;
18
+ };
19
+
20
+ onChooseExecGet = ({ module = "", line = "", keywords = [] }: ChooseExecGetPayload = {}) => {
21
+ if (typeof this.handlers[module] === "function") return this.handlers[module]({ line, keywords });
22
+ return "";
23
+ };
24
+ }
@@ -0,0 +1,30 @@
1
+ import { Module } from "@vnejs/module";
2
+
3
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
4
+ import type { ChooseEmitPayload, ChooseOptionLine } from "../utils/choose.js";
5
+
6
+ export class ChooseScenario extends Module<ChoosePluginEvents, ChoosePluginConstants, ChoosePluginSettings, ChoosePluginParams> {
7
+ name = "choose.scenario";
8
+
9
+ execName = "choose";
10
+
11
+ init = () => this.emit(this.EVENTS.SCENARIO.LINE_EXEC_REG, { block: this.execName, handler: this.onLineExec });
12
+
13
+ onLineExec = async ({ args = {} }: { args?: Record<string, unknown> } = {}) => {
14
+ const [{ curLine = 0, label }, optionsArr] = [this.globalState.scenario, [] as number[]];
15
+ const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label })) as ChooseOptionLine[];
16
+
17
+ let indexShift = 1;
18
+ let curLineObj = lines[curLine + indexShift];
19
+
20
+ while (curLineObj && (curLineObj.indent ?? 0) >= (lines[curLine]?.indent ?? 0)) {
21
+ curLineObj.line.startsWith("% option") && curLineObj.indent === (lines[curLine]?.indent ?? 0) + 2 && optionsArr.push(curLine + indexShift);
22
+ indexShift++;
23
+ curLineObj = lines[curLine + indexShift];
24
+ }
25
+
26
+ const options = optionsArr.map((index) => ({ index, optionLine: lines[index] }));
27
+
28
+ await this.emit(this.EVENTS.CHOOSE.EMIT, { args, options } satisfies ChooseEmitPayload);
29
+ };
30
+ }
@@ -0,0 +1,21 @@
1
+ import { ModuleView } from "@vnejs/module.components";
2
+
3
+ import { render } from "../view/index.js";
4
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
5
+ import type { ChoosePluginControllerState } from "../utils/choose.js";
6
+
7
+ export class ChooseView extends ModuleView<
8
+ ChoosePluginEvents,
9
+ ChoosePluginConstants,
10
+ ChoosePluginSettings,
11
+ ChoosePluginParams,
12
+ ChoosePluginControllerState
13
+ > {
14
+ name = "choose.view";
15
+
16
+ animationTime = this.PARAMS.CHOOSE.TRANSITION;
17
+ updateEvent = this.EVENTS.CHOOSE.UPDATE;
18
+
19
+ renderFunc = render;
20
+ updateHandler = this.onUpdateStoreComponent;
21
+ }
package/src/types.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
2
+ import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/plugins.controls.contract";
3
+ import type { PluginName as LogsPluginName, SubscribeEvents as LogsSubscribeEvents } from "@vnejs/plugins.core.logs.contract";
4
+ import type { Constants as ScenarioConstants, PluginName as ScenarioPluginName, SubscribeEvents as ScenarioSubscribeEvents } from "@vnejs/plugins.core.scenario.contract";
5
+ import type { PluginName as StatePluginName, SubscribeEvents as StateSubscribeEvents } from "@vnejs/plugins.core.state.contract";
6
+ import type { PluginName as VendorsPluginName, SubscribeEvents as VendorsSubscribeEvents } from "@vnejs/plugins.core.vendors.contract";
7
+ import type { PluginName as TextPluginName, SubscribeEvents as TextSubscribeEvents } from "@vnejs/plugins.text.contract";
8
+ import type { Params, PluginName, SubscribeEvents } from "@vnejs/plugins.views.scenario.choose.contract";
9
+
10
+ export type ChoosePluginEvents = ModuleComponentsEvents &
11
+ Record<PluginName, SubscribeEvents> &
12
+ Record<ScenarioPluginName, ScenarioSubscribeEvents> &
13
+ Record<StatePluginName, StateSubscribeEvents> &
14
+ Record<VendorsPluginName, VendorsSubscribeEvents> &
15
+ Record<LogsPluginName, LogsSubscribeEvents> &
16
+ Record<TextPluginName, TextSubscribeEvents>;
17
+
18
+ export type ChoosePluginConstants = ModuleComponentsConstants &
19
+ Record<ControlsPluginName, ControlsConstants> &
20
+ Record<ScenarioPluginName, ScenarioConstants>;
21
+
22
+ export type ChoosePluginSettings = ModuleComponentsSettings;
23
+
24
+ export type ChoosePluginParams = ModuleComponentsParams & Record<PluginName, Params>;
@@ -0,0 +1,54 @@
1
+ import type { ModuleControllerState } from "@vnejs/module.components";
2
+
3
+ export type ChooseOptionLine = {
4
+ line: string;
5
+ args?: Record<string, unknown>;
6
+ indent?: number;
7
+ };
8
+
9
+ export type ChooseOption = {
10
+ index: number;
11
+ text?: string;
12
+ coords?: number[];
13
+ hided?: boolean;
14
+ disabled?: boolean;
15
+ [key: string]: unknown;
16
+ };
17
+
18
+ export type ChoosePluginModelState = {
19
+ options: ChooseOption[];
20
+ args: Record<string, unknown>;
21
+ isShow: boolean;
22
+ };
23
+
24
+ export type ChoosePluginControllerState = ModuleControllerState &
25
+ ChoosePluginModelState & {
26
+ currentItem?: number | null;
27
+ };
28
+
29
+ export type ChooseEmitPayload = {
30
+ options?: { index: number; optionLine: ChooseOptionLine }[];
31
+ args?: Record<string, unknown>;
32
+ };
33
+
34
+ export type ChooseOptionPayload = {
35
+ index?: number;
36
+ };
37
+
38
+ export type ChooseExecRegPayload = {
39
+ handler?: (payload: ChooseExecGetPayload) => unknown;
40
+ module?: string;
41
+ };
42
+
43
+ export type ChooseExecGetPayload = {
44
+ module?: string;
45
+ line?: string;
46
+ keywords?: string[];
47
+ };
48
+
49
+ export type ChooseReplacePayload = {
50
+ text?: string;
51
+ args?: Record<string, unknown>;
52
+ label?: string;
53
+ state?: Record<string, unknown>;
54
+ };
@@ -0,0 +1,83 @@
1
+ import type { ViewRenderFunc } from "@vnejs/module.components";
2
+ import type { ReactComponentProps } from "@vnejs/uis.react";
3
+ import { PositionBox, Screen, Text, TextControls, createRenderFunc, useCallback, useIsForceHook, useMemo, useStoreState } from "@vnejs/uis.react";
4
+
5
+ import type { ChoosePluginConstants, ChoosePluginEvents, ChoosePluginParams, ChoosePluginSettings } from "../types.js";
6
+ import type { ChooseOption, ChoosePluginControllerState } from "../utils/choose.js";
7
+
8
+ type ChooseComponentProps = ReactComponentProps<
9
+ ChoosePluginEvents,
10
+ ChoosePluginConstants,
11
+ ChoosePluginSettings,
12
+ ChoosePluginParams,
13
+ ChoosePluginControllerState
14
+ >;
15
+
16
+ type OptionWithCoordsProps = {
17
+ text?: string;
18
+ isDisabled?: boolean;
19
+ isNotRender?: boolean;
20
+ value?: number;
21
+ coords?: number[];
22
+ props: ChooseComponentProps;
23
+ currentItem?: number | null;
24
+ onClick: (value?: unknown) => void;
25
+ };
26
+
27
+ const renderOptionWithCoords = ({ text, isDisabled, isNotRender, value, coords, props, currentItem, onClick }: OptionWithCoordsProps) => {
28
+ const [x = 0, y = 0] = coords ?? [];
29
+ const positionProps = { left: `${x}%`, top: `${y}%`, translateX: "-50%", translateY: "-50%", isNotRender };
30
+ const propsText = { ...props.PARAMS.CHOOSE.VIEW_PROPS.text, isDisabled, onClick, text, value, isSelected: currentItem === value };
31
+
32
+ return (
33
+ <PositionBox
34
+ {...positionProps}
35
+ key={value}
36
+ >
37
+ <Text {...propsText} />
38
+ </PositionBox>
39
+ );
40
+ };
41
+
42
+ const Choose = ({ store, onMount, emit, EVENTS, PARAMS }: ChooseComponentProps) => {
43
+ const { isShow = false, isForce = false, options = [], currentItem = null } = useStoreState<ChoosePluginControllerState>(store, onMount);
44
+
45
+ const onClick = useCallback((value?: unknown) => void emit(EVENTS.CHOOSE.OPTION, { index: Number(value) }), [emit, EVENTS.CHOOSE.OPTION]);
46
+
47
+ const isRealForce = useIsForceHook(isForce);
48
+
49
+ const optionsMapped = useMemo(
50
+ () => options.map(({ text, hided, coords, disabled }: ChooseOption, i: number) => ({ text, i, coords, isNotRender: Boolean(hided), isDisabled: Boolean(disabled) })),
51
+ [options],
52
+ );
53
+ const textsInfo = useMemo(
54
+ () => optionsMapped.map(({ i, ...obj }) => ({ value: i, isSelected: currentItem === i, ...obj })),
55
+ [optionsMapped, currentItem],
56
+ );
57
+ const optionsRegular = useMemo(() => textsInfo.filter((e) => !e.coords), [textsInfo]);
58
+ const optionsWithCoords = useMemo(() => textsInfo.filter((e) => e.coords), [textsInfo]);
59
+
60
+ const propsView = PARAMS.CHOOSE.VIEW_PROPS;
61
+
62
+ const propsScreen = useMemo(
63
+ () => ({ ...propsView.screen, isDisableAutoread: true, isIgnoreOnScreenshot: false, isShow, isForce: isRealForce }),
64
+ [isShow, isRealForce, propsView.screen],
65
+ );
66
+ const propsControls = useMemo(() => ({ ...propsView.controls, texts: optionsRegular, onClick }), [optionsRegular, onClick, propsView.controls]);
67
+
68
+ const optionsWithCoordsWithProps = useMemo(
69
+ () => optionsWithCoords.map((option) => ({ ...option, currentItem, onClick, props: { store, onMount, emit, EVENTS, PARAMS } as ChooseComponentProps })),
70
+ [optionsWithCoords, currentItem, onClick, store, onMount, emit, EVENTS, PARAMS],
71
+ );
72
+
73
+ return (
74
+ <Screen {...propsScreen}>
75
+ {optionsWithCoordsWithProps.map(renderOptionWithCoords)}
76
+ <PositionBox {...propsView.position}>
77
+ <TextControls {...propsControls} />
78
+ </PositionBox>
79
+ </Screen>
80
+ );
81
+ };
82
+
83
+ export const render: ViewRenderFunc<ChoosePluginControllerState> = createRenderFunc(Choose);
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
- EMIT: "vne:choose:emit",
3
- OPTION: "vne:choose:option",
4
- SHOW: "vne:choose:show",
5
- HIDE: "vne:choose:hide",
6
- UPDATE: "vne:choose:update",
7
- EXEC_REG: "vne:choose:exec_reg",
8
- EXEC_GET: "vne:choose:exec_get",
9
- };
package/const/params.js DELETED
@@ -1,11 +0,0 @@
1
- export const TRANSITION = 300;
2
- export const ZINDEX = 1200;
3
-
4
- export const VIEW_PROPS = {
5
- screen: { withBlur: true, withDark: true, zIndex: ZINDEX, transition: TRANSITION },
6
- position: { isCentered: true },
7
- controls: { flexDirection: "column", flexGap: 60, textSize: 96, textAlign: "center" },
8
- text: { size: 96 },
9
- };
10
-
11
- export const CONTROLS_EXTENSIONS = {};
package/index.js DELETED
@@ -1,12 +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 { Choose } from "./modules/choose";
7
- import { ChooseController } from "./modules/controller";
8
- import { ChooseExec } from "./modules/exec";
9
- import { ChooseScenario } from "./modules/scenario";
10
- import { ChooseView } from "./modules/view";
11
-
12
- regPlugin("CHOOSE", { events: SUBSCRIBE_EVENTS, params }, [Choose, ChooseController, ChooseExec, ChooseScenario, ChooseView]);
package/modules/choose.js DELETED
@@ -1,75 +0,0 @@
1
- import { splitLineKeywords } from "@vnejs/helpers";
2
- import { Module } from "@vnejs/module";
3
-
4
- export class Choose extends Module {
5
- name = "choose";
6
-
7
- subscribe = () => {
8
- this.on(this.EVENTS.CHOOSE.EMIT, this.onChooseEmit);
9
- this.on(this.EVENTS.CHOOSE.OPTION, this.onChooseOption);
10
-
11
- this.on(this.EVENTS.STATE.SET, this.onStateSet);
12
- this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
13
- };
14
-
15
- onChooseEmit = async ({ options, args } = {}) => {
16
- this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "emit", options, args } });
17
- this.updateState({ isShow: true, options: await this.getRealOptions(options), args });
18
- await this.emit(this.EVENTS.CHOOSE.SHOW);
19
- };
20
- onChooseOption = async ({ index = 0 } = {}) => {
21
- this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "choose", index } });
22
- this.globalState.scenario.curLine = this.state.options[index].index + 1;
23
- await this.emit(this.EVENTS.CHOOSE.HIDE);
24
- this.setDefaultState();
25
- this.emit(this.EVENTS.SCENARIO.NEXT, { module: this.name });
26
- };
27
-
28
- onStateSet = async ({ [this.name]: state } = {}) => {
29
- const clonedState = await this.emitOne(this.EVENTS.VENDORS.CLONE, state);
30
-
31
- if (this.state.isShow === clonedState.isShow) return;
32
-
33
- this.state.args = clonedState.args;
34
- this.state.options = clonedState.options;
35
-
36
- return this.emit(state.isShow ? this.EVENTS.CHOOSE.SHOW : this.EVENTS.CHOOSE.HIDE, { isForce: true });
37
- };
38
- onStateClear = () => {
39
- this.setDefaultState();
40
-
41
- return this.emit(this.EVENTS.CHOOSE.HIDE, { isForce: true });
42
- };
43
-
44
- getRealOptions = async (options = []) => Promise.all(options.map(this.mapOptions));
45
- mapOptions = async ({ optionLine, index } = {}) => {
46
- const text = await this.getOptionText(optionLine.line, optionLine.args);
47
- const result = { index, text, coords: this.getOptionCoords(optionLine.line), ...optionLine.args };
48
-
49
- await Promise.all(
50
- Object.keys(optionLine.args).map(async (key) => {
51
- if (typeof optionLine.args[key] !== "string" || !optionLine.args[key].startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE)) return;
52
-
53
- const { line = "", module = "", keywords = [] } = splitLineKeywords(optionLine.args[key]);
54
-
55
- result[key] = await this.emitOne(this.EVENTS.CHOOSE.EXEC_GET, { line, module, keywords });
56
- }),
57
- );
58
-
59
- return result;
60
- };
61
- getOptionText = (line, args) => {
62
- const quotedText = line.slice(line.indexOf('"'), line.lastIndexOf('"') + 1);
63
- const text = quotedText.slice(1, quotedText.length - 1);
64
-
65
- return this.emitOne(this.EVENTS.TEXT.REPLACE, { text, args, label: this.globalState.scenario.label, state: this.globalState });
66
- };
67
- getOptionCoords = (line) => {
68
- const lineText = line.slice("% option ".length);
69
- const numbers = lineText.slice(lineText.lastIndexOf('"') + 2);
70
-
71
- return numbers === "" ? undefined : numbers.split(" ").map(Number);
72
- };
73
-
74
- getDefaultState = () => ({ options: [], args: {}, isShow: false });
75
- }
@@ -1,38 +0,0 @@
1
- import { ModuleController } from "@vnejs/module.components";
2
-
3
- export class ChooseController extends ModuleController {
4
- name = "choose.controller";
5
-
6
- maxCurrentItem = 0;
7
- updateEvent = this.EVENTS.CHOOSE.UPDATE;
8
-
9
- controls = {
10
- [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: () => this.onArrow(this.decCurrentItem),
11
- [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: () => this.onArrow(this.incCurrentItem),
12
- [this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => this.currentItem !== null && this.emit(this.EVENTS.CHOOSE.OPTION, { index: this.currentItem }),
13
- };
14
- controlsIndex = this.PARAMS.CHOOSE.ZINDEX;
15
-
16
- subscribe = () => {
17
- this.on(this.EVENTS.CHOOSE.SHOW, this.onShow);
18
- this.on(this.EVENTS.CHOOSE.HIDE, this.onHide);
19
- };
20
- init = () => {
21
- Object.assign(this.controls, this.PARAMS.CHOOSE.CONTROLS_EXTENSIONS);
22
- };
23
-
24
- beforeShow = async () => {
25
- const state = await this.emitOne(this.EVENTS.VENDORS.CLONE, this.globalState.choose);
26
-
27
- this.updateState(state);
28
- this.maxCurrentItem = this.state.options.length - 1;
29
-
30
- return this.emit(this.EVENTS.INTERFACE.HIDE);
31
- };
32
- afterHide = () => this.setDefaultState();
33
-
34
- onArrow = (cb) => {
35
- cb();
36
- while (this.state.options?.[this.currentItem].hided) cb();
37
- };
38
- }
package/modules/exec.js DELETED
@@ -1,21 +0,0 @@
1
- import { Module } from "@vnejs/module";
2
-
3
- export class ChooseExec extends Module {
4
- name = "choose.exec";
5
-
6
- handlers = {};
7
-
8
- subscribe = () => {
9
- this.on(this.EVENTS.CHOOSE.EXEC_REG, this.onChooseExecReg);
10
- this.on(this.EVENTS.CHOOSE.EXEC_GET, this.onChooseExecGet);
11
- };
12
-
13
- onChooseExecReg = ({ handler, module } = {}) => {
14
- this.handlers[module] = handler;
15
- };
16
-
17
- onChooseExecGet = ({ module, line = "", keywords = [] } = {}) => {
18
- if (typeof this.handlers[module] === "function") return this.handlers[module]({ line, keywords });
19
- return "";
20
- };
21
- }
@@ -1,26 +0,0 @@
1
- import { Module } from "@vnejs/module";
2
-
3
- export class ChooseScenario extends Module {
4
- name = "choose.scenario";
5
-
6
- execName = "choose";
7
-
8
- init = () => this.emit(this.EVENTS.SCENARIO.LINE_EXEC_REG, { block: this.execName, handler: this.onLineExec });
9
-
10
- onLineExec = async ({ args = {} } = {}) => {
11
- const [{ curLine = 0, label }, optionsArr] = [this.globalState.scenario, []];
12
- const lines = await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label });
13
-
14
- let [indexShift, curLineObj] = [1, lines[curLine + 1]];
15
-
16
- while (curLineObj && curLineObj.indent >= lines[curLine].indent) {
17
- curLineObj.line.startsWith("% option") && curLineObj.indent === lines[curLine].indent + 2 && optionsArr.push(curLine + indexShift);
18
- indexShift++;
19
- curLineObj = lines[curLine + indexShift];
20
- }
21
-
22
- const options = optionsArr.map((index) => ({ index, optionLine: lines[index] }));
23
-
24
- await this.emit(this.EVENTS.CHOOSE.EMIT, { args, options });
25
- };
26
- }
package/modules/view.js DELETED
@@ -1,13 +0,0 @@
1
- import { ModuleView } from "@vnejs/module.components";
2
-
3
- import { render } from "../view";
4
-
5
- export class ChooseView extends ModuleView {
6
- name = "choose.view";
7
-
8
- animationTime = this.PARAMS.CHOOSE.TRANSITION;
9
- updateEvent = this.EVENTS.CHOOSE.UPDATE;
10
-
11
- renderFunc = render;
12
- updateHandler = this.onUpdateStoreComponent;
13
- }
package/view/index.jsx DELETED
@@ -1,66 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
2
- import { createRoot } from "react-dom/client";
3
-
4
- import { PositionBox, Screen, Text, TextControls, useIsForceHook } from "@vnejs/uis.react";
5
-
6
- const EMPTY_ARRAY = [];
7
-
8
- const renderOptionWithCoords = ({ text, isDisabled, isNotRender, value, coords: [x, y], props, currentItem, onClick } = {}) => {
9
- const positionProps = { left: `${x}%`, top: `${y}%`, translateX: "-50%", translateY: "-50%", isNotRender };
10
- const propsText = { ...props.PARAMS.CHOOSE.VIEW_PROPS.text, isDisabled, onClick, text, value, isSelected: currentItem === value };
11
-
12
- return (
13
- <PositionBox
14
- {...positionProps}
15
- key={value}
16
- >
17
- <Text {...propsText} />
18
- </PositionBox>
19
- );
20
- };
21
-
22
- const Choose = ({ store, onMount, ...props } = {}) => {
23
- const [{ isShow = false, isForce = false, options = EMPTY_ARRAY, currentItem = null }, setState] = useState({});
24
-
25
- useEffect(() => store.subscribe(setState), []);
26
- useEffect(() => void onMount(), []);
27
-
28
- const onClick = useCallback((index) => props.emit(props.EVENTS.CHOOSE.OPTION, { index }), []);
29
-
30
- const isRealForce = useIsForceHook(isForce);
31
-
32
- const optionsMapped = useMemo(
33
- () => options.map(({ text, hided, coords, disabled }, i) => ({ text, i, coords, isNotRender: Boolean(hided), isDisabled: Boolean(disabled) })),
34
- [options],
35
- );
36
- const textsInfo = useMemo(
37
- () => optionsMapped.map(({ i, ...obj } = {}) => ({ value: i, isSelected: currentItem === i, ...obj })),
38
- [optionsMapped, currentItem],
39
- );
40
- const optionsRegular = useMemo(() => textsInfo.filter((e) => !e.coords), [textsInfo]);
41
- const optionsWithCoords = useMemo(() => textsInfo.filter((e) => e.coords), [textsInfo]);
42
-
43
- const propsView = props.PARAMS.CHOOSE.VIEW_PROPS;
44
-
45
- const propsScreen = useMemo(
46
- () => ({ ...propsView.screen, isDisableAutoread: true, isIgnoreOnScreenshot: false, isShow, isForce: isRealForce }),
47
- [isShow, isRealForce],
48
- );
49
- const propsControls = useMemo(() => ({ ...propsView.controls, texts: optionsRegular, onClick }), [optionsRegular]);
50
-
51
- const optionsWithCoordsWithProps = useMemo(
52
- () => optionsWithCoords.map((option) => ({ ...option, currentItem, onClick, props })),
53
- [optionsWithCoords, currentItem, onClick],
54
- );
55
-
56
- return (
57
- <Screen {...propsScreen}>
58
- {optionsWithCoordsWithProps.map(renderOptionWithCoords)}
59
- <PositionBox {...propsView.position}>
60
- <TextControls {...propsControls} />
61
- </PositionBox>
62
- </Screen>
63
- );
64
- };
65
-
66
- export const render = (props, root) => createRoot(root).render(<Choose {...props} />);