@rydr/game-sdk 7.0.1 → 7.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 (95) hide show
  1. package/README.md +19 -0
  2. package/dist/protocol/glyphs.d.ts +7 -0
  3. package/dist/protocol/glyphs.d.ts.map +1 -1
  4. package/dist/protocol/glyphs.js +26 -0
  5. package/dist/protocol/glyphs.js.map +1 -1
  6. package/dist/protocol/version.d.ts +1 -1
  7. package/dist/protocol/version.js +1 -1
  8. package/dist/ui/README.md +119 -0
  9. package/dist/ui/controller/combo-demo.d.ts +74 -0
  10. package/dist/ui/controller/combo-demo.d.ts.map +1 -0
  11. package/dist/ui/controller/combo-demo.js +295 -0
  12. package/dist/ui/controller/combo-demo.js.map +1 -0
  13. package/dist/ui/controller/combo-strip.d.ts +36 -0
  14. package/dist/ui/controller/combo-strip.d.ts.map +1 -0
  15. package/dist/ui/controller/combo-strip.js +66 -0
  16. package/dist/ui/controller/combo-strip.js.map +1 -0
  17. package/dist/ui/controller/control-trainer.d.ts +132 -0
  18. package/dist/ui/controller/control-trainer.d.ts.map +1 -0
  19. package/dist/ui/controller/control-trainer.js +570 -0
  20. package/dist/ui/controller/control-trainer.js.map +1 -0
  21. package/dist/ui/controller/controller-map.d.ts +82 -0
  22. package/dist/ui/controller/controller-map.d.ts.map +1 -0
  23. package/dist/ui/controller/controller-map.js +291 -0
  24. package/dist/ui/controller/controller-map.js.map +1 -0
  25. package/dist/ui/controller/controller-pad.d.ts +122 -0
  26. package/dist/ui/controller/controller-pad.d.ts.map +1 -0
  27. package/dist/ui/controller/controller-pad.js +200 -0
  28. package/dist/ui/controller/controller-pad.js.map +1 -0
  29. package/dist/ui/controller/index.d.ts +26 -0
  30. package/dist/ui/controller/index.d.ts.map +1 -0
  31. package/dist/ui/controller/index.js +26 -0
  32. package/dist/ui/controller/index.js.map +1 -0
  33. package/dist/ui/controller/input-chip.d.ts +100 -0
  34. package/dist/ui/controller/input-chip.d.ts.map +1 -0
  35. package/dist/ui/controller/input-chip.js +322 -0
  36. package/dist/ui/controller/input-chip.js.map +1 -0
  37. package/dist/ui/controller/layouts/dualsense.d.ts +12 -0
  38. package/dist/ui/controller/layouts/dualsense.d.ts.map +1 -0
  39. package/dist/ui/controller/layouts/dualsense.js +64 -0
  40. package/dist/ui/controller/layouts/dualsense.js.map +1 -0
  41. package/dist/ui/controller/layouts/index.d.ts +20 -0
  42. package/dist/ui/controller/layouts/index.d.ts.map +1 -0
  43. package/dist/ui/controller/layouts/index.js +34 -0
  44. package/dist/ui/controller/layouts/index.js.map +1 -0
  45. package/dist/ui/controller/layouts/joycon.d.ts +21 -0
  46. package/dist/ui/controller/layouts/joycon.d.ts.map +1 -0
  47. package/dist/ui/controller/layouts/joycon.js +76 -0
  48. package/dist/ui/controller/layouts/joycon.js.map +1 -0
  49. package/dist/ui/controller/layouts/switch-pro.d.ts +12 -0
  50. package/dist/ui/controller/layouts/switch-pro.d.ts.map +1 -0
  51. package/dist/ui/controller/layouts/switch-pro.js +60 -0
  52. package/dist/ui/controller/layouts/switch-pro.js.map +1 -0
  53. package/dist/ui/controller/layouts/xbox.d.ts +11 -0
  54. package/dist/ui/controller/layouts/xbox.d.ts.map +1 -0
  55. package/dist/ui/controller/layouts/xbox.js +59 -0
  56. package/dist/ui/controller/layouts/xbox.js.map +1 -0
  57. package/dist/ui/controller/layouts/zwift.d.ts +27 -0
  58. package/dist/ui/controller/layouts/zwift.d.ts.map +1 -0
  59. package/dist/ui/controller/layouts/zwift.js +62 -0
  60. package/dist/ui/controller/layouts/zwift.js.map +1 -0
  61. package/dist/ui/controller/pad-svg.d.ts +105 -0
  62. package/dist/ui/controller/pad-svg.d.ts.map +1 -0
  63. package/dist/ui/controller/pad-svg.js +289 -0
  64. package/dist/ui/controller/pad-svg.js.map +1 -0
  65. package/dist/ui/controller/parts-map.d.ts +96 -0
  66. package/dist/ui/controller/parts-map.d.ts.map +1 -0
  67. package/dist/ui/controller/parts-map.js +187 -0
  68. package/dist/ui/controller/parts-map.js.map +1 -0
  69. package/dist/ui/controller/styles.d.ts +19 -0
  70. package/dist/ui/controller/styles.d.ts.map +1 -0
  71. package/dist/ui/controller/styles.js +364 -0
  72. package/dist/ui/controller/styles.js.map +1 -0
  73. package/dist/ui/controller/tokens.d.ts +106 -0
  74. package/dist/ui/controller/tokens.d.ts.map +1 -0
  75. package/dist/ui/controller/tokens.js +50 -0
  76. package/dist/ui/controller/tokens.js.map +1 -0
  77. package/dist/ui/controller/types.d.ts +157 -0
  78. package/dist/ui/controller/types.d.ts.map +1 -0
  79. package/dist/ui/controller/types.js +61 -0
  80. package/dist/ui/controller/types.js.map +1 -0
  81. package/dist/ui/index.d.ts +8 -0
  82. package/dist/ui/index.d.ts.map +1 -1
  83. package/dist/ui/index.js +8 -0
  84. package/dist/ui/index.js.map +1 -1
  85. package/dist/ui/keycap.d.ts +14 -0
  86. package/dist/ui/keycap.d.ts.map +1 -1
  87. package/dist/ui/keycap.js +5 -0
  88. package/dist/ui/keycap.js.map +1 -1
  89. package/dist/ui/showcase/gallery.d.ts +13 -1
  90. package/dist/ui/showcase/gallery.d.ts.map +1 -1
  91. package/dist/ui/showcase/gallery.js.map +1 -1
  92. package/dist/ui/showcase/index.d.ts.map +1 -1
  93. package/dist/ui/showcase/index.js +257 -1
  94. package/dist/ui/showcase/index.js.map +1 -1
  95. package/package.json +1 -1
