@benev/tact 0.1.1 → 0.2.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 (109) hide show
  1. package/README.md +30 -16
  2. package/package.json +13 -12
  3. package/s/deck/deck.ts +1 -14
  4. package/s/deck/index.ts +1 -2
  5. package/s/deck/parts/db.ts +2 -3
  6. package/s/deck/views/bindings/view.ts +95 -0
  7. package/s/deck/views/overlay/view.ts +46 -0
  8. package/s/demo/game/parts/renderer.ts +4 -5
  9. package/s/demo/game/parts/state.ts +1 -2
  10. package/s/demo/main.bundle.ts +1 -4
  11. package/s/demo/ui/theater/styles.css.ts +1 -2
  12. package/s/demo/ui/theater/view.ts +47 -52
  13. package/s/demo/ui/theater/virtual/view.ts +10 -12
  14. package/s/index.html.ts +53 -44
  15. package/s/nubs/index.ts +3 -4
  16. package/s/nubs/lookpad/{component.ts → view.ts} +10 -16
  17. package/s/nubs/stick/{component.ts → view.ts} +27 -34
  18. package/s/nubs/vpad/{component.ts → view.ts} +25 -33
  19. package/s/utils/circular-clamp.ts +1 -2
  20. package/s/utils/gamepads.ts +2 -2
  21. package/x/core/devices/standard/stick.d.ts +2 -2
  22. package/x/deck/deck.d.ts +0 -7
  23. package/x/deck/deck.js +1 -9
  24. package/x/deck/deck.js.map +1 -1
  25. package/x/deck/index.d.ts +1 -2
  26. package/x/deck/index.js +1 -2
  27. package/x/deck/index.js.map +1 -1
  28. package/x/deck/parts/db.d.ts +3 -3
  29. package/x/deck/parts/db.js.map +1 -1
  30. package/x/deck/parts/overlay-visibility.d.ts +3 -3
  31. package/x/deck/views/bindings/style.css.js.map +1 -0
  32. package/x/deck/views/bindings/view.d.ts +2 -0
  33. package/x/deck/views/bindings/view.js +80 -0
  34. package/x/deck/views/bindings/view.js.map +1 -0
  35. package/x/deck/views/overlay/style.css.js.map +1 -0
  36. package/x/deck/views/overlay/view.d.ts +2 -0
  37. package/x/deck/views/overlay/view.js +40 -0
  38. package/x/deck/views/overlay/view.js.map +1 -0
  39. package/x/demo/game/parts/renderer.js +4 -4
  40. package/x/demo/game/parts/renderer.js.map +1 -1
  41. package/x/demo/game/parts/state.js +1 -1
  42. package/x/demo/game/parts/state.js.map +1 -1
  43. package/x/demo/main.bundle.js +1 -5
  44. package/x/demo/main.bundle.js.map +1 -1
  45. package/x/demo/main.bundle.min.js +242 -233
  46. package/x/demo/main.bundle.min.js.map +4 -4
  47. package/x/demo/ui/theater/styles.css.js +1 -1
  48. package/x/demo/ui/theater/view.d.ts +1 -367
  49. package/x/demo/ui/theater/view.js +27 -32
  50. package/x/demo/ui/theater/view.js.map +1 -1
  51. package/x/demo/ui/theater/virtual/view.d.ts +1 -1
  52. package/x/demo/ui/theater/virtual/view.js +6 -6
  53. package/x/demo/ui/theater/virtual/view.js.map +1 -1
  54. package/x/index.html +41 -125
  55. package/x/index.html.js +50 -39
  56. package/x/index.html.js.map +1 -1
  57. package/x/nubs/index.d.ts +3 -4
  58. package/x/nubs/index.js +3 -4
  59. package/x/nubs/index.js.map +1 -1
  60. package/x/nubs/lookpad/view.d.ts +1 -0
  61. package/x/nubs/lookpad/{component.js → view.js} +11 -14
  62. package/x/nubs/lookpad/view.js.map +1 -0
  63. package/x/nubs/stick/view.d.ts +2 -0
  64. package/x/nubs/stick/{component.js → view.js} +28 -34
  65. package/x/nubs/stick/view.js.map +1 -0
  66. package/x/nubs/vpad/view.d.ts +2 -0
  67. package/x/nubs/vpad/{component.js → view.js} +26 -32
  68. package/x/nubs/vpad/view.js.map +1 -0
  69. package/x/utils/circular-clamp.js +1 -1
  70. package/x/utils/circular-clamp.js.map +1 -1
  71. package/x/utils/gamepads.js +2 -2
  72. package/s/deck/components/components.ts +0 -22
  73. package/s/deck/components/deck-bindings/component.ts +0 -99
  74. package/s/deck/components/deck-overlay/component.ts +0 -51
  75. package/s/deck/components/framework.ts +0 -17
  76. package/s/nubs/components.ts +0 -14
  77. package/s/utils/types.ts +0 -19
  78. package/x/deck/components/components.d.ts +0 -14
  79. package/x/deck/components/components.js +0 -9
  80. package/x/deck/components/components.js.map +0 -1
  81. package/x/deck/components/deck-bindings/component.d.ts +0 -6
  82. package/x/deck/components/deck-bindings/component.js +0 -83
  83. package/x/deck/components/deck-bindings/component.js.map +0 -1
  84. package/x/deck/components/deck-bindings/style.css.js.map +0 -1
  85. package/x/deck/components/deck-overlay/component.d.ts +0 -6
  86. package/x/deck/components/deck-overlay/component.js +0 -44
  87. package/x/deck/components/deck-overlay/component.js.map +0 -1
  88. package/x/deck/components/deck-overlay/style.css.js.map +0 -1
  89. package/x/deck/components/framework.d.ts +0 -7
  90. package/x/deck/components/framework.js +0 -13
  91. package/x/deck/components/framework.js.map +0 -1
  92. package/x/nubs/components.d.ts +0 -9
  93. package/x/nubs/components.js +0 -11
  94. package/x/nubs/components.js.map +0 -1
  95. package/x/nubs/lookpad/component.d.ts +0 -4
  96. package/x/nubs/lookpad/component.js.map +0 -1
  97. package/x/nubs/stick/component.d.ts +0 -368
  98. package/x/nubs/stick/component.js.map +0 -1
  99. package/x/nubs/vpad/component.d.ts +0 -368
  100. package/x/nubs/vpad/component.js.map +0 -1
  101. package/x/utils/types.d.ts +0 -3
  102. package/x/utils/types.js +0 -3
  103. package/x/utils/types.js.map +0 -1
  104. /package/s/deck/{components/deck-bindings → views/bindings}/style.css.ts +0 -0
  105. /package/s/deck/{components/deck-overlay → views/overlay}/style.css.ts +0 -0
  106. /package/x/deck/{components/deck-bindings → views/bindings}/style.css.d.ts +0 -0
  107. /package/x/deck/{components/deck-bindings → views/bindings}/style.css.js +0 -0
  108. /package/x/deck/{components/deck-overlay → views/overlay}/style.css.d.ts +0 -0
  109. /package/x/deck/{components/deck-overlay → views/overlay}/style.css.js +0 -0
