@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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/modules/controller.d.ts +44 -0
- package/dist/modules/controller.js +169 -0
- package/dist/modules/view.d.ts +11 -0
- package/dist/modules/view.js +10 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.js +1 -0
- package/dist/utils/settings.d.ts +25 -0
- package/dist/utils/settings.js +1 -0
- package/dist/view/SettingsExampleText.d.ts +9 -0
- package/dist/view/SettingsExampleText.js +25 -0
- package/dist/view/SettingsTabContent.d.ts +15 -0
- package/dist/view/SettingsTabContent.js +32 -0
- package/dist/view/index.d.ts +3 -0
- package/dist/view/index.js +18 -0
- package/package.json +52 -7
- package/src/index.ts +9 -0
- package/src/modules/controller.ts +221 -0
- package/src/modules/view.ts +22 -0
- package/src/tests/controller.test.ts +240 -0
- package/src/tests/setup.ts +44 -0
- package/src/types.ts +20 -0
- package/src/utils/settings.ts +28 -0
- package/src/view/SettingsExampleText.tsx +61 -0
- package/src/view/SettingsTabContent.tsx +118 -0
- package/src/view/index.tsx +63 -0
- package/tsconfig.json +10 -0
- package/const/events.js +0 -7
- package/const/params.js +0 -43
- package/index.js +0 -9
- package/modules/controller.js +0 -132
- package/modules/view.js +0 -14
- package/view/components/SettingsControls.jsx +0 -22
- package/view/components/SettingsCross.jsx +0 -13
- package/view/components/SettingsExampleText.jsx +0 -40
- package/view/components/SettingsTabContent.jsx +0 -66
- package/view/components/index.js +0 -4
- package/view/index.jsx +0 -42
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "@vnejs/contracts.views.settings";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import "@vnejs/contracts.views.settings";
|
|
2
|
+
import { regPlugin } from "@vnejs/shared";
|
|
3
|
+
import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/contracts.views.settings";
|
|
4
|
+
import { SettingsViewController } from "./modules/controller.js";
|
|
5
|
+
import { SettingsView } from "./modules/view.js";
|
|
6
|
+
regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [SettingsViewController, SettingsView]);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ModuleController } from "@vnejs/module.components";
|
|
2
|
+
import type { SettingsField } from "@vnejs/contracts.views.settings";
|
|
3
|
+
import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
|
|
4
|
+
import type { SettingsViewPluginState, SettingsViewTabContent, SettingsViewTabPayload } from "../utils/settings.js";
|
|
5
|
+
export declare class SettingsViewController extends ModuleController<SettingsViewPluginEvents, SettingsViewPluginConstants, SettingsViewPluginSettings, SettingsViewPluginParams, SettingsViewPluginState> {
|
|
6
|
+
name: string;
|
|
7
|
+
updateEvent: "vne:settings_view:update";
|
|
8
|
+
controlsIndex: number;
|
|
9
|
+
tabKeyOf: ({ tabKey, tab }?: SettingsViewTabPayload) => string;
|
|
10
|
+
tabContentOf: (tab: SettingsViewTabPayload["tab"], locs?: Record<string, string>) => SettingsViewTabContent;
|
|
11
|
+
applyTab: (payload?: SettingsViewTabPayload) => {
|
|
12
|
+
tab: import("@vnejs/contracts.views.settings").SettingsTab | undefined;
|
|
13
|
+
tabKey: string;
|
|
14
|
+
tabsContent: {
|
|
15
|
+
[k: string]: SettingsViewTabContent;
|
|
16
|
+
};
|
|
17
|
+
fields: SettingsField[];
|
|
18
|
+
locs: Record<string, string> | undefined;
|
|
19
|
+
showTextExample: boolean;
|
|
20
|
+
currentItemInner: number;
|
|
21
|
+
};
|
|
22
|
+
onShowFields: (payload?: SettingsViewTabPayload) => Promise<void>;
|
|
23
|
+
onTabSet: (payload?: SettingsViewTabPayload) => Promise<void | unknown[]>;
|
|
24
|
+
getFocusedField: () => SettingsField | undefined;
|
|
25
|
+
innerIndexOfField: (field?: SettingsField) => number;
|
|
26
|
+
optionIndexOf: (length: number, index?: number) => number;
|
|
27
|
+
shiftOptions: (direction: -1 | 1) => void;
|
|
28
|
+
setCurrentItem: (value: number, defaultValue: number) => Promise<void>;
|
|
29
|
+
onArrowLeft: () => void | false;
|
|
30
|
+
onArrowRight: () => void | false;
|
|
31
|
+
onInteract: () => void;
|
|
32
|
+
controls: {
|
|
33
|
+
abstract_interact: () => undefined;
|
|
34
|
+
abstract_arrow_left: () => undefined;
|
|
35
|
+
abstract_arrow_right: () => undefined;
|
|
36
|
+
abstract_arrow_up: () => Promise<void>;
|
|
37
|
+
abstract_arrow_bottom: () => Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
controlsCheckNext: boolean;
|
|
40
|
+
subscribe: () => void;
|
|
41
|
+
beforeShow: (payload?: SettingsViewTabPayload) => Promise<void>;
|
|
42
|
+
afterHide: () => void;
|
|
43
|
+
onSettingChange: () => false | Promise<unknown[]> | undefined;
|
|
44
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ModuleController } from "@vnejs/module.components";
|
|
2
|
+
export class SettingsViewController extends ModuleController {
|
|
3
|
+
name = "settings.fields.controller";
|
|
4
|
+
updateEvent = this.EVENTS.SETTINGS_VIEW.UPDATE;
|
|
5
|
+
controlsIndex = this.PARAMS.SETTINGS_VIEW.ZINDEX;
|
|
6
|
+
tabKeyOf = ({ tabKey, tab } = {}) => tabKey || tab?.titleLocKey || "default";
|
|
7
|
+
tabContentOf = (tab, locs) => ({
|
|
8
|
+
fields: tab?.fields ?? [],
|
|
9
|
+
showTextExample: Boolean(tab?.showTextExample),
|
|
10
|
+
locs,
|
|
11
|
+
});
|
|
12
|
+
applyTab = (payload = {}) => {
|
|
13
|
+
const { tab, locs } = payload;
|
|
14
|
+
const fields = tab?.fields ?? [];
|
|
15
|
+
const key = this.tabKeyOf(payload);
|
|
16
|
+
this.maxCurrentItem = Math.max((fields.length ?? 1) - 1, 0);
|
|
17
|
+
const tabsContent = payload.tabs
|
|
18
|
+
? Object.fromEntries(Object.entries(payload.tabs).map(([tabKey, settingsTab]) => [tabKey, this.tabContentOf(settingsTab, locs)]))
|
|
19
|
+
: { ...(this.state.tabsContent ?? {}), [key]: this.tabContentOf(tab, locs) };
|
|
20
|
+
return {
|
|
21
|
+
tab,
|
|
22
|
+
tabKey: key,
|
|
23
|
+
tabsContent,
|
|
24
|
+
fields,
|
|
25
|
+
locs,
|
|
26
|
+
showTextExample: Boolean(tab?.showTextExample),
|
|
27
|
+
currentItemInner: 0,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
onShowFields = (payload = {}) => this.onShow(payload);
|
|
31
|
+
onTabSet = async (payload = {}) => {
|
|
32
|
+
if (!this.state.isShow)
|
|
33
|
+
return this.onShow(payload);
|
|
34
|
+
const isForce = Boolean(payload.isForce || this.shared.viewForceAnimationSources?.isNotEmpty());
|
|
35
|
+
this.currentItem = null;
|
|
36
|
+
const next = { ...this.applyTab(payload), currentItem: null };
|
|
37
|
+
if (isForce)
|
|
38
|
+
return this.updateStateAndViewForce(next);
|
|
39
|
+
const key = next.tabKey;
|
|
40
|
+
const alreadyMounted = Boolean(this.state.tabsContent?.[key]);
|
|
41
|
+
// Mount the incoming tab at opacity 0 first so CSS can crossfade both layers together.
|
|
42
|
+
if (!alreadyMounted) {
|
|
43
|
+
await this.updateStateAndViewFast({ tabsContent: next.tabsContent });
|
|
44
|
+
await this.waitRerender();
|
|
45
|
+
}
|
|
46
|
+
return this.updateStateAndView(next);
|
|
47
|
+
};
|
|
48
|
+
getFocusedField = () => {
|
|
49
|
+
const { currentItem, fields = [] } = this.state;
|
|
50
|
+
if (currentItem == null || !fields.length)
|
|
51
|
+
return;
|
|
52
|
+
return fields[currentItem];
|
|
53
|
+
};
|
|
54
|
+
innerIndexOfField = (field) => {
|
|
55
|
+
const options = field?.options ?? [];
|
|
56
|
+
if (!options.length)
|
|
57
|
+
return 0;
|
|
58
|
+
const settingKey = field?.settingKey;
|
|
59
|
+
if (!settingKey)
|
|
60
|
+
return 0;
|
|
61
|
+
const index = options.findIndex((option) => option.value === this.shared.settings[settingKey]);
|
|
62
|
+
return index >= 0 ? index : 0;
|
|
63
|
+
};
|
|
64
|
+
optionIndexOf = (length, index = 0) => {
|
|
65
|
+
if (!length)
|
|
66
|
+
return 0;
|
|
67
|
+
return ((index % length) + length) % length;
|
|
68
|
+
};
|
|
69
|
+
shiftOptions = (direction) => {
|
|
70
|
+
const field = this.getFocusedField();
|
|
71
|
+
const options = field?.options ?? [];
|
|
72
|
+
if (!options.length)
|
|
73
|
+
return;
|
|
74
|
+
const currentItemInner = this.optionIndexOf(options.length, (this.state.currentItemInner ?? 0) + direction);
|
|
75
|
+
const option = options[currentItemInner];
|
|
76
|
+
const settingKey = field?.settingKey;
|
|
77
|
+
void this.updateStateAndViewFast({ currentItemInner });
|
|
78
|
+
if (settingKey && option && !option.action) {
|
|
79
|
+
void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: option.value });
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
setCurrentItem = async (value, defaultValue) => {
|
|
83
|
+
if (this.currentItem === null) {
|
|
84
|
+
this.currentItem = defaultValue;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.currentItem = value;
|
|
88
|
+
if (this.currentItem > this.maxCurrentItem)
|
|
89
|
+
this.currentItem = 0;
|
|
90
|
+
if (this.currentItem < 0)
|
|
91
|
+
this.currentItem = this.maxCurrentItem;
|
|
92
|
+
}
|
|
93
|
+
const currentItemInner = this.innerIndexOfField(this.state.fields?.[this.currentItem]);
|
|
94
|
+
await this.updateStateAndViewFast({ currentItem: this.currentItem, currentItemInner });
|
|
95
|
+
};
|
|
96
|
+
onArrowLeft = () => {
|
|
97
|
+
const field = this.getFocusedField();
|
|
98
|
+
if (!field)
|
|
99
|
+
return;
|
|
100
|
+
if (field.options?.length)
|
|
101
|
+
return this.shiftOptions(-1);
|
|
102
|
+
const { settingKey = "", step = 0, min = 0, type = "" } = field;
|
|
103
|
+
if (!settingKey)
|
|
104
|
+
return;
|
|
105
|
+
if (type === "toggle") {
|
|
106
|
+
return this.shared.settings[settingKey] === true && void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: false });
|
|
107
|
+
}
|
|
108
|
+
if (type === "range") {
|
|
109
|
+
const newValue = Number(Number(Number(this.shared.settings[settingKey]) - step).toFixed(4));
|
|
110
|
+
return newValue >= min && void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: newValue });
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
onArrowRight = () => {
|
|
114
|
+
const field = this.getFocusedField();
|
|
115
|
+
if (!field)
|
|
116
|
+
return;
|
|
117
|
+
if (field.options?.length)
|
|
118
|
+
return this.shiftOptions(1);
|
|
119
|
+
const { settingKey = "", step = 0, max = 0, type = "" } = field;
|
|
120
|
+
if (!settingKey)
|
|
121
|
+
return;
|
|
122
|
+
if (type === "toggle") {
|
|
123
|
+
return this.shared.settings[settingKey] === false && void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: true });
|
|
124
|
+
}
|
|
125
|
+
if (type === "range") {
|
|
126
|
+
const newValue = Number(Number(Number(this.shared.settings[settingKey]) + step).toFixed(4));
|
|
127
|
+
return newValue <= max && void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: newValue });
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
onInteract = () => {
|
|
131
|
+
const field = this.getFocusedField();
|
|
132
|
+
if (!field)
|
|
133
|
+
return;
|
|
134
|
+
const { settingKey = "", type = "", options = [] } = field;
|
|
135
|
+
const { locs = {} } = this.state;
|
|
136
|
+
if (options?.length) {
|
|
137
|
+
const option = options[this.optionIndexOf(options.length, this.state.currentItemInner ?? 0)];
|
|
138
|
+
if (!option)
|
|
139
|
+
return;
|
|
140
|
+
if (option.action)
|
|
141
|
+
return this.PARAMS.SETTINGS_VIEW.ACTIONS[option.action](this, locs);
|
|
142
|
+
if (settingKey)
|
|
143
|
+
return void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: option.value });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!settingKey)
|
|
147
|
+
return;
|
|
148
|
+
if (type === "toggle")
|
|
149
|
+
return void this.emit(this.EVENTS.SETTINGS.SET, { name: settingKey, value: !this.shared.settings[settingKey] });
|
|
150
|
+
};
|
|
151
|
+
controls = {
|
|
152
|
+
[this.CONST.CONTROLS.BUTTONS.INTERACT]: () => void this.onInteract(),
|
|
153
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_LEFT]: () => void this.onArrowLeft(),
|
|
154
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_RIGHT]: () => void this.onArrowRight(),
|
|
155
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_UP]: this.decCurrentItem,
|
|
156
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: this.incCurrentItem,
|
|
157
|
+
};
|
|
158
|
+
controlsCheckNext = true;
|
|
159
|
+
subscribe = () => {
|
|
160
|
+
this.on(this.EVENTS.SETTINGS_VIEW.SHOW, this.onShowFields);
|
|
161
|
+
this.on(this.EVENTS.SETTINGS_VIEW.HIDE, this.onHide);
|
|
162
|
+
this.on(this.EVENTS.SETTINGS_VIEW.TAB_SET, this.onTabSet);
|
|
163
|
+
this.on(this.EVENTS.SETTINGS.CHANGED, this.onSettingChange);
|
|
164
|
+
this.on(this.EVENTS.COMPONENTS.EXTERNAL_UPDATE, this.onSettingChange);
|
|
165
|
+
};
|
|
166
|
+
beforeShow = async (payload = {}) => this.updateState(this.applyTab(payload));
|
|
167
|
+
afterHide = () => this.setDefaultState();
|
|
168
|
+
onSettingChange = () => this.state.isShow && this.updateViewFast();
|
|
169
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ModuleView } from "@vnejs/module.components";
|
|
2
|
+
import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
|
|
3
|
+
import type { SettingsViewPluginState } from "../utils/settings.js";
|
|
4
|
+
export declare class SettingsView extends ModuleView<SettingsViewPluginEvents, SettingsViewPluginConstants, SettingsViewPluginSettings, SettingsViewPluginParams, SettingsViewPluginState> {
|
|
5
|
+
name: string;
|
|
6
|
+
locLabel: string;
|
|
7
|
+
animationTime: number;
|
|
8
|
+
updateEvent: "vne:settings_view:update";
|
|
9
|
+
renderFunc: import("@vnejs/module.components").ViewRenderFunc<SettingsViewPluginState>;
|
|
10
|
+
updateHandler: (state?: SettingsViewPluginState | 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 SettingsView extends ModuleView {
|
|
4
|
+
name = "settings.fields.view";
|
|
5
|
+
locLabel = this.PARAMS.SETTINGS_VIEW.LOC_LABEL;
|
|
6
|
+
animationTime = this.PARAMS.SETTINGS_VIEW.TRANSITION;
|
|
7
|
+
updateEvent = this.EVENTS.SETTINGS_VIEW.UPDATE;
|
|
8
|
+
renderFunc = render;
|
|
9
|
+
updateHandler = this.onUpdateStoreComponent;
|
|
10
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
|
|
2
|
+
import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/contracts.controls";
|
|
3
|
+
import type { PluginName as SettingsPluginName, SubscribeEvents as SettingsSubscribeEvents } from "@vnejs/contracts.core.settings";
|
|
4
|
+
import type { SettingsKeys as TextsizeSettingsKeys, PluginName as TextsizePluginName } from "@vnejs/contracts.settings.textsize";
|
|
5
|
+
import type { Params as TextSmoothParams, PluginName as TextSmoothPluginName, SettingsKeys as TextSmoothSettingsKeys } from "@vnejs/contracts.text.smooth";
|
|
6
|
+
import type { Params, PluginName, SubscribeEvents } from "@vnejs/contracts.views.settings";
|
|
7
|
+
export type SettingsViewPluginEvents = ModuleComponentsEvents & Record<PluginName, SubscribeEvents> & Record<SettingsPluginName, SettingsSubscribeEvents>;
|
|
8
|
+
export type SettingsViewPluginConstants = ModuleComponentsConstants & Record<ControlsPluginName, ControlsConstants>;
|
|
9
|
+
export type SettingsViewPluginSettings = ModuleComponentsSettings & Record<TextSmoothPluginName, TextSmoothSettingsKeys> & Record<TextsizePluginName, TextsizeSettingsKeys>;
|
|
10
|
+
export type SettingsViewPluginParams = ModuleComponentsParams & Record<PluginName, Params> & Record<TextSmoothPluginName, TextSmoothParams>;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SettingsField, SettingsTab } from "@vnejs/contracts.views.settings";
|
|
2
|
+
export type SettingsViewTabContent = {
|
|
3
|
+
fields?: SettingsField[];
|
|
4
|
+
showTextExample?: boolean;
|
|
5
|
+
locs?: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
export type SettingsViewPluginState = {
|
|
8
|
+
isShow: boolean;
|
|
9
|
+
isForce: boolean;
|
|
10
|
+
tab?: SettingsTab;
|
|
11
|
+
tabKey?: string;
|
|
12
|
+
tabsContent?: Record<string, SettingsViewTabContent>;
|
|
13
|
+
fields?: SettingsField[];
|
|
14
|
+
locs?: Record<string, string>;
|
|
15
|
+
showTextExample?: boolean;
|
|
16
|
+
currentItem?: number | null;
|
|
17
|
+
currentItemInner?: number | null;
|
|
18
|
+
};
|
|
19
|
+
export type SettingsViewTabPayload = {
|
|
20
|
+
tab?: SettingsTab;
|
|
21
|
+
tabs?: Record<string, SettingsTab>;
|
|
22
|
+
tabKey?: string;
|
|
23
|
+
locs?: Record<string, string>;
|
|
24
|
+
isForce?: boolean;
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactComponentProps } from "@vnejs/uis.react";
|
|
2
|
+
import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
|
|
3
|
+
import type { SettingsViewPluginState } from "../utils/settings.js";
|
|
4
|
+
type SettingsExampleTextProps = ReactComponentProps<SettingsViewPluginEvents, SettingsViewPluginConstants, SettingsViewPluginSettings, SettingsViewPluginParams, SettingsViewPluginState> & {
|
|
5
|
+
isShow?: boolean;
|
|
6
|
+
locs?: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
export declare const SettingsExampleText: ({ isShow, locs, PARAMS, shared, SETTINGS }: SettingsExampleTextProps) => import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { tokenizeText } from "@vnejs/helpers";
|
|
3
|
+
import { SmoothText, useEffect, useMemo, useState } from "@vnejs/uis.react";
|
|
4
|
+
export const SettingsExampleText = ({ isShow = false, locs = {}, PARAMS, shared, SETTINGS }) => {
|
|
5
|
+
const [tokens, setTokens] = useState([]);
|
|
6
|
+
const isForce = shared.textProcessSkipSources.isNotEmpty();
|
|
7
|
+
const text = useMemo(() => locs["fields.text.example"] ?? "", [locs]);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (isShow)
|
|
10
|
+
setTokens(tokenizeText(text));
|
|
11
|
+
}, [isShow, text]);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
setTokens((prev) => (prev.length ? [...prev] : prev));
|
|
14
|
+
}, [isForce]);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (isShow || isForce)
|
|
17
|
+
return;
|
|
18
|
+
const tm = setTimeout(() => setTokens([]), PARAMS.SETTINGS_VIEW.TRANSITION);
|
|
19
|
+
return () => clearTimeout(tm);
|
|
20
|
+
}, [isShow, isForce, PARAMS.SETTINGS_VIEW.TRANSITION]);
|
|
21
|
+
const charDelay = isForce
|
|
22
|
+
? 0
|
|
23
|
+
: PARAMS.TEXT_SMOOTH.TOKEN_RENDER_DELAY / Number(shared.settings[SETTINGS.TEXT_SMOOTH.TOKEN_RENDER_SPEED]);
|
|
24
|
+
return (_jsx(SmoothText, { tokens: tokens, isForce: isForce, charDelay: charDelay, tokensVisibleForce: isForce ? tokens.length : null, transition: PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.transition, size: PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.size, color: PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.color, height: PARAMS.SETTINGS_VIEW.VIEW_PROPS.exampleText.height, scrollBarTextSize: Number(shared.settings[SETTINGS.TEXTSIZE.VALUE]) }));
|
|
25
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SettingsField } from "@vnejs/contracts.views.settings";
|
|
2
|
+
import type { ReactComponentProps } from "@vnejs/uis.react";
|
|
3
|
+
import type { SettingsViewPluginConstants, SettingsViewPluginEvents, SettingsViewPluginParams, SettingsViewPluginSettings } from "../types.js";
|
|
4
|
+
import type { SettingsViewPluginState } from "../utils/settings.js";
|
|
5
|
+
type SettingsTabContentProps = ReactComponentProps<SettingsViewPluginEvents, SettingsViewPluginConstants, SettingsViewPluginSettings, SettingsViewPluginParams, SettingsViewPluginState> & {
|
|
6
|
+
isShow?: boolean;
|
|
7
|
+
isForce?: boolean;
|
|
8
|
+
locs?: Record<string, string>;
|
|
9
|
+
fields?: SettingsField[];
|
|
10
|
+
showTextExample?: boolean;
|
|
11
|
+
currentItem?: number | null;
|
|
12
|
+
currentItemInner?: number | null;
|
|
13
|
+
};
|
|
14
|
+
export declare const SettingsTabContent: ({ isShow, isForce, locs, fields, showTextExample, currentItem, currentItemInner, PARAMS, emit, EVENTS, shared, SETTINGS, store, onMount, CONST, }: SettingsTabContentProps) => import("react").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Flex, PositionBox, Settings, useCallback } from "@vnejs/uis.react";
|
|
3
|
+
import { SettingsExampleText } from "./SettingsExampleText.js";
|
|
4
|
+
export const SettingsTabContent = ({ isShow = false, isForce = false, locs = {}, fields = [], showTextExample = false, currentItem = null, currentItemInner = null, PARAMS, emit, EVENTS, shared, SETTINGS, store, onMount, CONST, }) => {
|
|
5
|
+
const mapFields = useCallback(({ locKey = "", type = "", settingKey = "", options = [], titleToggledLocKey = "", titleUntoggledLocKey = "", valueMap = "", ...fieldProps } = {}) => {
|
|
6
|
+
const onChange = (value) => void emit(EVENTS.SETTINGS.SET, { name: settingKey, value });
|
|
7
|
+
const titles = { title: locs[locKey], titleToggled: locs[titleToggledLocKey], titleUntoggled: locs[titleUntoggledLocKey] };
|
|
8
|
+
const valueMapReal = valueMap ? PARAMS.SETTINGS_VIEW.VALUE_MAPS[valueMap] : null;
|
|
9
|
+
const optionsReal = options.map((option) => {
|
|
10
|
+
const result = { ...option };
|
|
11
|
+
if (option.locKey) {
|
|
12
|
+
delete result.locKey;
|
|
13
|
+
result.text = locs[option.locKey];
|
|
14
|
+
}
|
|
15
|
+
if (option.action) {
|
|
16
|
+
delete result.action;
|
|
17
|
+
result.onClick = () => PARAMS.SETTINGS_VIEW.ACTIONS[option.action]({ emit, emitOne: emit, emitReal: emit }, locs);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
});
|
|
21
|
+
return { ...titles, value: shared.settings[settingKey], type, onChange, props: fieldProps, options: optionsReal, valueMap: valueMapReal };
|
|
22
|
+
}, [EVENTS.SETTINGS.SET, PARAMS.SETTINGS_VIEW.ACTIONS, PARAMS.SETTINGS_VIEW.VALUE_MAPS, emit, locs, shared.settings]);
|
|
23
|
+
// Do not memoize mapped settings: shared.settings is mutated in place on SETTINGS.CHANGED.
|
|
24
|
+
const propsSettings = {
|
|
25
|
+
...PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldProps,
|
|
26
|
+
transition: isForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION,
|
|
27
|
+
settings: fields.map(mapFields),
|
|
28
|
+
selectedIndex: isShow ? (currentItem ?? undefined) : -1,
|
|
29
|
+
selectedIndexInner: isShow ? (currentItemInner ?? undefined) : -1,
|
|
30
|
+
};
|
|
31
|
+
return (_jsx(PositionBox, { isCentered: true, opacity: isShow ? 1 : 0, transition: isForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION, children: _jsxs(Flex, { direction: Flex.DIRECTION.COLUMN, gap: PARAMS.SETTINGS_VIEW.VIEW_PROPS.fieldsGap, children: [_jsx(Settings, { ...propsSettings }), showTextExample && (_jsx(SettingsExampleText, { store: store, onMount: onMount, PARAMS: PARAMS, emit: emit, EVENTS: EVENTS, shared: shared, CONST: CONST, SETTINGS: SETTINGS, locs: locs, isShow: isShow }))] }) }));
|
|
32
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createElement as _createElement } from "react";
|
|
3
|
+
import { View, createRenderFunc, useIsForceHook, useMemo, useStoreState } from "@vnejs/uis.react";
|
|
4
|
+
import { SettingsTabContent } from "./SettingsTabContent.js";
|
|
5
|
+
const SettingsViewComponent = ({ store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS }) => {
|
|
6
|
+
const { isShow = false, isForce = false, locs = {}, tabsContent = {}, tabKey = "", currentItem = null, currentItemInner = null, } = useStoreState(store, onMount);
|
|
7
|
+
const isRealForce = useIsForceHook(isForce);
|
|
8
|
+
const propsByView = PARAMS.SETTINGS_VIEW.VIEW_PROPS;
|
|
9
|
+
const propsView = useMemo(() => ({
|
|
10
|
+
...propsByView.view,
|
|
11
|
+
isShow,
|
|
12
|
+
isForce: isRealForce,
|
|
13
|
+
transition: isRealForce ? 0 : PARAMS.SETTINGS_VIEW.TRANSITION,
|
|
14
|
+
}), [isShow, isRealForce, propsByView.view, PARAMS.SETTINGS_VIEW.TRANSITION]);
|
|
15
|
+
const propsTab = useMemo(() => ({ store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS, isForce: isRealForce, currentItem, currentItemInner, locs }), [store, onMount, PARAMS, emit, EVENTS, shared, CONST, SETTINGS, isRealForce, currentItem, currentItemInner, locs]);
|
|
16
|
+
return (_jsx(View, { ...propsView, children: Object.entries(tabsContent).map(([key, content]) => (_createElement(SettingsTabContent, { ...propsTab, key: key, isShow: tabKey === key, fields: content.fields, showTextExample: content.showTextExample, locs: content.locs ?? locs }))) }));
|
|
17
|
+
};
|
|
18
|
+
export const render = createRenderFunc(SettingsViewComponent);
|
package/package.json
CHANGED
|
@@ -1,17 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vnejs/plugins.views.settings",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.2.2",
|
|
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
|
-
"test": "
|
|
21
|
+
"test": "npx @vnejs/monorepo test",
|
|
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": "
|
|
11
|
-
"publish:minor": "
|
|
12
|
-
"publish:patch": "
|
|
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
|
-
"
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@vnejs/contracts.views.settings": "~0.2.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@vnejs/helpers": "~0.2.0",
|
|
37
|
+
"@vnejs/module.core": "~0.2.0",
|
|
38
|
+
"@vnejs/module.components": "~0.2.0",
|
|
39
|
+
"@vnejs/contracts.controls": "~0.2.0",
|
|
40
|
+
"@vnejs/contracts.core.settings": "~0.2.0",
|
|
41
|
+
"@vnejs/contracts.settings.textsize": "~0.2.0",
|
|
42
|
+
"@vnejs/contracts.text.smooth": "~0.2.0",
|
|
43
|
+
"@vnejs/shared": "~0.2.0",
|
|
44
|
+
"@vnejs/uis.react": "~0.2.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@vnejs/configs.ts-common": "~0.2.0",
|
|
48
|
+
"@vnejs/configs.vitest": "~0.2.0",
|
|
49
|
+
"@vnejs/test-utils": "~0.2.0",
|
|
50
|
+
"@vnejs/contracts.controls": "~0.2.0",
|
|
51
|
+
"@vnejs/contracts.core.settings": "~0.2.0",
|
|
52
|
+
"@vnejs/contracts.settings.textsize": "~0.2.0",
|
|
53
|
+
"@vnejs/contracts.text.smooth": "~0.2.0",
|
|
54
|
+
"@vnejs/contracts.views.settings": "~0.2.0",
|
|
55
|
+
"@vnejs/helpers": "~0.2.0",
|
|
56
|
+
"@vnejs/module.core": "~0.2.0",
|
|
57
|
+
"@vnejs/module.components": "~0.2.0",
|
|
58
|
+
"@vnejs/shared": "~0.2.0",
|
|
59
|
+
"@vnejs/sources-set": "~0.2.0",
|
|
60
|
+
"@vnejs/uis.react": "~0.2.0"
|
|
61
|
+
}
|
|
17
62
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "@vnejs/contracts.views.settings";
|
|
2
|
+
|
|
3
|
+
import { regPlugin } from "@vnejs/shared";
|
|
4
|
+
import { PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/contracts.views.settings";
|
|
5
|
+
|
|
6
|
+
import { SettingsViewController } from "./modules/controller.js";
|
|
7
|
+
import { SettingsView } from "./modules/view.js";
|
|
8
|
+
|
|
9
|
+
regPlugin(PLUGIN_NAME, { events: SUBSCRIBE_EVENTS, params: PARAMS }, [SettingsViewController, SettingsView]);
|