@vnejs/plugins.views.settings 0.1.3 → 0.2.2

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.
Files changed (39) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +6 -0
  3. package/dist/modules/controller.d.ts +44 -0
  4. package/dist/modules/controller.js +169 -0
  5. package/dist/modules/view.d.ts +11 -0
  6. package/dist/modules/view.js +10 -0
  7. package/dist/types.d.ts +10 -0
  8. package/dist/types.js +1 -0
  9. package/dist/utils/settings.d.ts +25 -0
  10. package/dist/utils/settings.js +1 -0
  11. package/dist/view/SettingsExampleText.d.ts +9 -0
  12. package/dist/view/SettingsExampleText.js +25 -0
  13. package/dist/view/SettingsTabContent.d.ts +15 -0
  14. package/dist/view/SettingsTabContent.js +32 -0
  15. package/dist/view/index.d.ts +3 -0
  16. package/dist/view/index.js +18 -0
  17. package/package.json +52 -7
  18. package/src/index.ts +9 -0
  19. package/src/modules/controller.ts +221 -0
  20. package/src/modules/view.ts +22 -0
  21. package/src/tests/controller.test.ts +240 -0
  22. package/src/tests/setup.ts +44 -0
  23. package/src/types.ts +20 -0
  24. package/src/utils/settings.ts +28 -0
  25. package/src/view/SettingsExampleText.tsx +61 -0
  26. package/src/view/SettingsTabContent.tsx +118 -0
  27. package/src/view/index.tsx +63 -0
  28. package/tsconfig.json +10 -0
  29. package/const/events.js +0 -7
  30. package/const/params.js +0 -43
  31. package/index.js +0 -9
  32. package/modules/controller.js +0 -132
  33. package/modules/view.js +0 -14
  34. package/view/components/SettingsControls.jsx +0 -22
  35. package/view/components/SettingsCross.jsx +0 -13
  36. package/view/components/SettingsExampleText.jsx +0 -40
  37. package/view/components/SettingsTabContent.jsx +0 -66
  38. package/view/components/index.js +0 -4
  39. package/view/index.jsx +0 -42