package/README.md CHANGED
@@ -23,7 +23,9 @@ it's good at user-customizable keybindings, multiple gamepad support, and mobile
23
23
  ## 🍋 tact deck
24
24
  > *full setup with ui, batteries included*
25
25
 
26
- the deck ties together all the important pieces of tact into a single user experience, complete with ui components.
26
+ the deck ties together all the important pieces of tact into a single user experience, complete with ui views.
27
+
28
+ tact's ui is built with [`@e280/sly` shadow views](https://github.com/e280/sly).
27
29
 
28
30
  ### 🛹 deck setup
29
31
  - **import stuff from tact**
@@ -77,13 +79,18 @@ the deck ties together all the important pieces of tact into a single user exper
77
79
  ```
78
80
 
79
81
  ### 🛹 deck ui: the overlay
80
- - **register the deck's web components to the dom**
82
+ - **render the deck overlay with sly**
81
83
  ```ts
82
- deck.registerComponents()
84
+ import {dom} from "@e280/sly"
85
+
86
+ dom.render(
87
+ dom("#game-ui"),
88
+ tact.DeckOverlay(deck),
89
+ )
83
90
  ```
84
91
  - **place the ui on top of your game canvas**
85
92
  ```html
86
- <deck-overlay></deck-overlay>
93
+ <div id="game-ui"></div>
87
94
  ```
88
95
 
89
96
 
@@ -390,25 +397,33 @@ the hub embraces that analogy, helping you coordinate the plugging and unpluggin
390
397
  > *mobile ui like virtual thumbsticks and buttons*
391
398
 
392
399
  ### 📱 nubs setup
393
- - **register nub components to dom**
400
+ - **render nub views with sly**
394
401
  ```ts
