ultimatedarktowerdisplay 0.1.0 → 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.
- package/CHANGELOG.md +16 -0
- package/README.md +44 -24
- package/dist/TowerDisplay.d.ts +6 -2
- package/dist/TowerSideView.d.ts +32 -0
- package/dist/TowerStateReadout.d.ts +2 -1
- package/dist/effectLabels.d.ts +1 -0
- package/dist/index.cjs.js +10710 -17
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +10926 -68
- package/dist/index.esm.js.map +1 -1
- package/dist/types.d.ts +16 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.0] - 2026-04-15
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `TowerSideView` now calls `injectStyles()` so side-view-only mode gets CSS
|
|
14
|
+
- JSDoc for `TowerDisplayOptions.renderers` now correctly documents the default as `['readout', 'side-view']`
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Tests for seal overlay injection, double-dispose safety, and multi-button side selection
|
|
19
|
+
- `applySeals(brokenSeals: SealIdentifier[])` method on `TowerDisplay`, `TowerSideView`, and `ITowerDisplay` — hides seal SVG overlays for broken seals on the currently displayed side; re-evaluates when switching sides
|
|
20
|
+
- `SealIdentifier` re-exported from the package public API
|
|
21
|
+
- `clickToToggleSeals` option on `TowerDisplayOptions` (default `true`) — clicking a seal in the side view toggles its visibility independently of game state; user-toggled state and game-broken state are merged so either alone can hide a seal; toggle state is per-side and is cleared on `dispose()`
|
|
22
|
+
- `clickToToggleSeals` public property on `TowerSideView` for consumers using the class directly
|
|
23
|
+
- Console logging on seal click: logs the side, level, and new visibility state (or notes when toggle is disabled)
|
|
24
|
+
|
|
9
25
|
## [0.1.0] - 2026-03-22
|
|
10
26
|
|
|
11
27
|
### Added
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
DOM-based visual readout for decoded [Ultimate Dark Tower](https://github.com/ChessMess/ultimatedarktower) tower state.
|
|
4
4
|
|
|
5
|
+
**[Live Demo](https://chessmess.github.io/UltimateDarkTowerDisplay/)**
|
|
6
|
+
|
|
5
7
|
This package renders a live tower dashboard into a DOM element. It is intended for tools that already know how to obtain or decode a `TowerState` and want a compact on-screen display of:
|
|
6
8
|
|
|
7
9
|
- LED layers and per-light effects
|
|
@@ -30,13 +32,13 @@ npm install ultimatedarktowerdisplay ultimatedarktower
|
|
|
30
32
|
## Quick Start
|
|
31
33
|
|
|
32
34
|
```ts
|
|
33
|
-
import { TowerDisplay } from
|
|
34
|
-
import { createDefaultTowerState } from
|
|
35
|
+
import { TowerDisplay } from 'ultimatedarktowerdisplay';
|
|
36
|
+
import { createDefaultTowerState } from 'ultimatedarktower';
|
|
35
37
|
|
|
36
|
-
const container = document.getElementById(
|
|
38
|
+
const container = document.getElementById('tower');
|
|
37
39
|
|
|
38
40
|
if (!container) {
|
|
39
|
-
throw new Error(
|
|
41
|
+
throw new Error('Missing #tower container');
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
const display = new TowerDisplay({ container });
|
|
@@ -72,17 +74,13 @@ In most applications the flow looks like this:
|
|
|
72
74
|
Example with a manually adjusted state:
|
|
73
75
|
|
|
74
76
|
```ts
|
|
75
|
-
import { TowerDisplay } from
|
|
76
|
-
import {
|
|
77
|
-
createDefaultTowerState,
|
|
78
|
-
LIGHT_EFFECTS,
|
|
79
|
-
TOWER_AUDIO_LIBRARY,
|
|
80
|
-
} from "ultimatedarktower";
|
|
77
|
+
import { TowerDisplay } from 'ultimatedarktowerdisplay';
|
|
78
|
+
import { createDefaultTowerState, LIGHT_EFFECTS, TOWER_AUDIO_LIBRARY } from 'ultimatedarktower';
|
|
81
79
|
|
|
82
|
-
const container = document.getElementById(
|
|
80
|
+
const container = document.getElementById('tower');
|
|
83
81
|
|
|
84
82
|
if (!container) {
|
|
85
|
-
throw new Error(
|
|
83
|
+
throw new Error('Missing #tower container');
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
const display = new TowerDisplay({ container });
|
|
@@ -133,7 +131,7 @@ type TowerState = {
|
|
|
133
131
|
For a valid starting point, prefer:
|
|
134
132
|
|
|
135
133
|
```ts
|
|
136
|
-
import { createDefaultTowerState } from
|
|
134
|
+
import { createDefaultTowerState } from 'ultimatedarktower';
|
|
137
135
|
|
|
138
136
|
const state = createDefaultTowerState();
|
|
139
137
|
```
|
|
@@ -151,36 +149,58 @@ The example page in [example/index.html](./example/index.html) follows this patt
|
|
|
151
149
|
|
|
152
150
|
### `TowerDisplay`
|
|
153
151
|
|
|
154
|
-
Primary entry point.
|
|
152
|
+
Primary entry point. Composes one or both renderers into a container.
|
|
155
153
|
|
|
156
154
|
```ts
|
|
157
155
|
new TowerDisplay(options: TowerDisplayOptions)
|
|
158
156
|
```
|
|
159
157
|
|
|
160
|
-
| Option
|
|
161
|
-
|
|
|
162
|
-
| `container`
|
|
158
|
+
| Option | Type | Default | Description |
|
|
159
|
+
| -------------------- | -------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
160
|
+
| `container` | `HTMLElement` | — | DOM element that will receive the rendered output |
|
|
161
|
+
| `renderers` | `RendererType \| RendererType[]` | `['readout', 'side-view']` | Which renderer(s) to show: `'readout'`, `'side-view'`, or both |
|
|
162
|
+
| `onSealClick` | `(seal: SealIdentifier) => void` | — | Called whenever the user clicks a seal overlay in the side view |
|
|
163
|
+
| `clickToToggleSeals` | `boolean` | `true` | When true, clicking a seal toggles its visibility independent of game state. Set to `false` to disable. |
|
|
163
164
|
|
|
164
165
|
Methods:
|
|
165
166
|
|
|
166
|
-
- `applyState(state: TowerState): void`
|
|
167
|
-
- `
|
|
168
|
-
- `
|
|
167
|
+
- `applyState(state: TowerState): void` — update all renderers with a new decoded tower state
|
|
168
|
+
- `applySeals(brokenSeals: SealIdentifier[]): void` — hide seal overlays for broken seals; pass the current list of broken seals each time it changes
|
|
169
|
+
- `showIdle(): void` — reset all renderers to their idle placeholder
|
|
170
|
+
- `dispose(): void` — remove all rendered DOM and reset internal state
|
|
171
|
+
|
|
172
|
+
### `TowerSideView`
|
|
173
|
+
|
|
174
|
+
SVG side-view renderer. Shows a rotatable view of one tower face with seal overlays and LED markers. Can be used standalone or composed via `TowerDisplay`.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const view = new TowerSideView(container);
|
|
178
|
+
view.onSealClick = (seal) => console.log(seal);
|
|
179
|
+
view.clickToToggleSeals = true; // default
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Property | Type | Default | Description |
|
|
183
|
+
| -------------------- | -------------------------------- | ------- | ------------------------------------------------------------ |
|
|
184
|
+
| `onSealClick` | `(seal: SealIdentifier) => void` | — | Callback fired on every seal click |
|
|
185
|
+
| `clickToToggleSeals` | `boolean` | `true` | Enables built-in click-to-toggle visibility on seal overlays |
|
|
169
186
|
|
|
170
187
|
### `TowerStateReadout`
|
|
171
188
|
|
|
172
|
-
|
|
189
|
+
Text-based readout renderer. Lower-level; takes a container directly.
|
|
173
190
|
|
|
174
191
|
```ts
|
|
175
192
|
new TowerStateReadout(container: HTMLElement)
|
|
176
193
|
```
|
|
177
194
|
|
|
178
|
-
|
|
195
|
+
Exposes the same methods as `TowerDisplay` (`applyState`, `applySeals`, `showIdle`, `dispose`).
|
|
179
196
|
|
|
180
197
|
### Exported Types
|
|
181
198
|
|
|
182
|
-
- `ITowerDisplay` common interface implemented by
|
|
183
|
-
- `TowerDisplayOptions` configuration object for `TowerDisplay`
|
|
199
|
+
- `ITowerDisplay` — common interface implemented by all renderers
|
|
200
|
+
- `TowerDisplayOptions` — configuration object for `TowerDisplay`
|
|
201
|
+
- `RendererType` — `'readout' | 'side-view'`
|
|
202
|
+
- `TowerSide` — `'north' | 'east' | 'south' | 'west'`
|
|
203
|
+
- `SealIdentifier` — `{ side: TowerSide, level: TowerLevels }`
|
|
184
204
|
|
|
185
205
|
`ultimatedarktowerdisplay` does not re-export tower protocol constants or helpers from `ultimatedarktower`.
|
|
186
206
|
|
package/dist/TowerDisplay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TowerState } from 'ultimatedarktower';
|
|
1
|
+
import type { TowerState, SealIdentifier } from 'ultimatedarktower';
|
|
2
2
|
import type { TowerDisplayOptions, ITowerDisplay } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* TowerDisplay renders decoded tower state into a DOM container.
|
|
@@ -7,15 +7,19 @@ import type { TowerDisplayOptions, ITowerDisplay } from './types';
|
|
|
7
7
|
* ```ts
|
|
8
8
|
* const display = new TowerDisplay({
|
|
9
9
|
* container: document.getElementById('tower')!,
|
|
10
|
+
* renderers: ['readout', 'side-view'],
|
|
10
11
|
* });
|
|
11
12
|
* display.applyState(state);
|
|
12
13
|
* ```
|
|
13
14
|
*/
|
|
14
15
|
export declare class TowerDisplay implements ITowerDisplay {
|
|
15
|
-
private readonly
|
|
16
|
+
private readonly renderers;
|
|
17
|
+
private readonly root;
|
|
16
18
|
constructor(options: TowerDisplayOptions);
|
|
17
19
|
/** Update the display with a new decoded tower state. */
|
|
18
20
|
applyState(state: TowerState): void;
|
|
21
|
+
/** Update seal visibility — pass the current list of broken seals. */
|
|
22
|
+
applySeals(brokenSeals: SealIdentifier[]): void;
|
|
19
23
|
/** Reset the display to its idle/waiting state. */
|
|
20
24
|
showIdle(): void;
|
|
21
25
|
/** Remove all rendered DOM content and reset internal state. */
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type TowerState, type SealIdentifier } from 'ultimatedarktower';
|
|
2
|
+
import type { ITowerDisplay } from './types';
|
|
3
|
+
export declare class TowerSideView implements ITowerDisplay {
|
|
4
|
+
private readonly container;
|
|
5
|
+
private wrapper;
|
|
6
|
+
private currentSide;
|
|
7
|
+
private latestState;
|
|
8
|
+
private buttons;
|
|
9
|
+
private ledNodes;
|
|
10
|
+
private sealNodes;
|
|
11
|
+
private latestBrokenSeals;
|
|
12
|
+
/** Optional callback fired when a user clicks a seal overlay. */
|
|
13
|
+
onSealClick?: (seal: SealIdentifier) => void;
|
|
14
|
+
/**
|
|
15
|
+
* When true (the default), clicking a seal toggles its visibility independently
|
|
16
|
+
* of game state. Set to false to disable the built-in toggle.
|
|
17
|
+
*/
|
|
18
|
+
clickToToggleSeals: boolean;
|
|
19
|
+
private userToggledSeals;
|
|
20
|
+
constructor(container: HTMLElement);
|
|
21
|
+
applyState(state: TowerState): void;
|
|
22
|
+
applySeals(brokenSeals: SealIdentifier[]): void;
|
|
23
|
+
showIdle(): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
private detectSealSide;
|
|
26
|
+
private updateSealVisibility;
|
|
27
|
+
private build;
|
|
28
|
+
private injectSeals;
|
|
29
|
+
private cacheLedNodes;
|
|
30
|
+
private applyLedState;
|
|
31
|
+
private selectSide;
|
|
32
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TowerState } from 'ultimatedarktower';
|
|
2
|
-
import type { ITowerDisplay } from './types';
|
|
2
|
+
import type { ITowerDisplay, SealIdentifier } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Core DOM renderer for tower state.
|
|
5
5
|
*
|
|
@@ -18,6 +18,7 @@ export declare class TowerStateReadout implements ITowerDisplay {
|
|
|
18
18
|
constructor(container: HTMLElement);
|
|
19
19
|
/** Update the display with a new decoded tower state. */
|
|
20
20
|
applyState(state: TowerState): void;
|
|
21
|
+
applySeals(_brokenSeals: SealIdentifier[]): void;
|
|
21
22
|
/** Reset the display to its idle/waiting state. */
|
|
22
23
|
showIdle(): void;
|
|
23
24
|
/** Remove all rendered DOM content and reset internal state. */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EFFECT_LABELS: Record<number, string>;
|