@caperjs/core 0.2.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/assetpack.mjs +90 -0
- package/build/index.mjs +3 -1
- package/build/internal/discovery.mjs +1 -1
- package/build/internal/manifest.mjs +8 -3
- package/build/internal/validate.mjs +3 -1
- package/build/plugins/assetTypes.mjs +4 -4
- package/build/plugins/caperConfig.mjs +12 -5
- package/build/plugins/lists.mjs +29 -9
- package/build/plugins/pruneFallbacks.mjs +25 -2
- package/cli/create.mjs +57 -6
- package/cli/create.test.mjs +36 -0
- package/cli/update.mjs +1 -1
- package/lib/{CaptionsPlugin-WPAcfAkx.js → CaptionsPlugin-cSJj-R9M.js} +5 -5
- package/lib/{CaptionsPlugin-WPAcfAkx.js.map → CaptionsPlugin-cSJj-R9M.js.map} +1 -1
- package/lib/{DataAdapter-DS-twowe.js → DataAdapter-D2tc6hx9.js} +15 -10
- package/lib/DataAdapter-D2tc6hx9.js.map +1 -0
- package/lib/{DebugRenderer-D1ryrRYx.js → DebugRenderer-CGUKy6Fy.js} +2 -2
- package/lib/{DebugRenderer-D1ryrRYx.js.map → DebugRenderer-CGUKy6Fy.js.map} +1 -1
- package/lib/{DevToolsPlugin-DH7zX7HU.js → DevToolsPlugin-B8GX3H9b.js} +2 -2
- package/lib/{DevToolsPlugin-DH7zX7HU.js.map → DevToolsPlugin-B8GX3H9b.js.map} +1 -1
- package/lib/{GSAPPlugin-BBtRjUqe.js → GSAPPlugin-Br9AjuTD.js} +6 -6
- package/lib/{GSAPPlugin-BBtRjUqe.js.map → GSAPPlugin-Br9AjuTD.js.map} +1 -1
- package/lib/{LayoutPlugin-Co6vcoV4.js → LayoutPlugin-BX3OP7pw.js} +4 -4
- package/lib/{LayoutPlugin-Co6vcoV4.js.map → LayoutPlugin-BX3OP7pw.js.map} +1 -1
- package/lib/{SpinePlugin-uN641Hmk.js → SpinePlugin-C-JDdXpf.js} +690 -793
- package/lib/SpinePlugin-C-JDdXpf.js.map +1 -0
- package/lib/{StatsPlugin-vZQRm6wh.js → StatsPlugin-yJlJtoQ2.js} +7 -7
- package/lib/StatsPlugin-yJlJtoQ2.js.map +1 -0
- package/lib/{VoiceOverPlugin-KlZdGj1G.js → VoiceOverPlugin-DjSZp4Ko.js} +7 -6
- package/lib/VoiceOverPlugin-DjSZp4Ko.js.map +1 -0
- package/lib/caper.mjs +159 -1917
- package/lib/caper.mjs.map +1 -1
- package/lib/const-C3sxeYhl.js +1746 -0
- package/lib/const-C3sxeYhl.js.map +1 -0
- package/lib/core/Application.d.ts +8 -3
- package/lib/core/Application.d.ts.map +1 -1
- package/lib/core/Application.test.d.ts +2 -0
- package/lib/core/Application.test.d.ts.map +1 -0
- package/lib/core/config.d.ts +6 -1
- package/lib/core/config.d.ts.map +1 -1
- package/lib/core/config.test.d.ts +2 -0
- package/lib/core/config.test.d.ts.map +1 -0
- package/lib/core/create.d.ts.map +1 -1
- package/lib/core/interfaces/IApplication.d.ts +6 -6
- package/lib/core/interfaces/IApplication.d.ts.map +1 -1
- package/lib/core/interfaces/ICoreSignals.d.ts +2 -1
- package/lib/core/interfaces/ICoreSignals.d.ts.map +1 -1
- package/lib/display/Camera.test.d.ts +2 -0
- package/lib/display/Camera.test.d.ts.map +1 -0
- package/lib/display/Entity.d.ts +2 -2
- package/lib/display/SceneTransition.test.d.ts +1 -0
- package/lib/display/SceneTransition.test.d.ts.map +1 -0
- package/lib/display/SpineAnimation.d.ts +3 -3
- package/lib/mixins/factory/methods.d.ts.map +1 -1
- package/lib/padding-1kHDpGlQ.js +41 -0
- package/lib/padding-1kHDpGlQ.js.map +1 -0
- package/lib/plugins/AssetsPlugin.d.ts.map +1 -1
- package/lib/plugins/AssetsPlugin.test.d.ts +2 -0
- package/lib/plugins/AssetsPlugin.test.d.ts.map +1 -0
- package/lib/plugins/DataAdapter.d.ts.map +1 -1
- package/lib/plugins/DataAdapter.test.d.ts +2 -0
- package/lib/plugins/DataAdapter.test.d.ts.map +1 -0
- package/lib/plugins/FullScreenPlugin.d.ts +0 -5
- package/lib/plugins/FullScreenPlugin.d.ts.map +1 -1
- package/lib/plugins/FullScreenPlugin.test.d.ts +2 -0
- package/lib/plugins/FullScreenPlugin.test.d.ts.map +1 -0
- package/lib/plugins/GSAPPlugin.d.ts +0 -2
- package/lib/plugins/GSAPPlugin.d.ts.map +1 -1
- package/lib/plugins/GSAPPlugin.test.d.ts +2 -0
- package/lib/plugins/GSAPPlugin.test.d.ts.map +1 -0
- package/lib/plugins/KeyboardPlugin.d.ts +0 -1
- package/lib/plugins/KeyboardPlugin.d.ts.map +1 -1
- package/lib/plugins/LookupPlugin.d.ts +6 -1
- package/lib/plugins/LookupPlugin.d.ts.map +1 -1
- package/lib/plugins/LookupPlugin.test.d.ts +2 -0
- package/lib/plugins/LookupPlugin.test.d.ts.map +1 -0
- package/lib/plugins/Plugin.d.ts +101 -2
- package/lib/plugins/Plugin.d.ts.map +1 -1
- package/lib/plugins/PopupManagerPlugin.d.ts.map +1 -1
- package/lib/plugins/PopupManagerPlugin.test.d.ts +1 -0
- package/lib/plugins/PopupManagerPlugin.test.d.ts.map +1 -0
- package/lib/plugins/SceneManagerPlugin.d.ts +1 -1
- package/lib/plugins/SceneManagerPlugin.d.ts.map +1 -1
- package/lib/plugins/SceneManagerPlugin.test.d.ts +2 -0
- package/lib/plugins/SceneManagerPlugin.test.d.ts.map +1 -0
- package/lib/plugins/StatsPlugin.d.ts.map +1 -1
- package/lib/plugins/TimerPlugin.d.ts.map +1 -1
- package/lib/plugins/WebEventsPlugin.d.ts +0 -1
- package/lib/plugins/WebEventsPlugin.d.ts.map +1 -1
- package/lib/plugins/actions/ActionsPlugin.test.d.ts +2 -0
- package/lib/plugins/actions/ActionsPlugin.test.d.ts.map +1 -0
- package/lib/plugins/audio/AudioChannel.d.ts.map +1 -1
- package/lib/plugins/audio/AudioManagerPlugin.d.ts.map +1 -1
- package/lib/plugins/audio/AudioManagerPlugin.test.d.ts +2 -0
- package/lib/plugins/audio/AudioManagerPlugin.test.d.ts.map +1 -0
- package/lib/plugins/audio/VoiceOverPlugin.d.ts.map +1 -1
- package/lib/plugins/breakpoints/BreakpointPlugin.d.ts.map +1 -1
- package/lib/plugins/captions/CaptionsPlugin.test.d.ts +2 -0
- package/lib/plugins/captions/CaptionsPlugin.test.d.ts.map +1 -0
- package/lib/plugins/focus/FocusManagerPlugin.d.ts.map +1 -1
- package/lib/plugins/focus/FocusManagerPlugin.test.d.ts +2 -0
- package/lib/plugins/focus/FocusManagerPlugin.test.d.ts.map +1 -0
- package/lib/plugins/gesture/GesturePlugin.d.ts.map +1 -1
- package/lib/plugins/input/AbstractControls.d.ts +47 -3
- package/lib/plugins/input/AbstractControls.d.ts.map +1 -1
- package/lib/plugins/input/Controls.test.d.ts +2 -0
- package/lib/plugins/input/Controls.test.d.ts.map +1 -0
- package/lib/plugins/input/InputPlugin.d.ts.map +1 -1
- package/lib/plugins/input/controlsCore.d.ts +58 -0
- package/lib/plugins/input/controlsCore.d.ts.map +1 -0
- package/lib/plugins/input/controlsCore.test.d.ts +2 -0
- package/lib/plugins/input/controlsCore.test.d.ts.map +1 -0
- package/lib/plugins/input/keyboard/KeyboardControls.d.ts +15 -0
- package/lib/plugins/input/keyboard/KeyboardControls.d.ts.map +1 -0
- package/lib/plugins/input/keyboard/index.d.ts +1 -1
- package/lib/plugins/input/keyboard/index.d.ts.map +1 -1
- package/lib/plugins/input/touch/VirtualControls.d.ts +8 -14
- package/lib/plugins/input/touch/VirtualControls.d.ts.map +1 -1
- package/lib/plugins/input/touch/VirtualControls.test.d.ts +2 -0
- package/lib/plugins/input/touch/VirtualControls.test.d.ts.map +1 -0
- package/lib/{registries-BLrxALZ0.js → registries-BfV-VF7a.js} +665 -597
- package/lib/registries-BfV-VF7a.js.map +1 -0
- package/lib/store/Store.d.ts.map +1 -1
- package/lib/ui/Button.d.ts.map +1 -1
- package/lib/ui/UICanvas.d.ts +10 -1
- package/lib/ui/UICanvas.d.ts.map +1 -1
- package/lib/ui/UICanvas.test.d.ts +0 -1
- package/lib/ui/UICanvas.test.d.ts.map +1 -1
- package/lib/utils/color.d.ts.map +1 -1
- package/lib/utils/color.test.d.ts +2 -0
- package/lib/utils/color.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/core/Application.test.ts +168 -0
- package/src/core/Application.ts +37 -27
- package/src/core/config.test.ts +79 -0
- package/src/core/config.ts +28 -6
- package/src/core/create.ts +11 -0
- package/src/core/interfaces/IApplication.ts +6 -6
- package/src/core/interfaces/ICoreSignals.ts +2 -0
- package/src/display/Camera.test.ts +40 -0
- package/src/display/Camera.ts +3 -3
- package/src/display/Entity.ts +2 -2
- package/src/display/SceneTransition.test.ts +58 -0
- package/src/display/SceneTransition.ts +1 -1
- package/src/display/SpineAnimation.ts +4 -4
- package/src/mixins/factory/methods.ts +0 -1
- package/src/plugins/AssetsPlugin.test.ts +48 -0
- package/src/plugins/AssetsPlugin.ts +3 -1
- package/src/plugins/DataAdapter.test.ts +32 -0
- package/src/plugins/DataAdapter.ts +5 -1
- package/src/plugins/FullScreenPlugin.test.ts +48 -0
- package/src/plugins/FullScreenPlugin.ts +9 -18
- package/src/plugins/GSAPPlugin.test.ts +31 -0
- package/src/plugins/GSAPPlugin.ts +1 -4
- package/src/plugins/KeyboardPlugin.ts +3 -10
- package/src/plugins/LookupPlugin.test.ts +42 -0
- package/src/plugins/LookupPlugin.ts +15 -3
- package/src/plugins/Plugin.test.ts +130 -2
- package/src/plugins/Plugin.ts +159 -3
- package/src/plugins/PopupManagerPlugin.test.ts +53 -0
- package/src/plugins/PopupManagerPlugin.ts +5 -3
- package/src/plugins/SceneManagerPlugin.test.ts +76 -0
- package/src/plugins/SceneManagerPlugin.ts +18 -13
- package/src/plugins/StatsPlugin.ts +3 -2
- package/src/plugins/TimerPlugin.ts +1 -2
- package/src/plugins/WebEventsPlugin.test.ts +32 -0
- package/src/plugins/WebEventsPlugin.ts +9 -16
- package/src/plugins/actions/ActionsPlugin.test.ts +68 -0
- package/src/plugins/actions/ActionsPlugin.ts +5 -5
- package/src/plugins/audio/AudioChannel.test.ts +19 -0
- package/src/plugins/audio/AudioChannel.ts +8 -1
- package/src/plugins/audio/AudioManagerPlugin.test.ts +41 -0
- package/src/plugins/audio/AudioManagerPlugin.ts +3 -2
- package/src/plugins/audio/VoiceOverPlugin.ts +1 -0
- package/src/plugins/breakpoints/BreakpointPlugin.ts +1 -2
- package/src/plugins/captions/CaptionsPlugin.test.ts +40 -0
- package/src/plugins/captions/CaptionsPlugin.ts +2 -2
- package/src/plugins/focus/FocusManagerPlugin.test.ts +71 -0
- package/src/plugins/focus/FocusManagerPlugin.ts +7 -0
- package/src/plugins/gesture/GesturePlugin.ts +4 -8
- package/src/plugins/input/AbstractControls.ts +104 -3
- package/src/plugins/input/Controls.test.ts +205 -0
- package/src/plugins/input/InputPlugin.ts +6 -14
- package/src/plugins/input/controlsCore.test.ts +151 -0
- package/src/plugins/input/controlsCore.ts +162 -0
- package/src/plugins/input/keyboard/KeyboardControls.ts +84 -0
- package/src/plugins/input/keyboard/index.ts +1 -1
- package/src/plugins/input/touch/VirtualControls.test.ts +38 -0
- package/src/plugins/input/touch/VirtualControls.ts +53 -120
- package/src/plugins/spine/SpinePlugin.ts +2 -2
- package/src/store/Store.test.ts +15 -0
- package/src/store/Store.ts +4 -1
- package/src/ui/Button.test.ts +12 -0
- package/src/ui/Button.ts +1 -0
- package/src/ui/UICanvas.test.ts +109 -6
- package/src/ui/UICanvas.ts +41 -3
- package/src/utils/color.test.ts +16 -0
- package/src/utils/color.ts +2 -1
- package/src/utils/platform.ts +1 -1
- package/src/version.ts +1 -1
- package/lib/DataAdapter-DS-twowe.js.map +0 -1
- package/lib/SpinePlugin-uN641Hmk.js.map +0 -1
- package/lib/StatsPlugin-vZQRm6wh.js.map +0 -1
- package/lib/VoiceOverPlugin-KlZdGj1G.js.map +0 -1
- package/lib/plugins/input/keyboard/KeyboardContols.d.ts +0 -28
- package/lib/plugins/input/keyboard/KeyboardContols.d.ts.map +0 -1
- package/lib/registries-BLrxALZ0.js.map +0 -1
- package/src/plugins/input/keyboard/KeyboardContols.ts +0 -182
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import { bindAllMethods } from '../../../utils';
|
|
2
|
-
import type { ControlsActionMap, JoystickControlsScheme, TouchControlsMap
|
|
2
|
+
import type { ControlsActionMap, JoystickControlsScheme, TouchControlsMap } from '../types';
|
|
3
3
|
|
|
4
4
|
import { JoystickDirection } from '..';
|
|
5
|
-
import {
|
|
6
|
-
import { WithSignals } from '../../../mixins/signals';
|
|
5
|
+
import type { SignalConnection } from '../../../signals';
|
|
7
6
|
import type { IButton, IJoystick } from '../../../ui';
|
|
8
7
|
import type { Action } from '../../actions';
|
|
9
8
|
import { AbstractControls } from '../AbstractControls';
|
|
9
|
+
import { evaluateCombinations } from '../controlsCore';
|
|
10
10
|
|
|
11
|
-
export class VirtualControls extends
|
|
11
|
+
export class VirtualControls extends AbstractControls {
|
|
12
12
|
protected scheme: Partial<TouchControlsMap>;
|
|
13
|
+
protected readonly logLabel = 'VirtualControls';
|
|
13
14
|
private _buttons: Set<IButton> = new Set();
|
|
14
|
-
private _joystickMap: Partial<JoystickControlsScheme>;
|
|
15
|
-
private _buttonDownMap: Partial<TouchControlsScheme>;
|
|
16
|
-
private _buttonUpMap: Partial<TouchControlsScheme>;
|
|
17
|
-
private _combinations: string[][] = [];
|
|
18
15
|
private _singleDownButtons: Set<string> = new Set();
|
|
19
16
|
private _activeJoystickDirections: Map<JoystickDirection, Action> = new Map();
|
|
20
|
-
private
|
|
21
|
-
private _activeButtonUpIds: Map<string, Action> = new Map();
|
|
22
|
-
private _combinationsMap: Map<string[], Action> = new Map();
|
|
17
|
+
private _buttonConnections: Map<IButton, SignalConnection[]> = new Map();
|
|
23
18
|
|
|
24
19
|
constructor() {
|
|
25
20
|
super();
|
|
@@ -36,20 +31,18 @@ export class VirtualControls extends WithSignals(AbstractControls) {
|
|
|
36
31
|
this._joystick = value;
|
|
37
32
|
}
|
|
38
33
|
|
|
39
|
-
get app() {
|
|
40
|
-
return Application.getInstance();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
34
|
addButton(button: IButton) {
|
|
44
35
|
if (!button || this._buttons.has(button)) {
|
|
45
36
|
return;
|
|
46
37
|
}
|
|
47
|
-
|
|
38
|
+
const connections = [
|
|
48
39
|
button.onDown.connect(() => this._handleButtonDown(button)),
|
|
49
40
|
button.onUp.connect(() => this._handleButtonUp(button)),
|
|
50
41
|
button.onUpOutside.connect(() => this._handleButtonUp(button)),
|
|
51
42
|
button.onDestroy.connect(() => this.removeButton(button)),
|
|
52
|
-
|
|
43
|
+
];
|
|
44
|
+
this.addSignalConnection(...connections);
|
|
45
|
+
this._buttonConnections.set(button, connections);
|
|
53
46
|
this._buttons.add(button);
|
|
54
47
|
}
|
|
55
48
|
|
|
@@ -57,104 +50,49 @@ export class VirtualControls extends WithSignals(AbstractControls) {
|
|
|
57
50
|
if (!button || !this._buttons.has(button)) {
|
|
58
51
|
return;
|
|
59
52
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
// signals disconnect by identity — disconnect the connections made in addButton
|
|
54
|
+
this._buttonConnections.get(button)?.forEach((connection) => connection.disconnect());
|
|
55
|
+
this._buttonConnections.delete(button);
|
|
56
|
+
this._singleDownButtons.delete(button.id!);
|
|
64
57
|
this._buttons.delete(button);
|
|
65
58
|
}
|
|
66
59
|
|
|
67
60
|
public initialize(scheme: Partial<TouchControlsMap>): void {
|
|
68
61
|
super.initialize(scheme as Partial<ControlsActionMap>);
|
|
69
|
-
this._buttonDownMap = scheme.down || {};
|
|
70
|
-
this._buttonUpMap = scheme.up || {};
|
|
71
|
-
this._joystickMap = scheme.joystick || {};
|
|
72
|
-
this.app.signal.onActionContextChanged.connect(this._sortActions);
|
|
73
|
-
this._sortActions();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public connect() {
|
|
77
|
-
this.app.ticker.add(this._update);
|
|
78
62
|
}
|
|
79
63
|
|
|
80
64
|
isActionActive(action: Action): boolean {
|
|
81
65
|
const buttonAction = this.scheme['down']?.[action] ?? null;
|
|
82
66
|
if (buttonAction) {
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
return super.isActionActive(action);
|
|
68
|
+
}
|
|
69
|
+
const joystickAction = this.scheme['joystick']?.[action] ?? null;
|
|
70
|
+
if (this._joystick && joystickAction) {
|
|
71
|
+
if (Array.isArray(joystickAction)) {
|
|
72
|
+
return joystickAction.includes(this._joystick.direction);
|
|
85
73
|
} else {
|
|
86
|
-
return this.
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
const joystickAction = this.scheme['joystick']?.[action] ?? null;
|
|
90
|
-
if (this._joystick && joystickAction) {
|
|
91
|
-
if (Array.isArray(joystickAction)) {
|
|
92
|
-
return joystickAction.includes(this._joystick.direction);
|
|
93
|
-
} else {
|
|
94
|
-
return joystickAction === this._joystick?.direction;
|
|
95
|
-
}
|
|
74
|
+
return joystickAction === this._joystick?.direction;
|
|
96
75
|
}
|
|
97
76
|
}
|
|
98
77
|
return false;
|
|
99
78
|
}
|
|
100
79
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this._combinationsMap.clear();
|
|
105
|
-
this._activeJoystickDirections.clear();
|
|
106
|
-
this._activeButtonDownIds.clear();
|
|
107
|
-
this._activeButtonUpIds.clear();
|
|
108
|
-
|
|
109
|
-
let buttons = Object.keys(this._buttonDownMap);
|
|
110
|
-
buttons.forEach((key) => {
|
|
111
|
-
const item = this._buttonDownMap[key];
|
|
112
|
-
const action = actions[key];
|
|
113
|
-
if (
|
|
114
|
-
action.context !== '*' &&
|
|
115
|
-
action.context !== this.app.actionContext &&
|
|
116
|
-
!action.context.includes(this.app.actionContext)
|
|
117
|
-
) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
let input = item;
|
|
121
|
-
if (input) {
|
|
122
|
-
if (!Array.isArray(input)) {
|
|
123
|
-
input = [input];
|
|
124
|
-
}
|
|
125
|
-
input.forEach((inputString) => {
|
|
126
|
-
if (inputString.includes('+')) {
|
|
127
|
-
const combo = inputString.split('+');
|
|
128
|
-
this._combinations.push(combo);
|
|
129
|
-
this._combinationsMap.set(combo, key as Action);
|
|
130
|
-
} else {
|
|
131
|
-
this._activeButtonDownIds.set(inputString, key as Action);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
});
|
|
80
|
+
protected isInputDown(id: string): boolean {
|
|
81
|
+
return this._singleDownButtons.has(id);
|
|
82
|
+
}
|
|
136
83
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
buttons.forEach((key) => {
|
|
142
|
-
const item = this._buttonUpMap[key];
|
|
143
|
-
const action = actions[key];
|
|
144
|
-
if (
|
|
145
|
-
action.context !== '*' &&
|
|
146
|
-
action.context !== this.app.actionContext &&
|
|
147
|
-
!action.context.includes(this.app.actionContext)
|
|
148
|
-
) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
this._activeButtonUpIds.set(item as string, key as Action);
|
|
152
|
-
});
|
|
84
|
+
/** A joystick direction can take part in a combination, but never stands alone. */
|
|
85
|
+
protected isComboPartDown(id: string): boolean {
|
|
86
|
+
return this._singleDownButtons.has(id) || this._joystick?.direction === id;
|
|
87
|
+
}
|
|
153
88
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
89
|
+
protected _sortActions(): void {
|
|
90
|
+
super._sortActions();
|
|
91
|
+
|
|
92
|
+
this._activeJoystickDirections.clear();
|
|
93
|
+
const joystickMap: Partial<JoystickControlsScheme> = this.scheme.joystick || {};
|
|
94
|
+
Object.keys(joystickMap).forEach((key) => {
|
|
95
|
+
let input = joystickMap[key];
|
|
158
96
|
if (input) {
|
|
159
97
|
if (!Array.isArray(input)) {
|
|
160
98
|
input = [input];
|
|
@@ -172,7 +110,7 @@ export class VirtualControls extends WithSignals(AbstractControls) {
|
|
|
172
110
|
|
|
173
111
|
private _handleButtonUp(button: IButton): void {
|
|
174
112
|
this._singleDownButtons.delete(button.id!);
|
|
175
|
-
const action = this.
|
|
113
|
+
const action = this.activeUpInputs.get(button.id!);
|
|
176
114
|
if (action) {
|
|
177
115
|
this.app.action(action, {
|
|
178
116
|
combination: false,
|
|
@@ -182,30 +120,25 @@ export class VirtualControls extends WithSignals(AbstractControls) {
|
|
|
182
120
|
}
|
|
183
121
|
}
|
|
184
122
|
|
|
185
|
-
|
|
123
|
+
protected _update() {
|
|
186
124
|
const joystickDirection = this._joystick?.direction ?? null;
|
|
187
125
|
const buttonsDown = this._singleDownButtons;
|
|
188
|
-
|
|
189
|
-
// this.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
button: combination,
|
|
203
|
-
combination: true,
|
|
204
|
-
inputState: 'down',
|
|
205
|
-
});
|
|
206
|
-
}
|
|
126
|
+
|
|
127
|
+
// this.combinations is already sorted from largest to smallest
|
|
128
|
+
const { fired, eliminated } = evaluateCombinations(
|
|
129
|
+
this.combinations,
|
|
130
|
+
(key) => buttonsDown.has(key) || joystickDirection === key,
|
|
131
|
+
);
|
|
132
|
+
fired.forEach((combination) => {
|
|
133
|
+
const action = this.combinationsMap.get(combination);
|
|
134
|
+
if (action) {
|
|
135
|
+
this.app.action(action, {
|
|
136
|
+
button: combination,
|
|
137
|
+
combination: true,
|
|
138
|
+
inputState: 'down',
|
|
139
|
+
});
|
|
207
140
|
}
|
|
208
|
-
}
|
|
141
|
+
});
|
|
209
142
|
|
|
210
143
|
// order doesn't matter here
|
|
211
144
|
this._singleDownButtons.forEach((id) => {
|
|
@@ -213,7 +146,7 @@ export class VirtualControls extends WithSignals(AbstractControls) {
|
|
|
213
146
|
return;
|
|
214
147
|
}
|
|
215
148
|
if (buttonsDown.has(id)) {
|
|
216
|
-
const action = this.
|
|
149
|
+
const action = this.activeDownInputs.get(id);
|
|
217
150
|
if (action) {
|
|
218
151
|
this.app.action(action, {
|
|
219
152
|
button: id,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { extensions } from 'pixi.js';
|
|
2
2
|
import { Plugin } from '../Plugin';
|
|
3
|
-
import { Spine, spineLoaderExtension,
|
|
3
|
+
import { Spine, spineLoaderExtension, spineTextureAtlasLoader } from './pixi-spine';
|
|
4
4
|
|
|
5
5
|
export class SpinePlugin extends Plugin {
|
|
6
6
|
public readonly id = 'SpinePlugin';
|
|
@@ -8,7 +8,7 @@ export class SpinePlugin extends Plugin {
|
|
|
8
8
|
public async initialize() {
|
|
9
9
|
extensions.add(spineTextureAtlasLoader);
|
|
10
10
|
extensions.add(spineLoaderExtension);
|
|
11
|
-
|
|
11
|
+
// SpinePipe and DarkTintBatcher register themselves at module scope in ./pixi-spine
|
|
12
12
|
(window as any).Spine = Spine;
|
|
13
13
|
}
|
|
14
14
|
}
|
package/src/store/Store.test.ts
CHANGED
|
@@ -143,4 +143,19 @@ describe('Store', () => {
|
|
|
143
143
|
expect(saveA).toHaveBeenCalledWith('k', 1);
|
|
144
144
|
expect(saveB).toHaveBeenCalledWith('k', 1);
|
|
145
145
|
});
|
|
146
|
+
|
|
147
|
+
it('save with "*" anywhere in an adapter array fans out to every storage-capable plugin', async () => {
|
|
148
|
+
const saveA = vi.fn(async () => 'a');
|
|
149
|
+
const saveB = vi.fn(async () => 'b');
|
|
150
|
+
const store = new Store().initialize(
|
|
151
|
+
makeApp([
|
|
152
|
+
{ id: 'a', save: saveA, load: async () => undefined },
|
|
153
|
+
{ id: 'b', save: saveB, load: async () => undefined },
|
|
154
|
+
{ id: 'c' }, // not storage-capable → must be skipped
|
|
155
|
+
]),
|
|
156
|
+
);
|
|
157
|
+
await store.save(['a', '*'] as never, 'k', 1);
|
|
158
|
+
expect(saveA).toHaveBeenCalledWith('k', 1);
|
|
159
|
+
expect(saveB).toHaveBeenCalledWith('k', 1);
|
|
160
|
+
});
|
|
146
161
|
});
|
package/src/store/Store.ts
CHANGED
|
@@ -126,7 +126,10 @@ export class Store implements IStore {
|
|
|
126
126
|
keys = adapterId as string[] | Partial<AdapterSaveConfig>[];
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
const hasStarKey = keys.some(
|
|
130
|
+
(k) => (k as string) === '*' || (k as Partial<AdapterSaveConfig>)?.adapterId === '*',
|
|
131
|
+
);
|
|
132
|
+
if (hasStarKey) {
|
|
130
133
|
keys = this.allAdapterIds();
|
|
131
134
|
}
|
|
132
135
|
|
package/src/ui/Button.test.ts
CHANGED
|
@@ -147,6 +147,18 @@ describe('Button press-state machine', () => {
|
|
|
147
147
|
expect(onClick).toHaveBeenCalledTimes(1);
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
+
it('dispatches a click action with no data without throwing, attaching the button to the payload', () => {
|
|
151
|
+
const button = makeButton();
|
|
152
|
+
(button as any).config.actions = { click: { id: 'foo' } };
|
|
153
|
+
const action = vi.fn();
|
|
154
|
+
Object.defineProperty(button, 'app', { value: { action }, configurable: true });
|
|
155
|
+
|
|
156
|
+
(button as any).handlePointerDown({ pointerId: 1 });
|
|
157
|
+
expect(() => (button as any).handleClick({ pointerId: 1 })).not.toThrow();
|
|
158
|
+
|
|
159
|
+
expect(action).toHaveBeenCalledWith('foo', { button });
|
|
160
|
+
});
|
|
161
|
+
|
|
150
162
|
it('still clicks for a synthetic keyboard activation (no pointerId)', () => {
|
|
151
163
|
const button = makeButton();
|
|
152
164
|
const onClick = vi.fn();
|
package/src/ui/Button.ts
CHANGED
package/src/ui/UICanvas.test.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { Container as PIXIContainer } from 'pixi.js';
|
|
2
3
|
|
|
3
4
|
// UICanvas transitively imports Application → Pixi display graph. Stub it — the
|
|
4
|
-
// pure padding helper needs none of it.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
// pure padding helper needs none of it. The "element reordering" describe block
|
|
6
|
+
// below constructs real UICanvas instances, which internally build FlexContainer
|
|
7
|
+
// and Container children; those classes read `Application.getInstance()` for
|
|
8
|
+
// their own `app` getter (independent of UICanvas's own `app` override), so the
|
|
9
|
+
// stub needs a minimal shape (`config.useLayout`) satisfying their constructors too.
|
|
10
|
+
vi.mock('../core/Application', async () => {
|
|
11
|
+
const { Signal } = await import('../signals');
|
|
12
|
+
const fakeApp = {
|
|
13
|
+
config: { useLayout: true },
|
|
14
|
+
renderer: { layout: undefined },
|
|
15
|
+
ticker: { addOnce: () => {} },
|
|
16
|
+
onResize: new Signal(),
|
|
17
|
+
};
|
|
18
|
+
return { Application: { getInstance: () => fakeApp } };
|
|
19
|
+
});
|
|
8
20
|
|
|
9
|
-
|
|
21
|
+
// Registers the factory method table `Factory()` (part of Container's mixin
|
|
22
|
+
// chain) reads from — must be imported before any display/ui class is
|
|
23
|
+
// constructed. See importOrder.containerFirst.test.ts.
|
|
24
|
+
import '../mixins/factory/const';
|
|
25
|
+
import { Signal } from '../signals';
|
|
26
|
+
import { computeEffectivePadding, UICanvas } from './UICanvas';
|
|
10
27
|
|
|
11
28
|
const zero = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
12
29
|
|
|
@@ -33,3 +50,89 @@ describe('computeEffectivePadding', () => {
|
|
|
33
50
|
expect(computeEffectivePadding(base, safeArea).top).toBe(54);
|
|
34
51
|
});
|
|
35
52
|
});
|
|
53
|
+
|
|
54
|
+
describe('UICanvas element reordering', () => {
|
|
55
|
+
let app: any;
|
|
56
|
+
let originalAppDescriptor: PropertyDescriptor | undefined;
|
|
57
|
+
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
app = {
|
|
60
|
+
config: { useLayout: true },
|
|
61
|
+
size: { width: 800, height: 600 },
|
|
62
|
+
onResize: new Signal<() => void>(),
|
|
63
|
+
ticker: { addOnce: vi.fn() },
|
|
64
|
+
};
|
|
65
|
+
originalAppDescriptor = Object.getOwnPropertyDescriptor(UICanvas.prototype, 'app');
|
|
66
|
+
Object.defineProperty(UICanvas.prototype, 'app', { get: () => app, configurable: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
afterEach(() => {
|
|
70
|
+
if (originalAppDescriptor) {
|
|
71
|
+
Object.defineProperty(UICanvas.prototype, 'app', originalAppDescriptor);
|
|
72
|
+
} else {
|
|
73
|
+
delete (UICanvas.prototype as any).app;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
function addThree(canvas: UICanvas) {
|
|
78
|
+
const a = new PIXIContainer({ label: 'a' });
|
|
79
|
+
const b = new PIXIContainer({ label: 'b' });
|
|
80
|
+
const c = new PIXIContainer({ label: 'c' });
|
|
81
|
+
canvas.addElement(a, { align: 'top left' });
|
|
82
|
+
canvas.addElement(b, { align: 'top left' });
|
|
83
|
+
canvas.addElement(c, { align: 'top left' });
|
|
84
|
+
const container = (canvas as any)._childMap.get(a);
|
|
85
|
+
return { a, b, c, container };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
it('reorderElement moves an element within its region', () => {
|
|
89
|
+
const canvas = new UICanvas({});
|
|
90
|
+
const { a, b, c, container } = addThree(canvas);
|
|
91
|
+
|
|
92
|
+
canvas.reorderElement(a, 2);
|
|
93
|
+
|
|
94
|
+
expect(container.children.indexOf(a)).toBeGreaterThanOrEqual(0);
|
|
95
|
+
expect([b, c, a].every((child, i) => container.children[i] === child)).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('bringToFront moves an element to the last index in its region', () => {
|
|
99
|
+
const canvas = new UICanvas({});
|
|
100
|
+
const { a, b, c, container } = addThree(canvas);
|
|
101
|
+
|
|
102
|
+
canvas.bringToFront(a);
|
|
103
|
+
|
|
104
|
+
expect([b, c, a].every((child, i) => container.children[i] === child)).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('sendToBack moves an element to the first index in its region', () => {
|
|
108
|
+
const canvas = new UICanvas({});
|
|
109
|
+
const { a, b, c, container } = addThree(canvas);
|
|
110
|
+
|
|
111
|
+
canvas.sendToBack(c);
|
|
112
|
+
|
|
113
|
+
expect([c, a, b].every((child, i) => container.children[i] === child)).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('reorderElement throws when the child was never added via addElement', () => {
|
|
117
|
+
const canvas = new UICanvas({});
|
|
118
|
+
const neverAdded = new PIXIContainer({ label: 'never-added' });
|
|
119
|
+
|
|
120
|
+
expect(() => canvas.reorderElement(neverAdded, 0)).toThrow(/Cannot reorder element/);
|
|
121
|
+
expect(() => canvas.reorderElement(neverAdded, 0)).toThrow(/not added via addElement/);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('bringToFront and sendToBack throw when the child was never added via addElement', () => {
|
|
125
|
+
const canvas = new UICanvas({});
|
|
126
|
+
const neverAdded = new PIXIContainer({ label: 'never-added' });
|
|
127
|
+
|
|
128
|
+
expect(() => canvas.bringToFront(neverAdded)).toThrow(/Cannot reorder element/);
|
|
129
|
+
expect(() => canvas.sendToBack(neverAdded)).toThrow(/Cannot reorder element/);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('setChildIndex throws a guard error instead of the old Pixi passthrough', () => {
|
|
133
|
+
const canvas = new UICanvas({});
|
|
134
|
+
const { a } = addThree(canvas);
|
|
135
|
+
|
|
136
|
+
expect(() => canvas.setChildIndex(a, 0)).toThrow(/Do not call setChildIndex/);
|
|
137
|
+
});
|
|
138
|
+
});
|
package/src/ui/UICanvas.ts
CHANGED
|
@@ -490,9 +490,11 @@ export class UICanvas extends _UICanvas {
|
|
|
490
490
|
/**
|
|
491
491
|
* Sets the index of the child in the container
|
|
492
492
|
*/
|
|
493
|
-
public setChildIndex = <U extends PIXIContainer>(
|
|
494
|
-
|
|
495
|
-
|
|
493
|
+
public setChildIndex = <U extends PIXIContainer>(_child: U, _index: number): void => {
|
|
494
|
+
throw new Error(
|
|
495
|
+
`UICanvas: Do not call setChildIndex() directly. Use reorderElement(child, index), bringToFront(child), or sendToBack(child) instead.\n` +
|
|
496
|
+
`Example: uiCanvas.reorderElement(myChild, 0)`,
|
|
497
|
+
);
|
|
496
498
|
};
|
|
497
499
|
|
|
498
500
|
/**
|
|
@@ -668,6 +670,42 @@ export class UICanvas extends _UICanvas {
|
|
|
668
670
|
return child;
|
|
669
671
|
}
|
|
670
672
|
|
|
673
|
+
/**
|
|
674
|
+
* Reorders an element within its region container, changing its position in
|
|
675
|
+
* the flex layout and paint order.
|
|
676
|
+
*/
|
|
677
|
+
public reorderElement<U extends PIXIContainer>(child: U, index: number): U {
|
|
678
|
+
const container = this._childMap.get(child);
|
|
679
|
+
if (!container) {
|
|
680
|
+
throw new Error(
|
|
681
|
+
`UICanvas: Cannot reorder element — it was not added via addElement().\n` +
|
|
682
|
+
`Child label: "${child.label ?? '(unlabeled)'}"`,
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
container.setChildIndex(child, index);
|
|
687
|
+
this._updateLayout();
|
|
688
|
+
return child;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/** Moves an element to the last index (painted/laid-out last) within its region. */
|
|
692
|
+
public bringToFront<U extends PIXIContainer>(child: U): U {
|
|
693
|
+
const container = this._childMap.get(child);
|
|
694
|
+
if (!container) {
|
|
695
|
+
throw new Error(
|
|
696
|
+
`UICanvas: Cannot reorder element — it was not added via addElement().\n` +
|
|
697
|
+
`Child label: "${child.label ?? '(unlabeled)'}"`,
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
return this.reorderElement(child, container.children.length - 1);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/** Moves an element to the first index (painted/laid-out first) within its region. */
|
|
705
|
+
public sendToBack<U extends PIXIContainer>(child: U): U {
|
|
706
|
+
return this.reorderElement(child, 0);
|
|
707
|
+
}
|
|
708
|
+
|
|
671
709
|
private _childAdded(child: PIXIContainer) {
|
|
672
710
|
if (this.config.autoLayoutChildren) {
|
|
673
711
|
if (!child.layout) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { Color } from './color';
|
|
3
|
+
|
|
4
|
+
describe('Color.rgbToHexString', () => {
|
|
5
|
+
it('rounds fractional rgb components to a valid 2-digit hex pair', () => {
|
|
6
|
+
expect(Color.rgbToHexString(127.5)).toBe('80');
|
|
7
|
+
expect(Color.rgbToHexString(0.4)).toBe('00');
|
|
8
|
+
expect(Color.rgbToHexString(254.9)).toBe('ff');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('produces a valid 6-digit hex string from fractional rgb components', () => {
|
|
12
|
+
const hex = Color.rgbToFullHexString(127.5, 0.4, 254.9);
|
|
13
|
+
expect(hex).toMatch(/^[0-9a-f]{6}$/);
|
|
14
|
+
expect(hex).toBe('8000ff');
|
|
15
|
+
});
|
|
16
|
+
});
|
package/src/utils/color.ts
CHANGED
|
@@ -64,7 +64,8 @@ export class Color {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
public static rgbToHexString(pNumber: number): string {
|
|
67
|
-
|
|
67
|
+
const clamped = Math.max(0, Math.min(255, Math.round(Number(pNumber))));
|
|
68
|
+
let hex = clamped.toString(16);
|
|
68
69
|
if (hex.length < 2) {
|
|
69
70
|
hex = '0' + hex;
|
|
70
71
|
}
|
package/src/utils/platform.ts
CHANGED
|
@@ -20,7 +20,7 @@ export const isRetina =
|
|
|
20
20
|
*/
|
|
21
21
|
export const isTouch: boolean =
|
|
22
22
|
typeof window !== 'undefined'
|
|
23
|
-
? 'ontouchstart' in window || navigator.maxTouchPoints > 0
|
|
23
|
+
? 'ontouchstart' in window || navigator.maxTouchPoints > 0
|
|
24
24
|
: false;
|
|
25
25
|
|
|
26
26
|
/**
|
package/src/version.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataAdapter-DS-twowe.js","names":[],"sources":["../src/plugins/DataAdapter.ts"],"sourcesContent":["import { Signal } from '../signals';\nimport { AppTypeOverrides, deepMerge, DeepPartial } from '../utils';\nimport { Plugin } from './Plugin';\n\nexport type DataSchema = {\n [key: string]: any;\n};\n\n/**\n * Interface for the options of the DataAdapter.\n */\nexport interface IDataAdapterOptions {\n initial: Partial<AppTypeOverrides['Data']>;\n /**\n * The namespace to use for the keys in local storage.\n */\n namespace: string;\n /**\n * Whether to override the data with the data from local storage.\n */\n overrideWithLocalStorage: boolean;\n /**\n * Whether to backup all data to local storage.\n */\n backupAll: boolean;\n /**\n * The keys to backup to local storage.\n */\n backupKeys: Array<keyof AppTypeOverrides['Data']>;\n}\n\nexport interface DataChangeSignalDetail {\n key?: any;\n value?: any;\n restore?: boolean;\n clear?: boolean;\n}\n\ntype DataAdapterType = AppTypeOverrides['Data'];\n\nexport interface IDataAdapter {\n get(): DataAdapterType;\n get<K extends keyof DataAdapterType>(key: K): DataAdapterType[K] | undefined;\n set<K extends keyof DataAdapterType>(key: K, data: DataAdapterType[K]): DataAdapterType;\n set(data: DeepPartial<DataAdapterType>, merge?: boolean): DataAdapterType;\n clear(): void;\n clear<K extends keyof DataAdapterType>(key: K): void;\n increment<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends number ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n amount?: number,\n ): DataAdapterType[K];\n concat<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends any[] ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n value: DataAdapterType[K] extends (infer E)[] ? E | E[] : never,\n ): DataAdapterType[K];\n append<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends string ? P : never }[keyof DataAdapterType],\n >(\n key: K,\n value: string,\n separator?: string,\n ): DataAdapterType[K];\n snapshot(): DataAdapterType;\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K];\n onDataChange: Signal<(detail: DataChangeSignalDetail) => void>;\n clearOnResume?: boolean;\n}\n\nexport function defineData<T extends DataSchema>(data: T): T {\n return data;\n}\n\n/**\n * An in-memory game-data plugin with optional localStorage backup.\n *\n * Not `IStorageCapability` — its API (`get`/`set`/`increment`/...) is richer\n * than the generic save/load contract. Accessed directly via `app.data`.\n */\nexport class DataAdapter extends Plugin<Partial<IDataAdapterOptions>> implements IDataAdapter {\n public data: DataAdapterType;\n\n public onDataChange: Signal<(detail: DataChangeSignalDetail) => void> = new Signal();\n\n private backupKeys: Array<keyof DataAdapterType> = [];\n private backupAll: boolean = false;\n private namespace: string = '';\n private overrideWithLocalStorage: boolean = true;\n\n constructor(id: string = 'data') {\n super(id);\n }\n\n public getCoreSignals(): string[] {\n return ['onDataChange'];\n }\n\n destroy() {\n this.data = {} as DataAdapterType;\n }\n\n public initialize(options?: Partial<IDataAdapterOptions>): void {\n this.namespace = options?.namespace || this.app.appName;\n this.data = (options?.initial as DataAdapterType) || ({} as DataAdapterType);\n this.backupKeys = options?.backupKeys || [];\n this.backupAll = options?.backupAll || false;\n this.overrideWithLocalStorage = options?.overrideWithLocalStorage === false ? false : true;\n\n if (this.backupAll || this.backupKeys.length > 0) {\n if (this.overrideWithLocalStorage) {\n this.restoreFromLocalStorage(this.backupKeys);\n }\n this.backupToLocalStorage(this.backupKeys);\n }\n }\n\n set<K extends keyof DataAdapterType>(key: K, data: DataAdapterType[K]): DataAdapterType;\n set(data: DeepPartial<DataAdapterType>, merge?: boolean): DataAdapterType;\n set<K extends keyof DataAdapterType>(\n keyOrData: K | DeepPartial<DataAdapterType>,\n dataOrMerge?: DataAdapterType[K] | boolean,\n ): DataAdapterType {\n if (typeof keyOrData === 'string' || typeof keyOrData === 'number' || typeof keyOrData === 'symbol') {\n const key = keyOrData;\n const data = dataOrMerge as DataAdapterType[K];\n\n this.data[key] = data;\n if (this.backupAll || this.backupKeys.includes(key)) {\n this.backupToLocalStorage([key]);\n }\n this.onDataChange.emit({ key, value: data });\n return this.data;\n }\n\n const data = keyOrData as DeepPartial<DataAdapterType>;\n const merge = (dataOrMerge as boolean) ?? true;\n\n if (merge) {\n this.data = deepMerge({ ...this.data }, data);\n } else {\n this.data = data as DataAdapterType;\n }\n\n if (this.backupAll || this.backupKeys.length > 0) {\n this.backupToLocalStorage(this.backupKeys);\n }\n\n this.onDataChange.emit({\n key: Object.keys(data)?.length === 1 ? Object.keys(data)[0] : Object.keys(data),\n value: data[Object.keys(data)[0]] as DataAdapterType[keyof DataAdapterType],\n });\n\n return this.data;\n }\n\n get(): DataAdapterType;\n get<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | undefined;\n get<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | DataAdapterType | undefined {\n if (key === undefined) {\n return this.data;\n }\n return this.data[key];\n }\n\n increment<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends number ? P : never }[keyof DataAdapterType],\n >(key: K, amount: number = 1): DataAdapterType[K] {\n const currentValue = this.data[key] || 0;\n const newValue = currentValue + amount;\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n concat<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends any[] ? P : never }[keyof DataAdapterType],\n >(key: K, value: DataAdapterType[K] extends (infer E)[] ? E | E[] : never): DataAdapterType[K] {\n const currentValue = this.data[key];\n const newValue = [...currentValue, ...(Array.isArray(value) ? value : [value])];\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n append<\n K extends keyof DataAdapterType &\n { [P in keyof DataAdapterType]: DataAdapterType[P] extends string ? P : never }[keyof DataAdapterType],\n >(key: K, value: string, separator: string = ''): DataAdapterType[K] {\n const currentValue = this.data[key];\n let newValue = value;\n if ((currentValue as string)?.length > 0) {\n newValue = currentValue + separator + value;\n }\n this.set({ [key]: newValue } as DeepPartial<DataAdapterType>);\n return newValue as DataAdapterType[K];\n }\n\n clear(): void;\n clear<K extends keyof DataAdapterType>(key?: K): void {\n if (key === undefined) {\n this.data = {} as DataAdapterType;\n localStorage.clear();\n this.onDataChange.emit({ key, clear: true });\n } else {\n delete this.data[key];\n localStorage.removeItem(`${this.namespace}-${key as string}`);\n this.onDataChange.emit({ clear: true });\n }\n }\n\n snapshot(): DataAdapterType;\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K];\n snapshot<K extends keyof DataAdapterType>(key?: K): DataAdapterType[K] | DataAdapterType {\n if (key === undefined) {\n return JSON.parse(JSON.stringify(this.data));\n }\n return JSON.parse(JSON.stringify(this.data[key]));\n }\n\n private backupToLocalStorage(keys?: Array<keyof DataAdapterType>): void {\n const dataToBackup =\n keys && keys?.length > 0 ? Object.fromEntries(keys.map((key) => [key, this.data[key]])) : this.data;\n\n for (const key in dataToBackup) {\n localStorage.setItem(`${this.namespace}-${key}`, JSON.stringify(dataToBackup[key]));\n }\n }\n\n private restoreFromLocalStorage(keys?: Array<keyof DataAdapterType>): void {\n const keysToRestore = keys && keys?.length > 0 ? keys : (Object.keys(this.data) as Array<keyof DataAdapterType>);\n keysToRestore.forEach((key) => {\n try {\n const loadedData = localStorage.getItem(`${this.namespace}-${String(key)}`);\n if (loadedData !== null) {\n try {\n const parsedData = JSON.parse(loadedData);\n this.data[key] = parsedData;\n } catch (parseError) {\n console.warn(\n `Failed to parse data for key \"${String(key)}\" in namespace \"${this.namespace}\". Using default value.`,\n );\n }\n }\n } catch (storageError) {\n console.error(\n `Error accessing localStorage for key \"${String(key)}\" in namespace \"${this.namespace}\":`,\n storageError,\n );\n }\n });\n this.onDataChange.emit({ restore: true });\n }\n}\n"],"mappings":"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"}
|