@@ -0,0 +1,118 @@
1
+ import type { SettingsField } from "@vnejs/contracts.views.settings";
2
+ import type { ReactComponentProps } from "@vnejs/uis.react";
3
+ import { Flex, PositionBox, Settings, useCallback } from "@vnejs/uis.react";
4
+
5
+ import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
6
+ import type { SettingsViewPluginState } from "../utils/settings.js";
7
+ import { SettingsExampleText } from "./SettingsExampleText.js";
8
+
9
+ type SettingsTabContentProps = ReactComponentProps<
10
+ SettingsViewPluginEvents,
11
+ SettingsViewPluginConstants,
12
+ SettingsViewPluginSettings,
13
+ SettingsViewPluginParams,
14
+ SettingsViewPluginState
15
+ > & {
16
+ isShow?: boolean;
17
+ isForce?: boolean;
18
+ locs?: Record<string, string>;
19
+ fields?: SettingsField[];
20
+ showTextExample?: boolean;
21
+ currentItem?: number | null;
22
+ currentItemInner?: number | null;
23
+ };
24
+
25
+ type SettingsItem = NonNullable<Parameters<typeof Settings>[0]["settings"]>[number];
26
+
27
+ export const SettingsTabContent = ({
28
+ isShow = false,
29
+ isForce = false,
30
+ locs = {},
31
+ fields = [],
32
+ showTextExample = false,
33
+ currentItem = null,
34
+ currentItemInner = null,
35
+ PARAMS,
36
+ emit,
37
+ EVENTS,
38
+ shared,
39
+ SETTINGS,
40
+ store,
41
+ onMount,
42
+ CONST,
43
+ }: SettingsTabContentProps) => {
44
+ const mapFields = useCallback(
45
+ ({
46
+ locKey = "",
47
+ type = "",
48
+ settingKey = "",
49
+ options = [],
50
+ titleToggledLocKey = "",
51
+ titleUntoggledLocKey = "",
52
+ valueMap = "",
53
+ ...fieldProps
54
+ }: SettingsField = {}) => {
55
+ const onChange = (value: unknown) => void emit(EVENTS.SETTINGS.SET, { name: settingKey, value });
56
+
57
+ const titles = { title: locs[locKey], titleToggled: locs[titleToggledLocKey], titleUntoggled: locs[titleUntoggledLocKey] };
58
+ const valueMapReal = valueMap ? PARAMS.SETTINGS_VIEW.VALUE_MAPS[valueMap] : null;
59
+
60
+ const optionsReal = options.map((option) => {
61
+ const result: Record<string, unknown> = { ...option };
62
+
63
+ if (option.locKey) {
64
+ delete result.locKey;
65
+ result.text = locs[option.locKey];
66
+ }
67
+
68
+ if (option.action) {
69
+ delete result.action;
70
+ result.onClick = () => PARAMS.SETTINGS_VIEW.ACTIONS[option.action!]({ emit, emitOne: emit, emitReal: emit }, locs);
71
+ }
72
+
73
+ return result;
74
+ });
75
+
76
+ return { ...titles, value: shared.settings[settingKey], type, onChange, props: fieldProps, options: optionsReal, valueMap: valueMapReal };
77
+ },
78
+ [EVENTS.SETTINGS.SET, PARAMS.SETTINGS_VIEW.ACTIONS, PARAMS.SETTINGS_VIEW.VALUE_MAPS, emit, locs, shared.settings],
79
+ );
80
+
81
+ // Do not memoize mapped settings: shared.settings is mutated in place on SETTINGS.CHANGED.
82
+ const propsSettings = {
83
+ ...PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldProps,
84
+ transition: isForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION,
85
+ settings: fields.map(mapFields) as SettingsItem[],
86
+ selectedIndex: isShow ? (currentItem ?? undefined) : -1,
87
+ selectedIndexInner: isShow ? (currentItemInner ?? undefined) : -1,
88
+ } as Parameters<typeof Settings>[0];
89
+
90
+ return (
91
+ <PositionBox
92
+ isCentered={true}
93
+ opacity={isShow ? 1 : 0}
94
+ transition={isForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION}
95
+ >
96
+ <Flex
97
+ direction={Flex.DIRECTION.COLUMN}
98
+ gap={PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldsGap}
99
+ >
100
+ <Settings {...propsSettings} />
101
+ {showTextExample && (
102
+ <SettingsExampleText
103
+ store={store}
104
+ onMount={onMount}
105
+ PARAMS={PARAMS}
106
+ emit={emit}
107
+ EVENTS={EVENTS}
108
+ shared={shared}
109
+ CONST={CONST}
110
+ SETTINGS={SETTINGS}
111
+ locs={locs}
112
+ isShow={isShow}
113
+ />
114
+ )}
115
+ </Flex>
116
+ </PositionBox>
117
+ );
118
+ };
@@ -0,0 +1,63 @@
1
+ import type { ViewRenderFunc } from "@vnejs/module.components";
2
+ import type { ReactComponentProps } from "@vnejs/uis.react";
3
+ import { View, createRenderFunc, useIsForceHook, useMemo, useStoreState } from "@vnejs/uis.react";
4
+
5
+ import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
6
+ import type { SettingsViewPluginState } from "../utils/settings.js";
7
+ import { SettingsTabContent } from "./SettingsTabContent.js";
8
+
9
+ type SettingsComponentProps = ReactComponentProps<
10
+ SettingsViewPluginEvents,
11
+ SettingsViewPluginConstants,
12
+ SettingsViewPluginSettings,
13
+ SettingsViewPluginParams,
14
+ SettingsViewPluginState
15
+ >;
16
+
17
+ const SettingsViewComponent = ({ store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS }: SettingsComponentProps) => {
18
+ const {
19
+ isShow = false,
20
+ isForce = false,
21
+ locs = {},
22
+ tabsContent = {},
23
+ tabKey = "",
24
+ currentItem = null,
25
+ currentItemInner = null,
26
+ } = useStoreState<SettingsViewPluginState>(store, onMount);
27
+
28
+ const isRealForce = useIsForceHook(isForce);
29
+
30
+ const propsByView = PARAMS.SETTINGS_VIEW.VIEW_PROPS;
31
+
32
+ const propsView = useMemo(
33
+ () => ({
34
+ ...propsByView.view,
35
+ isShow,
36
+ isForce: isRealForce,
37
+ transition: isRealForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION,
38
+ }),
39
+ [isShow, isRealForce, propsByView.view, PARAMS.SETTINGS_VIEW.TRANSITION],
40
+ );
41
+
42
+ const propsTab = useMemo(
43
+ () => ({ store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS, isForce: isRealForce, currentItem, currentItemInner, locs }),
44
+ [store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS, isRealForce, currentItem, currentItemInner, locs],
45
+ );
46
+
47
+ return (
48
+ <View {...propsView}>
49
+ {Object.entries(tabsContent).map(([key, content]) => (
50
+ <SettingsTabContent
51
+ {...propsTab}
52
+ key={key}
53
+ isShow={tabKey === key}
54
+ fields={content.fields}
55
+ showTextExample={content.showTextExample}
56
+ locs={content.locs ?? locs}
57
+ />
58
+ ))}
59
+ </View>
60
+ );
61
+ };
62
+
63
+ export const render: ViewRenderFunc<SettingsViewPluginState> = createRenderFunc(SettingsViewComponent);
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", "src/tests"]
10
+ }
package/const/events.js DELETED
@@ -1,7 +0,0 @@
1
- export const SUBSCRIBE_EVENTS = {
2
- SHOW: "vne:settings_view:show",
3
- HIDE: "vne:settings_view:hide",
4
- UPDATE: "vne:settings_view:update",
5
- PRELOAD: "vne:settings_view:preload",
6
- TAB_SET: "vne:settings_view:tab_set",
7
- };
package/const/params.js DELETED
@@ -1,43 +0,0 @@
1
- export const TRANSITION = 500;
2
- export const ZINDEX = 4000;
3
- export const LOC_LABEL = "settings";
4
-
5
- export const BACKGROUND = "save";
6
-
7
- export const TABS = {};
8
-
9
- export const VALUE_MAPS = {};
10
-
11
- export const VIEW_PROPS = {
12
- screen: { withBackgroundDark: true, withBackgroundBlur: false, transition: TRANSITION, zIndex: ZINDEX },
13
-
14
- background: { withDark: true, withBlur: false },
15
-
16
- cross: { position: { bottom: 90, right: 120 }, svg: { size: 60 } },
17
-
18
- exampleText: { size: 60, height: 300, color: "var(--vne-color-active)", transition: 300 },
19
-
20
- fieldsGap: 48,
21
-
22
- fieldProps: {
23
- widthTitle: 1440,
24
- width: 3120,
25
-
26
- sizeTitle: 96,
27
- sizeText: 72,
28
-
29
- gapBetweenItems: 48,
30
- gapBetweenTitleAndContent: 120,
31
- gapBetweenInnerItems: 120,
32
-
33
- rangeHeight: 24,
34
-
35
- widthInnerLeft: 960,
36
- widthInnerRight: 240,
37
- },
38
-
39
- controls: {
40
- position: { top: 90, left: 120 },
41
- props: { textWidth: 660, wrapWidth: 3600, flexGap: 36, flexWithWrap: false, textSize: 96, textAlign: "center" },
42
- },
43
- };
package/index.js DELETED
@@ -1,9 +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 { SettingsController } from "./modules/controller";
7
- import { SettingsView } from "./modules/view";
8
-
9
- regPlugin("SETTINGS_VIEW", { events: SUBSCRIBE_EVENTS, params }, [SettingsController, SettingsView]);
@@ -1,132 +0,0 @@
1
- import { ModuleController } from "@vnejs/module.components";
2
-
3
- const filterTabsToShow = ({ showInSettings = false }) => Boolean(showInSettings);
4
-
5
- export class SettingsController extends ModuleController {
6
- name = "settings.controller";
7
-
8
- emitHide = () => this.emit(this.EVENTS.SETTINGS_VIEW.HIDE);
9
-
10
- onArrowLeft = () => {
11
- const { currentTab, currentItemInner, currentItem } = this.state;
12
-
13
- if (currentItem === null) return;
14
-
15
- const { settingKey = "", step = 0, min = 0, type = "", options = [] } = this.tabs[currentTab].fields[currentItem];
16
-
17
- if (options?.length) {
18
- const newValue = (currentItemInner === 0 ? options.length : currentItemInner) - 1;
19
-
20
- return this.updateStateAndViewFast({ currentItemInner: newValue });
21
- }
22
-
23
- if (type === "toggle") {
24
- return this.shared.settings[settingKey] === true && this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: false });
25
- }
26
-
27
- if (type === "range") {
28
- const newValue = Number(Number(this.shared.settings[settingKey] - step).toFixed(4));
29
-
30
- return newValue >= min && this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: newValue });
31
- }
32
- };
33
-
34
- onArrowRight = () => {
35
- const { currentTab, currentItemInner, currentItem } = this.state;
36
-
37
- if (currentItem === null) return;
38
-
39
- const { settingKey = "", step = 0, max = 0, type = "", options = [] } = this.tabs[currentTab].fields[currentItem];
40
-
41
- if (options?.length) {
42
- return this.updateStateAndViewFast({ currentItemInner: (currentItemInner + 1) % options.length });
43
- }
44
-
45
- if (type === "toggle") {
46
- return this.shared.settings[settingKey] === false && this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: true });
47
- }
48
-
49
- if (type === "range") {
50
- const newValue = Number(Number(this.shared.settings[settingKey] + step).toFixed(4));
51
-
52
- return newValue <= max && this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: newValue });
53
- }
54
- };
55
-
56
- onPrevTab = () => this.emit(this.EVENTS.SETTINGS_VIEW.TAB_SET, { tab: (this.state.currentTab === 0 ? this.tabs.length : this.state.currentTab) - 1 });
57
- onNextTab = () => this.emit(this.EVENTS.SETTINGS_VIEW.TAB_SET, { tab: (this.state.currentTab + 1) % this.tabs.length });
58
-
59
- onInteract = () => {
60
- const { currentTab, currentItemInner, currentItem } = this.state;
61
-
62
- if (currentItem === null) return;
63
-
64
- const { settingKey = "", type = "", options = [] } = this.tabs[currentTab].fields[currentItem];
65
-
66
- if (options?.length)
67
- return options[currentItemInner].action
68
- ? this.PARAMS.SETTINGS_VIEW.ACTIONS[options[currentItemInner].action](this, this.state.locs)
69
- : this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: options[currentItemInner].value });
70
-
71
- if (type === "toggle") return this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: !this.shared.settings[settingKey] });
72
- };
73
-
74
- bgName = this.PARAMS.SETTINGS_VIEW.BACKGROUND;
75
-
76
- updateEvent = this.EVENTS.SETTINGS_VIEW.UPDATE;
77
- controls = {
78
- [this.CONST.CONTROLS.BUTTONS.BACK]: this.emitHide,
79
- [this.CONST.CONTROLS.BUTTONS.MENU]: this.emitHide,
80
- [this.CONST.CONTROLS.BUTTONS.GAMEMENU]: this.emitHide,
81
- [this.CONST.CONTROLS.BUTTONS.INTERACT]: this.onInteract,
82
- [this.CONST.CONTROLS.BUTTONS.ACCEPT]: this.onInteract,
83
- [this.CONST.CONTROLS.BUTTONS.TAB_PREV]: this.onPrevTab,
84
- [this.CONST.CONTROLS.BUTTONS.TAB_NEXT]: this.onNextTab,
85
- [this.CONST.CONTROLS.BUTTONS.ARROW_LEFT]: this.onArrowLeft,
86
- [this.CONST.CONTROLS.BUTTONS.ARROW_RIGHT]: this.onArrowRight,
87
- [this.CONST.CONTROLS.BUTTONS.ARROW_UP]: this.decCurrentItem,
88
- [this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: this.incCurrentItem,
89
- };
90
- controlsIndex = this.PARAMS.SETTINGS_VIEW.ZINDEX;
91
-
92
- subscribe = () => {
93
- this.on(this.EVENTS.SETTINGS_VIEW.SHOW, this.onShow);
94
- this.on(this.EVENTS.SETTINGS_VIEW.HIDE, this.onHide);
95
- this.on(this.EVENTS.SETTINGS_VIEW.TAB_SET, this.onTabSet);
96
- this.on(this.EVENTS.SETTINGS_VIEW.PRELOAD, this.loadBgMedia);
97
-
98
- this.on(this.EVENTS.SETTINGS.CHANGED, this.onSettingChange);
99
-
100
- this.on(this.EVENTS.LOCS.CHANGED, this.updateViewFast);
101
-
102
- this.on(this.EVENTS.STATE.SET, this.onHide);
103
- this.on(this.EVENTS.STATE.CLEAR, this.onHide);
104
-
105
- this.on(this.EVENTS.MEMORY.CLEARED, this.onMemoryCleared);
106
- };
107
- init = () => {
108
- this.tabs = Object.values(this.PARAMS.SETTINGS_VIEW.TABS).filter(filterTabsToShow);
109
-
110
- this.setMaxCurrentItemByTabIndex(0);
111
-
112
- return this.emit(this.EVENTS.SETTINGS.INIT);
113
- };
114
-
115
- beforeShow = async () => this.updateState({ bgSrc: (await this.loadBgMedia()).src, tabs: this.tabs, currentTab: 0 });
116
- afterHide = () => this.setDefaultState();
117
-
118
- onSettingChange = () => this.isReady && this.state.isShow && this.updateViewFast();
119
-
120
- onTabSet = ({ tab = 0 } = {}) => {
121
- this.setMaxCurrentItemByTabIndex(tab);
122
- this.unsetCurrentItem();
123
-
124
- return this.updateStateAndViewFast({ currentTab: tab, currentItemInner: 0 });
125
- };
126
-
127
- onMemoryCleared = async () => this.updateStateAndViewFast({ bgSrc: (await this.loadBgMedia()).src });
128
-
129
- setMaxCurrentItemByTabIndex = (i) => {
130
- this.maxCurrentItem = this.tabs[i].fields.length - 1;
131
- };
132
- }
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 SettingsView extends ModuleView {
6
- name = "settings.view";
7
-
8
- locLabel = this.PARAMS.SETTINGS_VIEW.LOC_LABEL;
9
- animationTime = this.PARAMS.SETTINGS_VIEW.TRANSITION;
10
- updateEvent = this.EVENTS.SETTINGS_VIEW.UPDATE;
11
-
12
- renderFunc = render;
13
- updateHandler = this.onUpdateStoreComponent;
14
- }
@@ -1,22 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
2
-
3
- import { PositionBox, TextControls } from "@vnejs/uis.react";
4
-
5
- export const SettingsControls = ({ tabs = [], locs = {}, currentTab = 0, ...props } = {}) => {
6
- const [texts, setTexts] = useState();
7
-
8
- useEffect(() => void setTexts(Object.values(tabs).map(({ titleLocKey }, i) => ({ value: i, text: locs[titleLocKey] }))), [locs, tabs]);
9
-
10
- const onClick = useCallback((tab) => props.emit(props.EVENTS.SETTINGS_VIEW.TAB_SET, { tab }), []);
11
-
12
- const propsControls = useMemo(
13
- () => ({ ...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.controls.props, selectedIndex: currentTab, texts, onClick }),
14
- [currentTab, texts],
15
- );
16
-
17
- return (
18
- <PositionBox {...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.controls.position}>
19
- <TextControls {...propsControls} />
20
- </PositionBox>
21
- );
22
- };
@@ -1,13 +0,0 @@
1
- import { useMemo } from "react";
2
-
3
- import { PositionBox, Svg } from "@vnejs/uis.react";
4
-
5
- export const SettingsCross = (props = {}) => {
6
- const propsCross = useMemo(() => ({ ...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.cross.svg, onClick: () => props.emit(props.EVENTS.SETTINGS_VIEW.HIDE) }), []);
7
-
8
- return (
9
- <PositionBox {...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.cross.position}>
10
- <Svg.Cross {...propsCross} />
11
- </PositionBox>
12
- );
13
- };
@@ -1,40 +0,0 @@
1
- import { useEffect, useMemo, useState } from "react";
2
-
3
- import { SmoothText } from "@vnejs/uis.react";
4
-
5
- import { tokenizeText } from "@vnejs/helpers";
6
-
7
- const EMPTY_ARRAY = [];
8
-
9
- export const SettingsExampleText = ({ isShow = false, locs = {}, ...props } = {}) => {
10
- const [tokens, setTokens] = useState(EMPTY_ARRAY);
11
-
12
- const isForce = Boolean(props.shared.textNoAnimationSources.length);
13
-
14
- const text = useMemo(() => locs["fields.text.example"] ?? "", [locs]);
15
-
16
- useEffect(() => {
17
- if (isShow) setTokens(tokenizeText(text));
18
- }, [isShow, text]);
19
-
20
- useEffect(() => {
21
- if (isShow || isForce) return;
22
-
23
- const tm = setTimeout(() => setTokens(EMPTY_ARRAY), props.PARAMS.SETTINGS_VIEW.TRANSITION);
24
-
25
- return () => clearTimeout(tm);
26
- }, [isShow]);
27
-
28
- return (
29
- <SmoothText
30
- tokens={tokens}
31
- isForce={isForce}
32
- charDelay={props.PARAMS.TEXT.TOKEN_RENDER_DELAY / props.shared.settings[props.SETTINGS.TEXT.TOKEN_RENDER_SPEED]}
33
- transition={props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.transition}
34
- size={props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.size}
35
- color={props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.color}
36
- height={props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.height}
37
- scrollBarTextSize={props.shared.settings[props.SETTINGS.TEXTSIZE.VALUE]}
38
- />
39
- );
40
- };
@@ -1,66 +0,0 @@
1
- import { useCallback } from "react";
2
-
3
- import { PositionBox, Settings, Flex } from "@vnejs/uis.react";
4
-
5
- import { SettingsExampleText } from "./SettingsExampleText";
6
-
7
- export const SettingsTabContent = ({ isShow = false, isForce = false, locs = {}, fields = [], ...props } = {}) => {
8
- const mapFields = useCallback(
9
- ({ locKey = "", type = "", settingKey = "", options = [], titleToggledLocKey = "", titleUntoggledLocKey = "", valueMap = "", ...fieldProps } = {}) => {
10
- const onChange = (value) => props.emit(props.EVENTS.SETTINGS.SET, { name: settingKey, value });
11
-
12
- const titles = { title: locs[locKey], titleToggled: locs[titleToggledLocKey], titleUntoggled: locs[titleUntoggledLocKey] };
13
- const valueMapReal = valueMap ? props.PARAMS.SETTINGS_VIEW.VALUE_MAPS[valueMap] : null;
14
-
15
- const optionsReal = options.map((option) => {
16
- const result = { ...option };
17
-
18
- if (option.locKey) {
19
- delete result.locKey;
20
- result.text = locs[option.locKey];
21
- }
22
-
23
- if (option.action) {
24
- delete result.action;
25
- result.onClick = () => props.PARAMS.SETTINGS_VIEW.ACTIONS[option.action](props, locs);
26
- }
27
-
28
- return result;
29
- });
30
-
31
- return { ...titles, value: props.shared.settings[settingKey], type, onChange, props: fieldProps, options: optionsReal, valueMap: valueMapReal };
32
- },
33
- [locs],
34
- );
35
-
36
- return (
37
- <PositionBox
38
- isCentered={true}
39
- opacity={isShow ? 1 : 0}
40
- transition={isForce ? 0 : props.PARAMS.SETTINGS_VIEW.TRANSITION}
41
- >
42
- <Flex
43
- direction={Flex.DIRECTION.COLUMN}
44
- gap={props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldsGap}
45
- >
46
- <Settings
47
- selectedIndex={isShow ? props.currentItem : -1}
48
- selectedIndexInner={isShow ? props.currentItemInner : -1}
49
- transition={isForce ? 0 : props.PARAMS.SETTINGS_VIEW.TRANSITION}
50
- settings={fields.map(mapFields)}
51
- {...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldProps}
52
- />
53
-
54
- {props.showTextExample && (
55
- <SettingsExampleText
56
- {...props}
57
- locs={locs}
58
- isShow={isShow}
59
- isForce={isForce}
60
- text={locs["fields.text.example"] || ""}
61
- />
62
- )}
63
- </Flex>
64
- </PositionBox>
65
- );
66
- };
@@ -1,4 +0,0 @@
1
- export * from "./SettingsControls";
2
- export * from "./SettingsCross";
3
- export * from "./SettingsExampleText";
4
- export * from "./SettingsTabContent";
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 { Screen } from "@vnejs/uis.react";
5
-
6
- import { SettingsControls, SettingsCross, SettingsTabContent } from "./components";
7
-
8
- const Settings = ({ store, onMount, ...props } = {}) => {
9
- const [state, setState] = useState({});
10
-
11
- const { isShow = false, isForce = false, bgSrc = "", tabs = [], locs = {}, currentTab = 0, currentItem = null, currentItemInner = null } = state;
12
-
13
- useEffect(() => store.subscribe(setState), []);
14
- useEffect(() => void onMount(), []);
15
-
16
- const propsTab = useMemo(() => ({ ...props, isForce, currentItem, currentItemInner, locs }), [isForce, currentItem, currentItemInner, locs]);
17
- const propsScreen = useMemo(() => ({ ...props.PARAMS.SETTINGS_VIEW.VIEW_PROPS.screen, isShow, isForce, bgSrc }), [isShow, isForce, bgSrc]);
18
- const propsControls = useMemo(() => ({ ...props, locs, tabs, currentTab, isForce }), [locs, tabs, currentTab, isForce]);
19
-
20
- const renderTabContent = useCallback(
21
- ({ fields = [], showTextExample = false } = {}, i) => (
22
- <SettingsTabContent
23
- {...propsTab}
24
- key={i}
25
- isShow={currentTab === i}
26
- fields={fields}
27
- showTextExample={showTextExample}
28
- />
29
- ),
30
- [currentTab, propsTab],
31
- );
32
-
33
- return (
34
- <Screen {...propsScreen}>
35
- <SettingsCross {...props} />
36
- <SettingsControls {...propsControls} />
37
- {Object.values(tabs).map(renderTabContent)}
38
- </Screen>
39
- );
40
- };
41
-
42
- export const render = (props, root) => createRoot(root).render(<Settings {...props} />);