@@ -0,0 +1,200 @@
1
+ /**
2
+ * CONTROLLER PAD — the live drawing of the controller in the rider's hands.
3
+ *
4
+ * ```ts
5
+ * const pad = mountControllerPad(host, { press: session, size: "lg" });
6
+ * // …buttons light as they're pressed, stick caps follow the real axes. Nothing to call per frame.
7
+ * pad.dispose();
8
+ * ```
9
+ *
10
+ * This is the game-side counterpart of the shell's own controller diagram, and it is deliberately fed by
11
+ * **canonical input, not raw hardware**: a game never sees gamepad indices, per-device bindings or analog
12
+ * trigger travel, so this module translates `ButtonName` → drawn position (`parts-map.ts`) and polls
13
+ * `session.axis()` for the sticks. Three consequences worth knowing:
14
+ *
15
+ * 1. **Axes are polled, buttons are not.** `onButton` is an edge stream, so presses cost nothing between
16
+ * events; axes have no event, so when the source exposes `axis()` the pad runs its own
17
+ * `requestAnimationFrame` loop. It stops on `dispose()` and while the tab is hidden, and the
18
+ * `PadDriver` dirty-guard means an idle stick performs zero DOM writes per frame.
19
+ *
20
+ * 2. **The d-pad is shared with the left stick.** `UP`/`DOWN`/`LEFT`/`RIGHT` are emitted by the d-pad
21
+ * *and* by the left stick past its deadzone (see `protocol/buttons.ts`), and nothing in the canonical
22
+ * stream says which. When `axis()` is available we suppress the d-pad highlight for a direction the
23
+ * stick already explains — so pushing the stick moves the cap instead of falsely lighting the d-pad.
24
+ * Without `axis()` the d-pad lights for both, which is the honest best we can do.
25
+ *
26
+ * 3. **Triggers are clicks.** `LT`/`RT` have no analog travel in this protocol, so their travel meters
27
+ * are driven 0/1 from button state.
28
+ *
29
+ * It also **re-letters itself.** A keycap resolves its glyph set once, on the reasoning that keycaps are
30
+ * cheap to recreate; a controls screen is long-lived and `/hardware` is exactly where a rider swaps pads.
31
+ * So if the source exposes `hardware.subscribe`, the pad rebuilds its drawing in place when the resolved
32
+ * set changes, restoring anything currently held. Callers keep their handle and need to know nothing.
33
+ */
34
+ import { DEFAULT_GLYPH_SET } from "../../protocol/glyphs.js";
35
+ import { layoutForBrand } from "./layouts/index.js";
36
+ import { DPAD_DIRECTIONS, litPartOfButton, litPartOfControl } from "./parts-map.js";
37
+ import { buildPadSvg, createPadDriver, STICK_LIT_DEADZONE } from "./pad-svg.js";
38
+ import { injectPadCss } from "./styles.js";
39
+ const DPAD_NAMES = ["UP", "DOWN", "LEFT", "RIGHT"];
40
+ /** Explicit option → what the rider's hardware reports → the SDK-wide fallback. */
41
+ function resolveGlyphSet(opts) {
42
+ return opts.glyphSet ?? opts.press?.hardware?.current?.glyphSet ?? DEFAULT_GLYPH_SET;
43
+ }
44
+ export function mountControllerPad(host, opts = {}) {
45
+ injectPadCss();
46
+ const root = document.createElement("div");
47
+ root.className = `rydr-pad ${opts.size ?? "md"}${opts.ghost ? " ghost" : ""}`;
48
+ if (opts.accent) {
49
+ root.style.setProperty("--pad-accent", opts.accent);
50
+ root.style.setProperty("--pad-glow", opts.accent);
51
+ }
52
+ host.appendChild(root);
53
+ const live = !opts.ghost && opts.press != null;
54
+ const source = opts.press;
55
+ const hasAxis = live && typeof source?.axis === "function";
56
+ /** Everything currently held, so a rebuild can restore the lit state rather than dropping it. */
57
+ const held = new Set();
58
+ const rebuildCbs = new Set();
59
+ let glyphSet = resolveGlyphSet(opts);
60
+ let pad;
61
+ let driver;
62
+ let layout;
63
+ const availableParts = () => {
64
+ if (!opts.available)
65
+ return null;
66
+ const parts = [];
67
+ for (const name of opts.available) {
68
+ const part = litPartOfButton(name);
69
+ if (part)
70
+ parts.push(part);
71
+ }
72
+ return parts;
73
+ };
74
+ function build() {
75
+ layout = layoutForBrand(opts.brand ?? glyphSet);
76
+ pad = buildPadSvg(layout, { labels: opts.labels ?? true });
77
+ driver = createPadDriver(pad, layout, { allowShellOwned: opts.allowShellOwned });
78
+ root.textContent = "";
79
+ root.appendChild(pad.svg);
80
+ driver.setAvailable(availableParts());
81
+ }
82
+ build();
83
+ /**
84
+ * Apply one button's state to the drawing.
85
+ *
86
+ * The d-pad directions are skipped when we have axes, because the rAF loop is then their single
87
+ * writer — it has to be, since only it knows whether the left stick is explaining the direction. Two
88
+ * writers on the same part would fight every frame.
89
+ */
90
+ function applyButton(name, down) {
91
+ if (hasAxis && DPAD_NAMES.includes(name))
92
+ return;
93
+ const part = litPartOfControl(name);
94
+ if (part)
95
+ driver.setPart(part, down);
96
+ if (name === "LT")
97
+ driver.setMeter("l", down ? 1 : 0);
98
+ if (name === "RT")
99
+ driver.setMeter("r", down ? 1 : 0);
100
+ }
101
+ function applyAllHeld() {
102
+ for (const name of held)
103
+ applyButton(name, true);
104
+ }
105
+ const offButton = live
106
+ ? source?.onButton((e) => {
107
+ if (e.edge === "down")
108
+ held.add(e.name);
109
+ else
110
+ held.delete(e.name);
111
+ applyButton(e.name, e.edge === "down");
112
+ })
113
+ : undefined;
114
+ // Seed from whatever is already held, so mounting mid-press shows the truth immediately.
115
+ if (live && source?.buttonsDown) {
116
+ for (const name of source.buttonsDown())
117
+ held.add(name);
118
+ applyAllHeld();
119
+ }
120
+ // ── axis polling ────────────────────────────────────────────────────────────────────────────────
121
+ let raf = 0;
122
+ function frame() {
123
+ raf = requestAnimationFrame(frame);
124
+ const axis = source?.axis;
125
+ if (!axis)
126
+ return;
127
+ const lx = axis("LX");
128
+ const ly = axis("LY");
129
+ driver.setStick("l", lx, ly);
130
+ driver.setStick("r", axis("RX"), axis("RY"));
131
+ // The suppression rule: light a d-pad arm only if it's held AND the left stick isn't already
132
+ // showing that direction (projection of the stick vector onto the direction, past the deadzone).
133
+ for (const name of DPAD_NAMES) {
134
+ const [vx, vy] = DPAD_DIRECTIONS[name];
135
+ const explained = lx * vx + ly * vy > STICK_LIT_DEADZONE;
136
+ const part = litPartOfButton(name);
137
+ if (part)
138
+ driver.setPart(part, held.has(name) && !explained);
139
+ }
140
+ }
141
+ function startFrames() {
142
+ if (hasAxis && !raf)
143
+ raf = requestAnimationFrame(frame);
144
+ }
145
+ function stopFrames() {
146
+ if (raf)
147
+ cancelAnimationFrame(raf);
148
+ raf = 0;
149
+ }
150
+ const onVisibility = () => {
151
+ if (document.visibilityState === "hidden")
152
+ stopFrames();
153
+ else
154
+ startFrames();
155
+ };
156
+ if (hasAxis) {
157
+ startFrames();
158
+ document.addEventListener("visibilitychange", onVisibility);
159
+ }
160
+ // ── re-lettering ────────────────────────────────────────────────────────────────────────────────
161
+ // Only when the caller did NOT pin a glyph set: an explicit one is a deliberate preview.
162
+ const offHardware = !opts.glyphSet && live
163
+ ? source?.hardware?.subscribe?.((snapshot) => {
164
+ const next = snapshot.glyphSet ?? DEFAULT_GLYPH_SET;
165
+ if (next === glyphSet)
166
+ return; // a second pad of the same family is a non-event
167
+ glyphSet = next;
168
+ build();
169
+ applyAllHeld();
170
+ for (const cb of rebuildCbs)
171
+ cb();
172
+ })
173
+ : undefined;
174
+ return {
175
+ root,
176
+ svg: () => pad,
177
+ driver: () => driver,
178
+ layout: () => layout,
179
+ glyphSet: () => glyphSet,
180
+ onRebuild(cb) {
181
+ rebuildCbs.add(cb);
182
+ return () => rebuildCbs.delete(cb);
183
+ },
184
+ setVisible(on) {
185
+ root.style.display = on ? "" : "none";
186
+ },
187
+ dispose() {
188
+ offButton?.();
189
+ offHardware?.();
190
+ stopFrames();
191
+ document.removeEventListener("visibilitychange", onVisibility);
192
+ // Release everything before detaching: a button held at teardown must never leave a lit pad
193
+ // behind if the caller re-parents or re-mounts the node.
194
+ driver.clearAll();
195
+ rebuildCbs.clear();
196
+ root.remove();
197
+ },
198
+ };
199
+ }
200
+ //# sourceMappingURL=controller-pad.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller-pad.js","sourceRoot":"","sources":["../../../src/ui/controller/controller-pad.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The controller family of `@rydr/game-sdk/ui` — one drawing of the rider's controller, and the two
3
+ * views built on it.
4
+ *
5
+ * mountControllerPad the live pad: buttons light on press, stick caps follow the real axes
6
+ * mountControllerMap STATIC — the pad flanked by action callouts, each joined by a line to its button
7
+ * mountComboDemo DYNAMIC — a looping animation of the combination one action requires
8
+ *
9
+ * A game describes its controls once, declaratively, and the SDK owns everything else — which physical
10
+ * button that is on the rider's pad, the letter printed on it, where the callout sits, how the line
11
+ * routes, and how the demo animates. See `tokens.ts` for the vocabulary and `parts-map.ts` for the
12
+ * positional mapping that makes one action list correct on every controller.
13
+ */
14
+ export * from "./types.js";
15
+ export * from "./tokens.js";
16
+ export * from "./parts-map.js";
17
+ export * from "./layouts/index.js";
18
+ export * from "./pad-svg.js";
19
+ export * from "./input-chip.js";
20
+ export * from "./combo-strip.js";
21
+ export * from "./controller-pad.js";
22
+ export * from "./controller-map.js";
23
+ export * from "./combo-demo.js";
24
+ export * from "./control-trainer.js";
25
+ export { injectPadCss } from "./styles.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The controller family of `@rydr/game-sdk/ui` — one drawing of the rider's controller, and the two
3
+ * views built on it.
4
+ *
5
+ * mountControllerPad the live pad: buttons light on press, stick caps follow the real axes
6
+ * mountControllerMap STATIC — the pad flanked by action callouts, each joined by a line to its button
7
+ * mountComboDemo DYNAMIC — a looping animation of the combination one action requires
8
+ *
9
+ * A game describes its controls once, declaratively, and the SDK owns everything else — which physical
10
+ * button that is on the rider's pad, the letter printed on it, where the callout sits, how the line
11
+ * routes, and how the demo animates. See `tokens.ts` for the vocabulary and `parts-map.ts` for the
12
+ * positional mapping that makes one action list correct on every controller.
13
+ */
14
+ export * from "./types.js";
15
+ export * from "./tokens.js";
16
+ export * from "./parts-map.js";
17
+ export * from "./layouts/index.js";
18
+ export * from "./pad-svg.js";
19
+ export * from "./input-chip.js";
20
+ export * from "./combo-strip.js";
21
+ export * from "./controller-pad.js";
22
+ export * from "./controller-map.js";
23
+ export * from "./combo-demo.js";
24
+ export * from "./control-trainer.js";
25
+ export { injectPadCss } from "./styles.js";
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/controller/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * INPUT CHIP — the small pictogram for one control, and the atom both controller views are built from.
3
+ *
4
+ * One factory, five renderers, chosen by the token:
5
+ *
6
+ * DIAMOND_* → `createKeycap` (the kit's existing face-button keycap)
7
+ * UP/DOWN/LEFT/RIGHT, R* → `createDpadKeycap` (the kit's chevron-on-steel keycap)
8
+ * LT / RT / OPTIONS → `createLabelKeycap` (the kit's pill: "L2"/"ZL", "Menu"/"Options"/"+")
9
+ * LSTICK / RSTICK → a stick pictogram, cap centred inside four outward arrows
10
+ * LSTICK / RSTICK :direction → the same pictogram with ONE arrow, cap already slid that way
11
+ * LSTICK_PRESS / RSTICK_PRESS → a stick pictogram of the cap CLICKED: sunk inside a collar,
12
+ * with a chevron pressing down into it
13
+ *
14
+ * The sticks are pictures rather than lettered chips throughout, because that is the one control where
15
+ * the letter tells a rider nothing: "L3" does not say *click the stick*, and it changes per brand on
16
+ * top of that. The printed label still reaches them through the chip's tooltip and assistive tech.
17
+ *
18
+ * All the button shapes REUSE the keycap kit rather than redrawing it, so a control looks identical in a
19
+ * controls legend and in an in-game prompt — same shape, same per-role hue, same letter for the rider's
20
+ * own pad. Only the shapes the kit didn't have are new, and they're inline SVG built with
21
+ * `createElementNS` from string path constants, exactly as `keycap.ts` does with its `CHEVRON`: this SDK
22
+ * ships **no non-TS assets** and adds no build step.
23
+ *
24
+ * **Press wiring lives here, not in the keycap.** The keycaps are built without their own `press`
25
+ * option, because `createDpadKeycap("UP")` listens for `UP` and there is no way to ask it to listen for
26
+ * `RUP` instead. Doing it in one place covers all five renderers uniformly and lets the combo demo drive
27
+ * exactly the same `setPressed` path that real input drives.
28
+ */
29
+ import type { ButtonEdge } from "../../protocol/buttons.js";
30
+ import { type GlyphSet } from "../../protocol/glyphs.js";
31
+ import { type ComboToken, type ControlName } from "./tokens.js";
32
+ /**
33
+ * A control-event source. A `PlatformSession` satisfies it structurally.
34
+ *
35
+ * Typed on {@link ControlName} rather than `ButtonName` so a SHELL-side source can drive the shell-owned
36
+ * controls too — a session only ever emits the `ButtonName` subset, and still satisfies this.
37
+ */
38
+ export interface ChipPressSource {
39
+ onButton(cb: (e: {
40
+ name: ControlName;
41
+ edge: ButtonEdge;
42
+ }) => void): () => void;
43
+ }
44
+ export interface InputChipOptions {
45
+ /** Which controller's lettering to draw. Default {@link DEFAULT_GLYPH_SET}. */
46
+ glyphSet?: GlyphSet;
47
+ /** Wire to real input: the chip shows its pressed state while ITS control is held. */
48
+ press?: ChipPressSource;
49
+ /** Per-role hue on face keycaps (confirm green, back amber). Default true, as elsewhere in the kit. */
50
+ colored?: boolean;
51
+ /** Drawing convention for the joystick pictograms. Default {@link DEFAULT_STICK_STYLE}. */
52
+ stickStyle?: StickPictogramStyle;
53
+ }
54
+ /**
55
+ * What a chip is saying, for a guided lesson. Mirrors {@link PadPartState} so the chip in the card and
56
+ * the button on the drawing can never disagree.
57
+ */
58
+ export type InputChipState = "idle" | "hint" | "active" | "done";
59
+ export interface InputChip {
60
+ /** The element to place. Sized to share a baseline with the kit's 38px keycap. */
61
+ readonly el: HTMLElement;
62
+ /** Pressed/held state. Driven by real input when `press` was given, and by the combo demo. */
63
+ setPressed(on: boolean): void;
64
+ /** Lesson state: `hint` = do this, `active` = doing it, `done` = finished. */
65
+ setState(state: InputChipState): void;
66
+ /**
67
+ * Deflect a stick chip's cap. `x`/`y` are −1..1 in the SDK's convention (right = +1, **up = +1**).
68
+ * A no-op on every other chip kind, so callers can drive a whole strip without branching.
69
+ */
70
+ setDeflection(x: number, y: number): void;
71
+ dispose(): void;
72
+ }
73
+ /**
74
+ * Which drawing convention to use for the joystick pictograms. Three real ones from the industry, kept
75
+ * as an option because they trade off differently and the right answer is a judgement call:
76
+ *
77
+ * - **`"topdown"`** — the abstract plan view: a well, a cap dot, outline chevrons. Compact and neutral,
78
+ * the PlayStation/Steam-overlay convention. Weakest at small sizes, and the *click* is its hard case:
79
+ * pressing along the view axis is exactly what a top-down view cannot show.
80
+ * - **`"profile"`** — the hybrid the free prompt packs (Kenney, Xelu) settled on, and the clearest of
81
+ * the three: **plan view with bold filled arrows for directions**, and a **side view for the click** —
82
+ * a real stick with a shaft and a thumb pad, being pushed down by a solid arrow. Each gesture gets the
83
+ * viewpoint that can actually depict it.
84
+ * - **`"glyph"`** — the bold console-UI mark (Xbox / Steam Input): a solid disc with solid triangles,
85
+ * and a click drawn as a heavy ring with an arrow inside it. Loudest and most legible far away;
86
+ * least literal about the hardware.
87
+ *
88
+ * Compare them in the showcase's "Joystick pictograms" section before changing {@link DEFAULT_STICK_STYLE}.
89
+ */
90
+ export type StickPictogramStyle = "topdown" | "profile" | "glyph";
91
+ /** The style used when a caller doesn't ask for one. */
92
+ export declare const DEFAULT_STICK_STYLE: StickPictogramStyle;
93
+ /**
94
+ * Build the chip for one control.
95
+ *
96
+ * Always returns something drawable: an unrecognised token falls through to a text chip carrying
97
+ * `buttonLabel`'s own fallback (the name itself), so a caller can never render an empty box.
98
+ */
99
+ export declare function createInputChip(token: ComboToken, opts?: InputChipOptions): InputChip;
100
+ //# sourceMappingURL=input-chip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-chip.d.ts","sourceRoot":"","sources":["../../../src/ui/controller/input-chip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAA+C,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGtG,OAAO,EAAgD,KAAK,UAAU,EAAE,KAAK,WAAW,EAAiB,MAAM,aAAa,CAAC;AAE7H;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChF;AAED,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,sFAAsF;IACtF,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,uGAAuG;IACvG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,mBAAmB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,OAAO,IAAI,IAAI,CAAC;CACjB;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAElE,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,EAAE,mBAA+B,CAAC;AA8KlE;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,GAAE,gBAAqB,GAAG,SAAS,CAmHzF"}