@antha/gamepad-type 0.1.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.
Files changed (66) hide show
  1. package/LICENSE-CC0 +121 -0
  2. package/LICENSE-MIT +21 -0
  3. package/README.md +102 -0
  4. package/dist/create.d.ts +10 -0
  5. package/dist/create.js +20 -0
  6. package/dist/default-layouts.d.ts +8 -0
  7. package/dist/default-layouts.js +339 -0
  8. package/dist/default-models.d.ts +14 -0
  9. package/dist/default-models.js +46 -0
  10. package/dist/demo/elements/gamepad/vir-gamepad-axe.element.d.ts +7 -0
  11. package/dist/demo/elements/gamepad/vir-gamepad-axe.element.js +61 -0
  12. package/dist/demo/elements/gamepad/vir-gamepad-button.element.d.ts +7 -0
  13. package/dist/demo/elements/gamepad/vir-gamepad-button.element.js +87 -0
  14. package/dist/demo/elements/gamepad/vir-gamepad-input.element.d.ts +7 -0
  15. package/dist/demo/elements/gamepad/vir-gamepad-input.element.js +38 -0
  16. package/dist/demo/elements/gamepad/vir-gamepad-inputs.element.d.ts +20 -0
  17. package/dist/demo/elements/gamepad/vir-gamepad-inputs.element.js +110 -0
  18. package/dist/demo/elements/gamepad/vir-gamepad-name.element.d.ts +11 -0
  19. package/dist/demo/elements/gamepad/vir-gamepad-name.element.js +158 -0
  20. package/dist/demo/elements/gamepad/vir-gamepad.element.d.ts +8 -0
  21. package/dist/demo/elements/gamepad/vir-gamepad.element.js +41 -0
  22. package/dist/demo/elements/modals/vir-create-new-type.modal.element.d.ts +9 -0
  23. package/dist/demo/elements/modals/vir-create-new-type.modal.element.js +135 -0
  24. package/dist/demo/elements/modals/vir-edit-mappings.modal.element.d.ts +29 -0
  25. package/dist/demo/elements/modals/vir-edit-mappings.modal.element.js +185 -0
  26. package/dist/demo/elements/modals/vir-modal.element.d.ts +3 -0
  27. package/dist/demo/elements/modals/vir-modal.element.js +88 -0
  28. package/dist/demo/elements/vir-demo.element.d.ts +27 -0
  29. package/dist/demo/elements/vir-demo.element.js +469 -0
  30. package/dist/demo/events/modal-close.event.d.ts +1 -0
  31. package/dist/demo/events/modal-close.event.js +2 -0
  32. package/dist/demo/events/selected-gamepad-index-change.event.d.ts +1 -0
  33. package/dist/demo/events/selected-gamepad-index-change.event.js +2 -0
  34. package/dist/demo/gamepad-brand-color.d.ts +1 -0
  35. package/dist/demo/gamepad-brand-color.js +14 -0
  36. package/dist/demo/global-vars.d.ts +6 -0
  37. package/dist/demo/global-vars.js +3 -0
  38. package/dist/demo/overrides.d.ts +7 -0
  39. package/dist/demo/overrides.js +1 -0
  40. package/dist/demo/sentry-setup.d.ts +1 -0
  41. package/dist/demo/sentry-setup.js +11 -0
  42. package/dist/demo/util/casing.d.ts +1 -0
  43. package/dist/demo/util/casing.js +7 -0
  44. package/dist/demo/util/check-changes.d.ts +6 -0
  45. package/dist/demo/util/check-changes.js +28 -0
  46. package/dist/demo/util/local-save-data.d.ts +9 -0
  47. package/dist/demo/util/local-save-data.js +36 -0
  48. package/dist/demo/util/user-agent.d.ts +6 -0
  49. package/dist/demo/util/user-agent.js +2 -0
  50. package/dist/demo/util/window-listener.d.ts +1 -0
  51. package/dist/demo/util/window-listener.js +6 -0
  52. package/dist/find-matches.d.ts +42 -0
  53. package/dist/find-matches.js +77 -0
  54. package/dist/gamepad-layout.d.ts +29 -0
  55. package/dist/gamepad-layout.js +1 -0
  56. package/dist/gamepad-model.d.ts +67 -0
  57. package/dist/gamepad-model.js +69 -0
  58. package/dist/index.d.ts +8 -0
  59. package/dist/index.js +8 -0
  60. package/dist/known-input.d.ts +126 -0
  61. package/dist/known-input.js +128 -0
  62. package/dist/system-versions.d.ts +25 -0
  63. package/dist/system-versions.js +26 -0
  64. package/dist/util/lowercase-keys.d.ts +2 -0
  65. package/dist/util/lowercase-keys.js +10 -0
  66. package/package.json +67 -0