395
- tact.registerNubs()
396
- ```
397
- - **place nub components onto your html page**
398
- ```html
399
- <nub-stick></nub-stick>
402
+ import {dom} from "@e280/sly"
403
+
404
+ const stick = new tact.StickDevice()
405
+
406
+ dom.render(
407
+ dom("#controls"),
408
+ tact.NubStick(stick),
409
+ )
400
410
  ```
401
411
 
402
412
  ### 📱 nub stick
403
- - **place a nub-stick onto your page**
413
+ - **place a mount point onto your page**
404
414
  ```html
405
- <nub-stick></nub-stick>
415
+ <div id="controls"></div>
406
416
  ```
407
- - **get the stick device, plug it into your hub or whatever**
417
+ - **make the stick device yourself, then plug it into your hub or whatever**
408
418
  ```ts
409
- const nubStick = document.queryElement<tact.NubStick>("nub-stick")!
419
+ const stick = new tact.StickDevice()
410
420
 
411
- deck.hub.plug(nubStick.device)
421
+ dom.render(
422
+ dom("#controls"),
423
+ tact.NubStick(stick),
424
+ )
425
+
426
+ deck.hub.plug(stick)
412
427
  ```
413
428
 
414
429
 
@@ -418,4 +433,3 @@ the hub embraces that analogy, helping you coordinate the plugging and unpluggin
418
433
 
419
434
  ## 🍋 tact is by https://benevolent.games/
420
435
  > *building the future of web games*
421
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benev/tact",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "keybindings and gamepad support for web games",
5
5
  "license": "MIT",
6
6
  "author": "Chase Moskal <chasemoskal@gmail.com>",
@@ -16,34 +16,35 @@
16
16
  "s"
17
17
  ],
18
18
  "scripts": {
19
- "build": "run-s _clean _tsc _ln _scute",
19
+ "build": "octo-s --npm-run _clean _tsc _ln _scute",
20
+ "dev": "octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'hottie x'",
20
21
  "_clean": "rm -rf x",
21
22
  "_tsc": "tsc",
22
23
  "_scute": "scute -v",
23
- "start": "octo 'scute -vw' 'tsc -w' 'node --watch x/tests.test.js' 'http-server x -c-1'",
24
24
  "_ln": "run-s _ln-s _ln-assets",
25
25
  "_ln-s": "ln -s \"$(realpath s)\" x/s",
26
26
  "_ln-assets": "ln -s \"$(realpath assets)\" x/assets",
27
27
  "test": "node x/tests.test.js",
28
- "test-debug": "node inspect x/tests.test.js",
29
28
  "count": "find s -path '*/_archive' -prune -o -name '*.ts' -exec wc -l {} +"
30
29
  },
31
30
  "peerDependencies": {
32
31
  "lit": "^3.3.2"
33
32
  },
34
33
  "dependencies": {
35
- "@benev/math": "^0.2.0",
36
- "@e280/kv": "^0.1.0",
37
- "@e280/sly": "^0.2.5",
38
- "@e280/strata": "^0.2.8",
39
- "@e280/stz": "^0.2.24"
34
+ "@benev/math": "^0.3.0-5",
35
+ "@e280/kv": "^0.1.2",
36
+ "@e280/sly": "^0.3.7",
37
+ "@e280/strata": "^0.3.3",
38
+ "@e280/stz": "^0.2.32"
40
39
  },
41
40
  "devDependencies": {
42
- "@e280/science": "^0.1.8",
43
- "@e280/scute": "^0.1.5",
41
+ "@e280/hottie": "^0.1.0",
42
+ "@e280/octo": "^0.1.0",
43
+ "@e280/science": "^0.1.10",
44
+ "@e280/scute": "^0.3.2",
44
45
  "http-server": "^14.1.1",
45
46
  "npm-run-all": "^4.1.5",
46
- "typescript": "^5.9.3"
47
+ "typescript": "^6.0.2"
47
48
  },
48
49
  "repository": {
49
50
  "type": "git",
package/s/deck/deck.ts CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
2
  import {Kv} from "@e280/kv"
3
- import {dom} from "@e280/sly"
4
- import {disposer, ob, range} from "@e280/stz"
3
+ import {disposer, range} from "@e280/stz"
5
4
 
6
5
  import {Db} from "./parts/db.js"
7
6
  import {Hub} from "../core/hub/hub.js"
@@ -13,7 +12,6 @@ import {makeMetaBindings} from "../core/hub/meta-bindings.js"
13
12
  import {DeviceSkins} from "./parts/device-skins/device-skin.js"
14
13
  import {OverlayVisibility} from "./parts/overlay-visibility.js"
15
14
  import {PrimaryDevice} from "../core/devices/standard/primary.js"
16
- import {deckComponents, DeckViews} from "./components/components.js"
17
15
 
18
16
  export type DeckOptions<B extends Bindings, MB extends MetaBindings = any> = {
19
17
  kv: Kv
@@ -46,17 +44,6 @@ export class Deck<B extends Bindings, MB extends MetaBindings = any> {
46
44
  primaryDevice = new PrimaryDevice()
47
45
  overlayVisibility: OverlayVisibility
48
46
 
49
- components = deckComponents(this)
50
-
51
- views = (
52
- ob(this.components as any)
53
- .map(c => (...a: any[]) => c.view(this, ...a))
54
- ) as DeckViews
55
-
56
- registerComponents() {
57
- dom.register(this.components)
58
- }
59
-
60
47
  constructor(
61
48
  public baseBindings: B,
62
49
  public baseMetaBindings: MB,
package/s/deck/index.ts CHANGED
@@ -7,8 +7,7 @@ export * from "./parts/local-storage-kv.js"
7
7
  export * from "./parts/merge-bindings.js"
8
8
  export * from "./parts/overlay-visibility.js"
9
9
 
10
- export * from "./components/deck-overlay/component.js"
11
- export * from "./components/deck-overlay/style.css.js"
10
+ export * from "./views/overlay/view.js"
12
11
 
13
12
  export * from "./deck.js"
14
13
 
@@ -1,6 +1,6 @@
1
1
 
2
2
  import {disposer, Hex} from "@e280/stz"
3
- import {signal, SignalFn} from "@e280/strata"
3
+ import {signal, Signal} from "@e280/strata"
4
4
  import {StorageDriver, Store} from "@e280/kv"
5
5
 
6
6
  import {Bindings} from "../../core/bindings/types.js"
@@ -16,7 +16,7 @@ export class Db {
16
16
 
17
17
  constructor(
18
18
  private store: Store<CatalogData>,
19
- public $catalog: SignalFn<Catalog>,
19
+ public $catalog: Signal<Catalog>,
20
20
  ) {
21
21
 
22
22
  this.dispose.schedule(
@@ -63,4 +63,3 @@ export class Db {
63
63
  })
64
64
  }
65
65
  }
66
-
@@ -0,0 +1,95 @@
1
+
2
+ import {html} from "lit"
3
+ import {bytename} from "@e280/stz"
4
+ import {cssReset, shadow, useCss, useName, useSignal} from "@e280/sly"
5
+
6
+ import {Deck} from "../../deck.js"
7
+ import styleCss from "./style.css.js"
8
+ import {Port} from "../../../core/hub/port.js"
9
+ import {Profile} from "../../parts/catalog.js"
10
+ import {Atom, Bindings, Bracket} from "../../../core/bindings/types.js"
11
+
12
+ export const DeckBindings = shadow((deck: Deck<any>) => {
13
+ useCss(cssReset, styleCss)
14
+ useName("deck-bindings")
15
+ const {db, hub} = deck
16
+
17
+ const catalog = db.$catalog()
18
+ const defaultProfile: Profile = {id: "default", label: "default", bindings: deck.baseBindings}
19
+ const allProfiles = [defaultProfile, ...catalog.profiles.values()]
20
+ const $selectedProfileId = useSignal("default")
21
+ const profile = db.$catalog().getProfile($selectedProfileId()) ?? defaultProfile
22
+
23
+ function renderPort(_port: Port<Bindings>, index: number) {
24
+ const portProfile = catalog.getProfileForPort(index) ?? defaultProfile
25
+ return html`
26
+ <div class=port>
27
+ <span>port ${index + 1}</span>
28
+ <select>
29
+ ${allProfiles.map(profile => html`
30
+ <option
31
+ data-id="${profile.id}"
32
+ ?selected="${profile.id === portProfile.id}">
33
+ ${profile.label}
34
+ </option>
35
+ `)}
36
+ </select>
37
+ </div>
38
+ `
39
+ }
40
+
41
+ function renderBindingBracket(entry: [string, unknown]) {
42
+ const [mode, bracket] = entry as [string, Bracket]
43
+ return html`
44
+ <div class=bracket>
45
+ <strong class=mode>${mode}</strong>
46
+ <div>${Object.entries(bracket).map(renderBinds)}</div>
47
+ </div>
48
+ `
49
+ }
50
+
51
+ function renderBinds([action, _atom]: [action: string, atom: Atom]) {
52
+ return html`
53
+ <div class=bind>
54
+ <span class=action>${action}</span>
55
+ </div>
56
+ `
57
+ }
58
+
59
+ const clickClone = async() => {
60
+ const {bindings} = profile
61
+ const label = bytename.random(4)
62
+ const p = await db.createProfile(label, bindings)
63
+ $selectedProfileId(p.id)
64
+ }
65
+
66
+ const deleteProfile = (id: string) => async() => {
67
+ await db.deleteProfile(id)
68
+ }
69
+
70
+ const onSelected = (event: InputEvent) => {
71
+ const select = event.target as HTMLSelectElement
72
+ const id = select.value
73
+ $selectedProfileId(id)
74
+ }
75
+
76
+ return html`
77
+ <div class=portlist>
78
+ ${hub.ports.map(renderPort)}
79
+ </div>
80
+
81
+ <div class=bindable>
82
+ <select @input="${onSelected}">
83
+ ${allProfiles.map(p => html`
84
+ <option value="${p.id}" ?selected="${p.id === profile.id}">${p.label}</option>
85
+ `)}
86
+ </select>
87
+ <button @click="${clickClone}">clone</button>
88
+ <button ?disabled="${profile.id === defaultProfile.id}" @click="${deleteProfile(profile.id)}">delete</button>
89
+ <div class=bindings>
90
+ ${Object.entries(profile.bindings).map(renderBindingBracket)}
91
+ </div>
92
+ </div>
93
+ `
94
+ })
95
+
@@ -0,0 +1,46 @@
1
+
2
+ import {html} from "lit"
3
+ import {cssReset, shadow, useCss, useName} from "@e280/sly"
4
+ import {Deck} from "../../deck.js"
5
+ import styleCss from "./style.css.js"
6
+ import {Device} from "../../../core/devices/device.js"
7
+
8
+ export const DeckOverlay = shadow((deck: Deck<any>) => {
9
+ useCss(cssReset, styleCss)
10
+ useName("deck-overlay")
11
+ const {hub, deviceSkins, overlayVisibility: {$visible, $showLabels}} = deck
12
+
13
+ function renderDevice(device: Device) {
14
+ const skin = deviceSkins.get(device)
15
+ const style = `--color: ${skin.color};`
16
+ const next = () => hub.shimmy(device, 1)
17
+ const previous = () => hub.shimmy(device, -1)
18
+ return html`
19
+ <div class=device style="${style}">
20
+ <div class="primary row">
21
+ <button @click="${previous}">&lt;</button>
22
+ <div class=icon>${skin.icon}</div>
23
+ <button @click="${next}">&gt;</button>
24
+ </div>
25
+
26
+ ${$showLabels() ? html`
27
+ <div class="secondary row">
28
+ <div class=label>${skin.label}</div>
29
+ </div>
30
+ ` : null}
31
+ </div>
32
+ `
33
+ }
34
+
35
+ return html`
36
+ <div class=portlist ?data-active="${$visible()}">
37
+ ${hub.ports.map((port, index) => html`
38
+ <div class=port>
39
+ <header>P${index + 1}</header>
40
+ ${port.devices.array().map(renderDevice)}
41
+ </div>
42
+ `)}
43
+ </div>
44
+ `
45
+ })
46
+
@@ -22,16 +22,16 @@ export class Renderer {
22
22
 
23
23
  /** take a game-state position and resolve it into canvas coordinates */
24
24
  resolve(position: Vec2) {
25
- return position.clone()
25
+ return position.dup()
26
26
 
27
27
  // 0-1 relative to arena scale
28
- .divide(this.state.arenaSize)
28
+ .div(this.state.arenaSize)
29
29
 
30
30
  // flip y axis
31
- .morph(v => {v.y = 1 - v.y})
31
+ .morph((v: Vec2) => {v.y = 1 - v.y})
32
32
 
33
33
  // stretch to the size of the canvas
34
- .multiply_(this.canvas.width, this.canvas.height)
34
+ .mul_(this.canvas.width, this.canvas.height)
35
35
  }
36
36
 
37
37
  render() {
@@ -110,4 +110,3 @@ export class Renderer {
110
110
  ctx.fillText(agent.label, x, y)
111
111
  }
112
112
  }
113
-
@@ -11,7 +11,7 @@ export class State {
11
11
  agent.label = label
12
12
  agent.position
13
13
  .set_(0.5, 0.5)
14
- .multiply(this.arenaSize)
14
+ .mul(this.arenaSize)
15
15
  this.agents.add(agent)
16
16
  return agent
17
17
  }
@@ -21,4 +21,3 @@ export class State {
21
21
  return this
22
22
  }
23
23
  }
24
-
@@ -5,9 +5,6 @@ import {DemoTheater} from "./ui/theater/view.js"
5
5
 
6
6
  const game = await Game.load()
7
7
 
8
- dom.register({
9
- DemoTheater: class extends DemoTheater { game = game },
10
- })
8
+ dom.render(dom("#demo-theater"), DemoTheater(game))
11
9
 
12
10
  console.log("🎮 tact")
13
-
@@ -33,7 +33,7 @@ export const styles = css`
33
33
  outline: 1px solid red;
34
34
  }
35
35
 
36
- [deck="overlay"] {
36
+ [view="deck-overlay"] {
37
37
  position: absolute;
38
38
  top: 10%;
39
39
  left: 0;
@@ -55,4 +55,3 @@ export const styles = css`
55
55
  }
56
56
 
57
57
  `
58
-
@@ -1,60 +1,55 @@
1
1
 
2
2
  import {html} from "lit"
3
3
  import {repeat} from "lit/directives/repeat.js"
4
- import {BaseElement, cssReset, view} from "@e280/sly"
4
+ import {cssReset, shadow, useCss, useMount, useRender} from "@e280/sly"
5
5
 
6
6
  import {styles} from "./styles.css.js"
7
7
  import {Game} from "../../game/game.js"
8
8
  import {VirtualDeviceView} from "./virtual/view.js"
9
9
  import {VirtualDevice} from "../../game/parts/virtual-device.js"
10
- import {DeckBindings} from "../../../deck/components/deck-bindings/component.js"
11
-
12
- export class DemoTheater extends (
13
- view(use => (game: Game) => {
14
- use.css(cssReset, styles)
15
- use.mount(() => game.loop(60))
16
- use.mount(() => game.deck.hub.on(use.render))
17
-
18
- const addVirtual = () => game.plug(new VirtualDevice(game.deck.hub))
19
- const revealOverlay = () => game.deck.overlayVisibility.bump()
20
-
21
- const virtualDevices = game.deck.hub.ports
22
- .flatMap(port => port.devices.array())
23
- .filter(device => device instanceof VirtualDevice)
24
- .map(device => ({device, skin: game.deck.deviceSkins.get(device)}))
25
- .sort((a, b) => a.skin.label < b.skin.label ? -1 : 1)
26
-
27
- return html`
28
- <div class=surface>
29
- ${game.renderer.canvas}
30
- ${game.deck.views.DeckOverlay()}
31
- </div>
32
-
33
- <div class=dlist>
34
- ${repeat(
35
- virtualDevices,
36
- d => d.skin.label,
37
- ({device, skin}) => {
38
- return VirtualDeviceView
39
- .props(game.deck.hub, device, skin)
40
- .attr("style", `--color: ${skin.color};`)
41
- .render()
42
- },
43
- )}
44
-
45
- <button @click="${addVirtual}">
46
-
47
- </button>
48
-
49
- <button @click="${revealOverlay}">
50
- 👁️
51
- </button>
52
- </div>
53
-
54
- ${DeckBindings.view(game.deck)}
55
- `
56
- })
57
- .component(class extends BaseElement { game!: Game })
58
- .props(el => [el.game])
59
- ) {}
60
-
10
+ import {DeckBindings} from "../../../deck/views/bindings/view.js"
11
+ import { DeckOverlay } from "../../../deck/views/overlay/view.js"
12
+
13
+ export const DemoTheater = shadow((game: Game) => {
14
+ useCss(cssReset, styles)
15
+ useMount(() => game.loop(60))
16
+ const render = useRender()
17
+ useMount(() => game.deck.hub.on(render))
18
+
19
+ const addVirtual = () => game.plug(new VirtualDevice(game.deck.hub))
20
+ const revealOverlay = () => game.deck.overlayVisibility.bump()
21
+
22
+ const virtualDevices = game.deck.hub.ports
23
+ .flatMap(port => port.devices.array())
24
+ .filter(device => device instanceof VirtualDevice)
25
+ .map(device => ({device, skin: game.deck.deviceSkins.get(device)}))
26
+ .sort((a, b) => a.skin.label < b.skin.label ? -1 : 1)
27
+
28
+ return html`
29
+ <div class=surface>
30
+ ${game.renderer.canvas}
31
+ ${DeckOverlay(game.deck)}
32
+ </div>
33
+
34
+ <div class=dlist>
35
+ ${repeat(
36
+ virtualDevices,
37
+ d => d.skin.label,
38
+ ({device, skin}) => VirtualDeviceView.with({
39
+ props: [game.deck.hub, device, skin],
40
+ attrs: {style: `--color: ${skin.color};`},
41
+ }),
42
+ )}
43
+
44
+ <button @click="${addVirtual}">
45
+
46
+ </button>
47
+
48
+ <button @click="${revealOverlay}">
49
+ 👁️
50
+ </button>
51
+ </div>
52
+
53
+ ${DeckBindings(game.deck)}
54
+ `
55
+ })
@@ -1,26 +1,25 @@
1
1
 
2
2
  import {html} from "lit"
3
- import {cssReset, view} from "@e280/sly"
3
+ import {cssReset, shadow, useCss, useName} from "@e280/sly"
4
4
  import styleCss from "./style.css.js"
5
5
  import {Hub} from "../../../../core/hub/hub.js"
6
- import {NubStick} from "../../../../nubs/stick/component.js"
6
+ import {NubStick} from "../../../../nubs/stick/view.js"
7
7
  import {VirtualDevice} from "../../../game/parts/virtual-device.js"
8
8
  import {DeviceSkin} from "../../../../deck/parts/device-skins/device-skin.js"
9
9
 
10
- export const VirtualDeviceView = view(use => (
11
- hub: Hub<any>,
12
- device: VirtualDevice,
13
- _deviceSkin: DeviceSkin,
14
- ) => {
15
-
16
- use.styles(cssReset, styleCss)
17
- use.attrs.strings.device = "virtual"
10
+ export const VirtualDeviceView = shadow((
11
+ hub: Hub<any>,
12
+ device: VirtualDevice,
13
+ _deviceSkin: DeviceSkin,
14
+ ) => {
15
+ useCss(cssReset, styleCss)
16
+ useName("virtual-device")
18
17
 
19
18
  const unplug = () => hub.unplug(device)
20
19
 
21
20
  return html`
22
21
  <div class=box>
23
- ${NubStick.view(device)}
22
+ ${NubStick(device)}
24
23
 
25
24
  <button @click="${device.shimmyPrevious}">👈</button>
26
25
  <button @click="${unplug}">💀</button>
@@ -28,4 +27,3 @@ export const VirtualDeviceView = view(use => (
28
27
  </div>
29
28
  `
30
29
  })
31
-