@@ -0,0 +1,46 @@
1
+ import { PredefinedGamepadBrand, PredefinedGamepadModel, } from './gamepad-model.js';
2
+ /**
3
+ * Gamepad mappings of gamepad ids / names to GamepadModel defined by the
4
+ * [gamepad-type](https://www.npmjs.com/package/gamepad-type) package.
5
+ *
6
+ * @category Defaults
7
+ */
8
+ export const defaultGamepadModelMap = {
9
+ /** Safari detected OEM Switch Pro gamepad name. */
10
+ 'Pro Controller Extended Gamepad': PredefinedGamepadModel.SwitchPro,
11
+ /** Safari detected OEM Xbox Wireless gamepad name. */
12
+ 'Xbox Wireless Controller Extended Gamepad': PredefinedGamepadModel.XboxWireless,
13
+ /** Safari detected OEM DualSense gamepad name. */
14
+ 'DualSense Wireless Controller Extended Gamepad': PredefinedGamepadModel.PlaystationDualSense,
15
+ /** Safari detected OEM DualSense gamepad name. (Yes, another one.) */
16
+ 'Wireless Controller Extended Gamepad': PredefinedGamepadModel.PlaystationDualSense,
17
+ /** Firefox detected OEM DualSense gamepad name. */
18
+ '54c-ce6-Wireless Controller': PredefinedGamepadModel.PlaystationDualSense,
19
+ /** Firefox detected OEM Xbox Wireless gamepad name. */
20
+ '45e-b13-Xbox Wireless Controller': PredefinedGamepadModel.XboxWireless,
21
+ /** Chrome detected OEM Switch Pro gamepad name. */
22
+ 'Pro Controller (STANDARD GAMEPAD Vendor: 057e Product: 2009)': PredefinedGamepadModel.SwitchPro,
23
+ /** Chrome detected OEM DualSense gamepad name. */
24
+ 'Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 0ce6)': PredefinedGamepadModel.PlaystationDualSense,
25
+ /** Chrome detected OEM Xbox Wireless gamepad name. */
26
+ 'Xbox Series X Controller (STANDARD GAMEPAD Vendor: 045e Product: 0b12)': PredefinedGamepadModel.XboxWireless,
27
+ /** Inputs from external users. */
28
+ 'DUALSHOCK 4 Wireless Controller Extended Gamepad': PredefinedGamepadModel.PlaystationDualShock4, // e9ed532bca264299849b10d076040798
29
+ 'DUALSHOCK 4 Wireless Controller (STANDARD GAMEPAD Vendor: 054c Product: 09cc)': PredefinedGamepadModel.PlaystationDualShock4, // 9e8343773463416683ac7501d766e682
30
+ '54c-9cc-DUALSHOCK 4 Wireless Controller': PredefinedGamepadModel.PlaystationDualShock4, // 25024a8747044b43b71608ffa13c18c7
31
+ 'HID-compliant game controller (STANDARD GAMEPAD Vendor: 045e Product: 0b13)': PredefinedGamepadModel.XboxWireless, // issues #6578763126
32
+ };
33
+ /**
34
+ * PredefinedGamepadBrand for each PredefinedGamepadModel.
35
+ *
36
+ * @category Defaults
37
+ */
38
+ export const defaultGamepadBrandMap = {
39
+ [PredefinedGamepadModel.SwitchPro]: PredefinedGamepadBrand.Nintendo,
40
+ [PredefinedGamepadModel.Xbox360]: PredefinedGamepadBrand.Microsoft,
41
+ [PredefinedGamepadModel.XboxWireless]: PredefinedGamepadBrand.Microsoft,
42
+ [PredefinedGamepadModel.PlaystationDualSense]: PredefinedGamepadBrand.Sony,
43
+ [PredefinedGamepadModel.PlaystationDualShock]: PredefinedGamepadBrand.Sony,
44
+ [PredefinedGamepadModel.PlaystationDualShock4]: PredefinedGamepadBrand.Sony,
45
+ [PredefinedGamepadModel.SteamDeck]: PredefinedGamepadBrand.Valve,
46
+ };
@@ -0,0 +1,7 @@
1
+ import { type GamepadInputDetails } from 'input-device-handler';
2
+ import { type GamepadLayout } from '../../../index.js';
3
+ export declare const VirGamepadAxe: import("element-vir").DeclarativeElementDefinition<"vir-gamepad-axe", {
4
+ gamepadInput: Readonly<GamepadInputDetails>;
5
+ gamepadBrand: string | undefined;
6
+ gamepadLayout: Readonly<GamepadLayout> | undefined;
7
+ }, {}, {}, "vir-gamepad-axe-", "vir-gamepad-axe-color", readonly [], readonly []>;
@@ -0,0 +1,61 @@
1
+ import { css, defineElement, html } from 'element-vir';
2
+ import { noNativeSpacing } from 'vira';
3
+ import { getGamepadBrandColor } from '../../gamepad-brand-color.js';
4
+ export const VirGamepadAxe = defineElement()({
5
+ tagName: 'vir-gamepad-axe',
6
+ cssVars: {
7
+ 'vir-gamepad-axe-color': getGamepadBrandColor(undefined),
8
+ },
9
+ styles: ({ cssVars }) => {
10
+ return css `
11
+ :host {
12
+ display: block;
13
+ width: 200px;
14
+ border: 2px solid ${cssVars['vir-gamepad-axe-color'].value};
15
+ text-align: center;
16
+ position: relative;
17
+ background-color: white;
18
+ }
19
+
20
+ .progress {
21
+ z-index: 1;
22
+ position: absolute;
23
+ top: 0;
24
+ bottom: 0;
25
+ left: 50%;
26
+ right: 50%;
27
+ border: 1px solid ${cssVars['vir-gamepad-axe-color'].value};
28
+ background-color: ${cssVars['vir-gamepad-axe-color'].value};
29
+ }
30
+
31
+ p {
32
+ ${noNativeSpacing};
33
+ position: relative;
34
+ z-index: 10;
35
+ }
36
+ `;
37
+ },
38
+ render({ inputs, host }) {
39
+ host.style.setProperty('--vir-gamepad-axe-color', getGamepadBrandColor(inputs.gamepadBrand));
40
+ const progressPercents = inputs.gamepadInput.value >= 0
41
+ ? {
42
+ left: 50,
43
+ right: 50 - inputs.gamepadInput.value * 50,
44
+ }
45
+ : {
46
+ left: 50 + inputs.gamepadInput.value * 50,
47
+ right: 50,
48
+ };
49
+ const progressStyle = css `
50
+ left: ${progressPercents.left}%;
51
+ right: ${progressPercents.right}%;
52
+ `;
53
+ const inputName = inputs.gamepadLayout?.inputMappings[inputs.gamepadInput.inputName] ||
54
+ inputs.gamepadInput.inputName;
55
+ return html `
56
+ <div class="progress" style=${progressStyle}></div>
57
+ <p class="axe-words">${inputName}</p>
58
+ <p>${inputs.gamepadInput.value.toFixed(1)}</p>
59
+ `;
60
+ },
61
+ });
@@ -0,0 +1,7 @@
1
+ import { type GamepadInputDetails } from 'input-device-handler';
2
+ import { type GamepadLayout } from '../../../index.js';
3
+ export declare const VirGamepadButton: import("element-vir").DeclarativeElementDefinition<"vir-gamepad-button", {
4
+ gamepadInput: Readonly<GamepadInputDetails>;
5
+ gamepadBrand: string | undefined;
6
+ gamepadLayout: Readonly<GamepadLayout> | undefined;
7
+ }, {}, {}, "vir-gamepad-button-", "vir-gamepad-button-button-size" | "vir-gamepad-button-color", readonly [], readonly []>;
@@ -0,0 +1,87 @@
1
+ import { classMap, css, defineElement, html } from 'element-vir';
2
+ import { DeviceInputType } from 'input-device-handler';
3
+ import { getGamepadBrandColor } from '../../gamepad-brand-color.js';
4
+ export const VirGamepadButton = defineElement()({
5
+ tagName: 'vir-gamepad-button',
6
+ cssVars: {
7
+ 'vir-gamepad-button-button-size': '75px',
8
+ 'vir-gamepad-button-color': getGamepadBrandColor(undefined),
9
+ },
10
+ styles: ({ cssVars }) => {
11
+ return css `
12
+ :host {
13
+ display: flex;
14
+ position: relative;
15
+ height: ${cssVars['vir-gamepad-button-button-size'].value};
16
+ width: ${cssVars['vir-gamepad-button-button-size'].value};
17
+ border: 2px solid ${cssVars['vir-gamepad-button-color'].value};
18
+ box-sizing: border-box;
19
+ border-radius: 50%;
20
+ }
21
+
22
+ .button-fill-wrapper {
23
+ box-sizing: border-box;
24
+ position: absolute;
25
+ top: -1px;
26
+ left: -1px;
27
+ width: calc(100% + 2px);
28
+ height: calc(100% + 2px);
29
+ display: flex;
30
+ justify-content: center;
31
+ align-items: center;
32
+ }
33
+
34
+ .button-fill {
35
+ box-sizing: border-box;
36
+ width: 0%;
37
+ height: 0%;
38
+ pointer-events: none;
39
+ opacity: 1;
40
+ border-radius: 50%;
41
+ background-color: ${cssVars['vir-gamepad-button-color'].value};
42
+ border: 2px solid ${cssVars['vir-gamepad-button-color'].value};
43
+ z-index: 1;
44
+ }
45
+
46
+ .no-fill {
47
+ opacity: 0;
48
+ }
49
+
50
+ .button-name {
51
+ z-index: 4;
52
+ width: 100%;
53
+ height: 100%;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ text-align: center;
58
+ }
59
+ `;
60
+ },
61
+ render({ inputs, host }) {
62
+ if (inputs.gamepadInput.inputType !== DeviceInputType.Button) {
63
+ throw new Error(`
64
+ Incorrect input type '${inputs.gamepadInput.inputType}': expected
65
+ '${DeviceInputType.Button}'.
66
+ `);
67
+ }
68
+ host.style.setProperty('--vir-gamepad-button-color', getGamepadBrandColor(inputs.gamepadBrand));
69
+ const buttonFillStyle = css `
70
+ width: ${inputs.gamepadInput.value * 100}%;
71
+ height: ${inputs.gamepadInput.value * 100}%;
72
+ `;
73
+ const inputName = inputs.gamepadLayout?.inputMappings[inputs.gamepadInput.inputName] ||
74
+ inputs.gamepadInput.inputName;
75
+ return html `
76
+ <div class="button-fill-wrapper">
77
+ <div
78
+ class="button-fill ${classMap({
79
+ 'no-fill': !inputs.gamepadInput.value,
80
+ })}"
81
+ style=${buttonFillStyle}
82
+ ></div>
83
+ </div>
84
+ <div class="button-name">${inputName}</div>
85
+ `;
86
+ },
87
+ });
@@ -0,0 +1,7 @@
1
+ import { type GamepadInputDetails } from 'input-device-handler';
2
+ import { type GamepadLayout } from '../../../index.js';
3
+ export declare const VirGamepadInput: import("element-vir").DeclarativeElementDefinition<"vir-gamepad-input", {
4
+ gamepadInput: Readonly<GamepadInputDetails>;
5
+ gamepadBrand: string | undefined;
6
+ gamepadLayout: Readonly<GamepadLayout> | undefined;
7
+ }, {}, {}, "vir-gamepad-input-circle", "vir-gamepad-input-", readonly [], readonly []>;
@@ -0,0 +1,38 @@
1
+ import { css, defineElement, html } from 'element-vir';
2
+ import { DeviceInputType } from 'input-device-handler';
3
+ import { VirGamepadAxe } from './vir-gamepad-axe.element.js';
4
+ import { VirGamepadButton } from './vir-gamepad-button.element.js';
5
+ export const VirGamepadInput = defineElement()({
6
+ tagName: 'vir-gamepad-input',
7
+ hostClasses: {
8
+ 'vir-gamepad-input-circle': ({ inputs }) => {
9
+ return inputs.gamepadInput.inputType === DeviceInputType.Button;
10
+ },
11
+ },
12
+ styles: ({ hostClasses }) => {
13
+ return css `
14
+ :host {
15
+ display: flex;
16
+ }
17
+
18
+ ${hostClasses['vir-gamepad-input-circle'].selector} {
19
+ border-radius: 50%;
20
+ }
21
+ `;
22
+ },
23
+ render({ inputs }) {
24
+ if (inputs.gamepadInput.inputType === DeviceInputType.Axe) {
25
+ return html `
26
+ <${VirGamepadAxe.assign(inputs)}></${VirGamepadAxe}>
27
+ `;
28
+ }
29
+ else if (inputs.gamepadInput.inputType === DeviceInputType.Button) {
30
+ return html `
31
+ <${VirGamepadButton.assign(inputs)}></${VirGamepadButton}>
32
+ `;
33
+ }
34
+ else {
35
+ return `Invalid gamepad type received: ${inputs.gamepadInput.inputType}`;
36
+ }
37
+ },
38
+ });
@@ -0,0 +1,20 @@
1
+ import { type GamepadDevice } from 'input-device-handler';
2
+ import { type GamepadLayout, type GamepadModelMap } from '../../../index.js';
3
+ export declare const VirGamepadInputs: import("element-vir").DeclarativeElementDefinition<"vir-gamepad-inputs", {
4
+ gamepad: Readonly<GamepadDevice>;
5
+ gamepadLayout: Readonly<GamepadLayout> | undefined;
6
+ gamepadModelMap: Readonly<GamepadModelMap>;
7
+ }, {}, {
8
+ gamepadInputClick: import("element-vir").DefineEvent<Readonly<Readonly<{
9
+ deviceName: string;
10
+ deviceKey: import("input-device-handler").GamepadInputDeviceKey;
11
+ deviceType: import("input-device-handler").InputDeviceType;
12
+ inputName: string;
13
+ inputValue: number;
14
+ details: Readonly<Readonly<{
15
+ inputName: string;
16
+ value: number;
17
+ inputType: import("input-device-handler").DeviceInputType;
18
+ }>>;
19
+ }>>>;
20
+ }, "vir-gamepad-inputs-", "vir-gamepad-inputs-", readonly [], readonly []>;
@@ -0,0 +1,110 @@
1
+ import { getObjectTypedKeys } from '@augment-vir/common';
2
+ import { css, defineElement, defineElementEvent, html, listen } from 'element-vir';
3
+ import { findMatchingGamepadModel, } from '../../../index.js';
4
+ import { VirGamepadInput } from './vir-gamepad-input.element.js';
5
+ export const VirGamepadInputs = defineElement()({
6
+ tagName: 'vir-gamepad-inputs',
7
+ events: {
8
+ gamepadInputClick: defineElementEvent(),
9
+ },
10
+ styles: css `
11
+ :host {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 16px;
15
+ }
16
+
17
+ .inputs {
18
+ display: flex;
19
+ gap: 8px;
20
+ flex-wrap: wrap;
21
+ }
22
+
23
+ ${VirGamepadInput} {
24
+ cursor: pointer;
25
+ border: 1px solid transparent;
26
+ }
27
+
28
+ ${VirGamepadInput}:hover {
29
+ border-color: black;
30
+ }
31
+
32
+ .prefix.warning {
33
+ color: red;
34
+ }
35
+
36
+ .prefix {
37
+ font-weight: bold;
38
+ }
39
+
40
+ .prefix.info {
41
+ color: dodgerblue;
42
+ }
43
+ `,
44
+ render({ inputs, dispatch, events }) {
45
+ const { gamepadBrand } = findMatchingGamepadModel({
46
+ gamepad: inputs.gamepad.deviceName,
47
+ gamepadModelMap: inputs.gamepadModelMap,
48
+ });
49
+ const buttons = inputs.gamepad.deviceDetails.buttons.map((gamepadInput) => {
50
+ return html `
51
+ <${VirGamepadInput.assign({
52
+ gamepadBrand,
53
+ gamepadInput,
54
+ gamepadLayout: inputs.gamepadLayout,
55
+ })}
56
+ ${listen('click', () => {
57
+ dispatch(new events.gamepadInputClick({
58
+ details: gamepadInput,
59
+ deviceKey: inputs.gamepad.deviceKey,
60
+ deviceName: inputs.gamepad.deviceName,
61
+ deviceType: inputs.gamepad.deviceType,
62
+ inputName: gamepadInput.inputName,
63
+ inputValue: gamepadInput.value,
64
+ }));
65
+ })}
66
+ ></${VirGamepadInput}>
67
+ `;
68
+ });
69
+ const axes = inputs.gamepad.deviceDetails.axes.map((gamepadInput) => {
70
+ return html `
71
+ <${VirGamepadInput.assign({
72
+ gamepadBrand,
73
+ gamepadInput,
74
+ gamepadLayout: inputs.gamepadLayout,
75
+ })}
76
+ ${listen('click', () => {
77
+ dispatch(new events.gamepadInputClick({
78
+ details: gamepadInput,
79
+ deviceKey: inputs.gamepad.deviceKey,
80
+ deviceName: inputs.gamepad.deviceName,
81
+ deviceType: inputs.gamepad.deviceType,
82
+ inputName: gamepadInput.inputName,
83
+ inputValue: gamepadInput.value,
84
+ }));
85
+ })}
86
+ ></${VirGamepadInput}>
87
+ `;
88
+ });
89
+ const notesTemplate = inputs.gamepadLayout?.notes
90
+ ? getObjectTypedKeys(inputs.gamepadLayout.notes).map((noteType) => {
91
+ const note = inputs.gamepadLayout?.notes?.[noteType];
92
+ if (!note) {
93
+ return '';
94
+ }
95
+ const prefix = noteType === 'info' ? 'Note' : 'WARNING';
96
+ return html `
97
+ <p class="notes">
98
+ <span class="prefix ${noteType}">${prefix}:</span>
99
+ ${note}
100
+ </p>
101
+ `;
102
+ })
103
+ : '';
104
+ return html `
105
+ ${notesTemplate}
106
+ <div class="inputs">${buttons}</div>
107
+ <div class="inputs">${axes}</div>
108
+ `;
109
+ },
110
+ });
@@ -0,0 +1,11 @@
1
+ import { type GamepadDevice } from 'input-device-handler';
2
+ import { type GamepadModelMap } from '../../../index.js';
3
+ export declare const VirGamepadName: import("element-vir").DeclarativeElementDefinition<"vir-gamepad-name", {
4
+ gamepad: Readonly<GamepadDevice>;
5
+ gamepadIndex: number;
6
+ gamepadModelMap: Readonly<GamepadModelMap>;
7
+ }, {}, {
8
+ editMappingsClick: import("element-vir").DefineEvent<void>;
9
+ gamepadModelOverride: import("element-vir").DefineEvent<string>;
10
+ createNewModel: import("element-vir").DefineEvent<void>;
11
+ }, "vir-gamepad-name-", "vir-gamepad-name-gamepad-brand-color", readonly [], readonly []>;
@@ -0,0 +1,158 @@
1
+ import { assert } from '@augment-vir/assert';
2
+ import { getEnumValues, getObjectTypedValues } from '@augment-vir/common';
3
+ import { css, defineElement, defineElementEvent, html, listen, onDomCreated } from 'element-vir';
4
+ import { noNativeFormStyles, noNativeSpacing } from 'vira';
5
+ import { PredefinedGamepadModel, findMatchingGamepadModel, } from '../../../index.js';
6
+ import { getGamepadBrandColor } from '../../gamepad-brand-color.js';
7
+ import { kebabCaseToNameCase } from '../../util/casing.js';
8
+ const createNewGamepadModelValue = 'create new gamepad model';
9
+ export const VirGamepadName = defineElement()({
10
+ tagName: 'vir-gamepad-name',
11
+ cssVars: {
12
+ 'vir-gamepad-name-gamepad-brand-color': getGamepadBrandColor(undefined),
13
+ },
14
+ events: {
15
+ editMappingsClick: defineElementEvent(),
16
+ gamepadModelOverride: defineElementEvent(),
17
+ createNewModel: defineElementEvent(),
18
+ },
19
+ styles: ({ cssVars }) => {
20
+ return css `
21
+ :host {
22
+ border-radius: 24px;
23
+ padding: 32px;
24
+ gap: 16px;
25
+ display: flex;
26
+ flex-direction: column;
27
+ background-color: ${cssVars['vir-gamepad-name-gamepad-brand-color'].value};
28
+ border: 2px solid ${cssVars['vir-gamepad-name-gamepad-brand-color'].value};
29
+ background-image: linear-gradient(
30
+ hsla(0, 0%, 100%, 0.8),
31
+ hsla(0, 0%, 100%, 0) 75px,
32
+ hsla(0, 0%, 0%, 0.01) 75px,
33
+ hsla(0, 0%, 100%, 0)
34
+ );
35
+ text-shadow: 0 2px 4px hsla(0, 0%, 100%, 0.7);
36
+ box-shadow: inset 0 5px 20px hsla(0, 0%, 100%, 0.9);
37
+ }
38
+
39
+ h2,
40
+ p {
41
+ ${noNativeSpacing}
42
+ }
43
+
44
+ h2 {
45
+ font-size: 2em;
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 8px;
49
+ }
50
+
51
+ .subtitle {
52
+ color: #575757;
53
+ }
54
+
55
+ .subtitle:hover {
56
+ color: black;
57
+ }
58
+
59
+ button {
60
+ ${noNativeFormStyles};
61
+ align-self: center;
62
+ transition: 100ms;
63
+ border: 1px solid ${cssVars['vir-gamepad-name-gamepad-brand-color'].value};
64
+ background-color: white;
65
+ padding: 4px 8px;
66
+ font: inherit;
67
+ border-radius: 8px;
68
+ cursor: pointer;
69
+ font-weight: bold;
70
+ }
71
+
72
+ button:hover,
73
+ button:active {
74
+ color: ${cssVars['vir-gamepad-name-gamepad-brand-color'].value};
75
+ background-color: black;
76
+ }
77
+
78
+ select {
79
+ ${noNativeFormStyles};
80
+ flex-grow: 1;
81
+ padding: 2px 4px;
82
+ cursor: pointer;
83
+ width: 0;
84
+ font: inherit;
85
+ }
86
+ `;
87
+ },
88
+ render({ inputs, host, dispatch, events }) {
89
+ const { gamepadBrand, gamepadModel, gamepadModelDescription } = findMatchingGamepadModel({
90
+ gamepad: inputs.gamepad,
91
+ gamepadModelMap: inputs.gamepadModelMap,
92
+ });
93
+ host.style.setProperty('--vir-gamepad-name-gamepad-brand-color', getGamepadBrandColor(gamepadBrand));
94
+ const gamepadModelOptions = Array.from(new Set([
95
+ ...getEnumValues(PredefinedGamepadModel),
96
+ ...getObjectTypedValues(inputs.gamepadModelMap),
97
+ ]));
98
+ const gamepadTypeSelectTemplate = html `
99
+ <select
100
+ ${onDomCreated((element) => {
101
+ /**
102
+ * For some Reason the `?selected` attribute on the below `<option>` elements
103
+ * doesn't work here on Firefox.
104
+ */
105
+ assert.instanceOf(element, HTMLSelectElement);
106
+ if (gamepadModel) {
107
+ element.value = gamepadModel;
108
+ }
109
+ })}
110
+ ${listen('change', (event) => {
111
+ const element = event.currentTarget;
112
+ assert.instanceOf(element, HTMLSelectElement);
113
+ const value = element.value;
114
+ if (value === createNewGamepadModelValue) {
115
+ dispatch(new events.createNewModel());
116
+ if (gamepadModel) {
117
+ element.value = gamepadModel;
118
+ }
119
+ else {
120
+ element.value = '';
121
+ }
122
+ }
123
+ else {
124
+ dispatch(new events.gamepadModelOverride(value));
125
+ }
126
+ })}
127
+ >
128
+ ${gamepadModelOptions.map((model) => {
129
+ return html `
130
+ <option ?selected=${gamepadModel === model} value=${model}>
131
+ ${kebabCaseToNameCase(model)}
132
+ </option>
133
+ `;
134
+ })}
135
+ <option value=${createNewGamepadModelValue}>&gt; Enter New Gamepad Model</option>
136
+ </select>
137
+ `;
138
+ return html `
139
+ <h2>
140
+ <span>${inputs.gamepadIndex}:</span>
141
+ ${gamepadTypeSelectTemplate}
142
+ </h2>
143
+ <p class="subtitle">
144
+ "${inputs.gamepad.deviceName}"
145
+ <br />
146
+ <br />
147
+ ${gamepadModelDescription}
148
+ </p>
149
+ <button
150
+ ${listen('click', () => {
151
+ dispatch(new events.editMappingsClick());
152
+ })}
153
+ >
154
+ Edit Mappings
155
+ </button>
156
+ `;
157
+ },
158
+ });
@@ -0,0 +1,8 @@
1
+ import { type GamepadDevice } from 'input-device-handler';
2
+ import { type GamepadLayout, type GamepadModelMap } from '../../../index.js';
3
+ export declare const VirGamepad: import("element-vir").DeclarativeElementDefinition<"vir-gamepad", {
4
+ gamepad: Readonly<GamepadDevice>;
5
+ gamepadIndex: number;
6
+ gamepadLayout: Readonly<GamepadLayout> | undefined;
7
+ gamepadModelMap: Readonly<GamepadModelMap>;
8
+ }, {}, {}, "vir-gamepad-", "vir-gamepad-", readonly [], readonly []>;
@@ -0,0 +1,41 @@
1
+ import { css, defineElement, html } from 'element-vir';
2
+ import { VirGamepadInputs } from './vir-gamepad-inputs.element.js';
3
+ import { VirGamepadName } from './vir-gamepad-name.element.js';
4
+ export const VirGamepad = defineElement()({
5
+ tagName: 'vir-gamepad',
6
+ styles: css `
7
+ :host {
8
+ display: flex;
9
+ background-color: white;
10
+ color: black;
11
+ gap: 16px;
12
+ flex-wrap: wrap;
13
+ align-items: flex-start;
14
+ }
15
+
16
+ ${VirGamepadName} {
17
+ flex-grow: 1;
18
+ flex-basis: 600px;
19
+ }
20
+
21
+ ${VirGamepadInputs} {
22
+ flex-grow: 1000000;
23
+ flex-shrink: 1;
24
+ flex-basis: 300px;
25
+ }
26
+ `,
27
+ render({ inputs }) {
28
+ return html `
29
+ <${VirGamepadName.assign({
30
+ gamepad: inputs.gamepad,
31
+ gamepadIndex: inputs.gamepadIndex,
32
+ gamepadModelMap: inputs.gamepadModelMap,
33
+ })}></${VirGamepadName}>
34
+ <${VirGamepadInputs.assign({
35
+ gamepad: inputs.gamepad,
36
+ gamepadLayout: inputs.gamepadLayout,
37
+ gamepadModelMap: inputs.gamepadModelMap,
38
+ })}></${VirGamepadInputs}>
39
+ `;
40
+ },
41
+ });
@@ -0,0 +1,9 @@
1
+ import { type GamepadDevice } from 'input-device-handler';
2
+ export declare const VirCreateNewTypeModal: import("element-vir").DeclarativeElementDefinition<"vir-create-new-type-modal", {
3
+ gamepadDevices: ReadonlyArray<Readonly<GamepadDevice>>;
4
+ selectedGamepadIndex: number;
5
+ }, {
6
+ newModelName: string;
7
+ }, {
8
+ newModelCreate: import("element-vir").DefineEvent<string>;
9
+ }, "vir-create-new-type-modal-", "vir-create-new-type-modal-", readonly [], readonly []>;