@houstonp/rubiks-cube 2.0.0 → 2.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.
- package/README.md +258 -54
- package/package.json +6 -6
- package/src/{cameraState.js → camera/cameraState.js} +3 -3
- package/src/core.js +387 -67
- package/src/cube/animationSlice.js +205 -0
- package/src/cube/animationState.js +96 -0
- package/src/cube/cubeSettings.js +6 -5
- package/src/cube/cubeState.js +284 -139
- package/src/cube/stickerState.js +188 -0
- package/src/debouncer.js +1 -1
- package/src/index.js +153 -28
- package/src/settings.js +20 -8
- package/src/three/centerPiece.js +44 -0
- package/src/three/cornerPiece.js +60 -0
- package/src/three/cube.js +492 -0
- package/src/three/edgePiece.js +50 -0
- package/src/three/sticker.js +37 -0
- package/tests/common.js +27 -0
- package/tests/cube.five.test.js +126 -0
- package/tests/cube.four.test.js +126 -0
- package/tests/cube.seven.test.js +126 -0
- package/tests/cube.six.test.js +126 -0
- package/tests/cube.three.test.js +151 -0
- package/tests/cube.two.test.js +125 -0
- package/tests/setup.js +36 -0
- package/types/{cameraState.d.ts → camera/cameraState.d.ts} +4 -4
- package/types/core.d.ts +396 -67
- package/types/cube/animationSlice.d.ts +26 -0
- package/types/cube/animationState.d.ts +41 -0
- package/types/cube/cubeSettings.d.ts +7 -7
- package/types/cube/cubeState.d.ts +38 -7
- package/types/cube/stickerState.d.ts +21 -0
- package/types/index.d.ts +23 -1
- package/types/settings.d.ts +8 -4
- package/types/three/centerPiece.d.ts +15 -0
- package/types/three/cornerPiece.d.ts +24 -0
- package/types/three/cube.d.ts +130 -0
- package/types/three/edgePiece.d.ts +16 -0
- package/types/three/sticker.d.ts +15 -0
- package/src/cube/cube.js +0 -324
- package/src/cube/cubeRotation.js +0 -79
- package/src/cube/slice.js +0 -143
- package/src/schema.js +0 -22
- package/src/threejs/materials.js +0 -54
- package/src/threejs/pieces.js +0 -100
- package/src/threejs/stickers.js +0 -40
- package/types/cube/cube.d.ts +0 -102
- package/types/cube/cubeRotation.d.ts +0 -33
- package/types/cube/slice.d.ts +0 -15
- package/types/schema.d.ts +0 -11
- package/types/threejs/materials.d.ts +0 -21
- package/types/threejs/pieces.d.ts +0 -28
- package/types/threejs/stickers.d.ts +0 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rubiks Cube Web Component
|
|
2
2
|
|
|
3
|
-
A Rubik
|
|
3
|
+
A Rubik's Cube web component built with Three.js, WebGPU, and GSAP. The cube renders into a shadow‑DOM canvas and exposes a small, promise‑based API for cube moves, rotations, reset, state setting, and camera "peek" positions. Supports 2x2, 3x3, 4x4, 5x5, 6x6, and 7x7 Rubik's cubes.
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
@@ -34,7 +34,14 @@ RubiksCubeElement.register();
|
|
|
34
34
|
<title>Rubiks Cube Demo</title>
|
|
35
35
|
</head>
|
|
36
36
|
<body>
|
|
37
|
-
|
|
37
|
+
<!-- Create a 3x3 cube with custom settings -->
|
|
38
|
+
<rubiks-cube cube-type="Three" animation-speed-ms="1000" animation-style="exponential" piece-gap="1.04" camera-speed-ms="100"></rubiks-cube>
|
|
39
|
+
|
|
40
|
+
<!-- Or create a 2x2 cube -->
|
|
41
|
+
<rubiks-cube cube-type="Two"></rubiks-cube>
|
|
42
|
+
|
|
43
|
+
<!-- Or create a 7x7 cube -->
|
|
44
|
+
<rubiks-cube cube-type="Seven"></rubiks-cube>
|
|
38
45
|
|
|
39
46
|
<script type="module" src="index.js"></script>
|
|
40
47
|
</body>
|
|
@@ -43,109 +50,300 @@ RubiksCubeElement.register();
|
|
|
43
50
|
|
|
44
51
|
## Component attributes
|
|
45
52
|
|
|
46
|
-
These attributes control animation, spacing, and
|
|
53
|
+
These attributes control animation, spacing, camera behavior, and cube type. The available attributes
|
|
47
54
|
can be imported so that they can be get and set easily.
|
|
48
55
|
|
|
49
56
|
```js
|
|
50
|
-
import {
|
|
57
|
+
import { RubiksCubeElement, AttributeNames } from '@houstonp/rubiks-cube';
|
|
58
|
+
import { CubeTypes, AnimationStyles } from '@houstonp/rubiks-cube/core';
|
|
51
59
|
|
|
52
60
|
const cube = document.querySelector('rubiks-cube');
|
|
61
|
+
|
|
62
|
+
// Get an attribute value
|
|
53
63
|
const animationSpeed = cube.getAttribute(AttributeNames.animationSpeed);
|
|
54
|
-
|
|
64
|
+
console.log('Current animation speed:', animationSpeed);
|
|
65
|
+
|
|
66
|
+
// Set an attribute value
|
|
67
|
+
cube.setAttribute(AttributeNames.animationSpeed, '500');
|
|
68
|
+
cube.setAttribute(AttributeNames.cubeType, CubeTypes.Four); // Change to 4x4 cube
|
|
69
|
+
cube.setAttribute(AttributeNames.animationStyle, AnimationStyles.Exponential);
|
|
70
|
+
cube.setAttribute(AttributeNames.pieceGap, '1.05');
|
|
71
|
+
cube.setAttribute(AttributeNames.cameraRadius, '6');
|
|
72
|
+
cube.setAttribute(AttributeNames.cameraFieldOfView, '80');
|
|
73
|
+
cube.setAttribute(AttributeNames.cameraPeekAngleHorizontal, '0.7');
|
|
74
|
+
cube.setAttribute(AttributeNames.cameraPeekAngleVertical, '0.7');
|
|
55
75
|
```
|
|
56
76
|
|
|
57
|
-
| attribute | accepted values
|
|
58
|
-
| ---------------------------- |
|
|
59
|
-
|
|
|
60
|
-
| animation-
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
| camera-
|
|
64
|
-
| camera-
|
|
65
|
-
| camera-peek-angle-
|
|
66
|
-
| camera-
|
|
77
|
+
| attribute | accepted values | Description |
|
|
78
|
+
| ---------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
79
|
+
| cube-type | `"Two"`, `"Three"`, `"Four"`, `"Five"`, `"Six"`, `"Seven"` | Sets the cube size (2x2 through 7x7). Default is `"Three"` |
|
|
80
|
+
| animation-speed-ms | integer greater than or equal to 0 | Sets the duration of cube animations in milliseconds |
|
|
81
|
+
| animation-style | `"exponential"`, `"next"`, `"fixed"`, `"match"` | `fixed`: fixed animation lengths, `next`: skips to next animation, `exponential`: speeds up successive animations, `match`: matches the speed to the frequency of events |
|
|
82
|
+
| piece-gap | greater than 1 | Sets the gap between Rubik's Cube pieces |
|
|
83
|
+
| camera-speed-ms | greater than or equal to 0 | Sets the duration of camera animations in milliseconds |
|
|
84
|
+
| camera-radius | greater than or equal to 4 | Sets the camera radius |
|
|
85
|
+
| camera-peek-angle-horizontal | decimal between 0 and 1 | Sets the horizontal peek angle |
|
|
86
|
+
| camera-peek-angle-vertical | decimal between 0 and 1 | Sets the vertical peek angle |
|
|
87
|
+
| camera-field-of-view | integer between 40 and 100 | Sets the field of view of the camera |
|
|
67
88
|
|
|
68
89
|
## Programmatic control
|
|
69
90
|
|
|
70
91
|
The `RubiksCubeElement` instance exposes async methods that return the cube state after the operation completes:
|
|
71
92
|
|
|
93
|
+
### Move
|
|
94
|
+
|
|
95
|
+
Performs a cube movement and resolves with the new state string.
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
99
|
+
import { Movements } from '@houstonp/rubiks-cube/core';
|
|
100
|
+
|
|
101
|
+
const cube = document.querySelector('rubiks-cube');
|
|
102
|
+
|
|
103
|
+
// Single layer moves
|
|
104
|
+
await cube.move(Movements.Single.R); // Right face clockwise
|
|
105
|
+
await cube.move(Movements.Single.R2); // Right face 180 degrees
|
|
106
|
+
await cube.move(Movements.Single.RP); // Right face counter-clockwise
|
|
107
|
+
await cube.move(Movements.Single.U); // Upper face clockwise
|
|
108
|
+
await cube.move(Movements.Single.FP); // Front face counter-clockwise
|
|
109
|
+
|
|
110
|
+
// Wide moves
|
|
111
|
+
await cube.move(Movements.Wide.Rw); // Wide right move
|
|
112
|
+
await cube.move(Movements.Wide.r); // Right two layers
|
|
113
|
+
|
|
114
|
+
// Layer-specific moves (for 4x4+ cubes)
|
|
115
|
+
await cube.move(Movements.Two.R); // Second layer right
|
|
116
|
+
await cube.move(Movements.Three.R); // Third layer right (for 4x4+)
|
|
117
|
+
await cube.move(Movements.Four.R); // Fourth layer right (for 5x5+)
|
|
118
|
+
|
|
119
|
+
// Middle layer moves
|
|
120
|
+
await cube.move(Movements.Single.M); // Middle layer
|
|
121
|
+
await cube.move(Movements.Single.E); // Equatorial layer
|
|
122
|
+
await cube.move(Movements.Single.S); // Standing layer
|
|
123
|
+
|
|
124
|
+
// Chain multiple moves
|
|
125
|
+
const moves = [Movements.Single.R, Movements.Single.U, Movements.Single.RP, Movements.Single.UP];
|
|
126
|
+
for (const move of moves) {
|
|
127
|
+
const state = await cube.move(move);
|
|
128
|
+
console.log('State after', move, ':', state);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Rotate
|
|
133
|
+
|
|
134
|
+
Rotates the entire cube and resolves with the new state string.
|
|
135
|
+
|
|
72
136
|
```js
|
|
73
137
|
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
138
|
+
import { Rotations } from '@houstonp/rubiks-cube/core';
|
|
139
|
+
|
|
140
|
+
const cube = document.querySelector('rubiks-cube');
|
|
141
|
+
|
|
142
|
+
// Rotate cube on x-axis (like R move)
|
|
143
|
+
await cube.rotate(Rotations.x); // 90 degrees clockwise
|
|
144
|
+
await cube.rotate(Rotations.x2); // 180 degrees
|
|
145
|
+
await cube.rotate(Rotations.xP); // 90 degrees counter-clockwise
|
|
146
|
+
|
|
147
|
+
// Rotate cube on y-axis (like U move)
|
|
148
|
+
await cube.rotate(Rotations.y); // 90 degrees clockwise
|
|
149
|
+
await cube.rotate(Rotations.y2); // 180 degrees
|
|
150
|
+
await cube.rotate(Rotations.yP); // 90 degrees counter-clockwise
|
|
151
|
+
|
|
152
|
+
// Rotate cube on z-axis (like F move)
|
|
153
|
+
await cube.rotate(Rotations.z); // 90 degrees clockwise
|
|
154
|
+
await cube.rotate(Rotations.z2); // 180 degrees
|
|
155
|
+
await cube.rotate(Rotations.zP); // 90 degrees counter-clockwise
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Reset
|
|
159
|
+
|
|
160
|
+
Resets the cube to the solved state and resolves with the new state string.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
164
|
+
import { Movements } from '@houstonp/rubiks-cube/core';
|
|
165
|
+
|
|
74
166
|
const cube = document.querySelector('rubiks-cube');
|
|
75
167
|
|
|
76
|
-
// Reset
|
|
77
|
-
const
|
|
168
|
+
// Reset to solved state
|
|
169
|
+
const solvedState = await cube.reset();
|
|
170
|
+
console.log('Cube reset to solved state:', solvedState);
|
|
78
171
|
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
cube.move(
|
|
82
|
-
|
|
83
|
-
});
|
|
172
|
+
// Reset after performing some moves
|
|
173
|
+
await cube.move(Movements.Single.R);
|
|
174
|
+
await cube.move(Movements.Single.U);
|
|
175
|
+
const resetState = await cube.reset();
|
|
84
176
|
```
|
|
85
177
|
|
|
86
|
-
|
|
178
|
+
### SetState
|
|
179
|
+
|
|
180
|
+
Sets the cube to a specific state using a Kociemba-format state string. This allows you to restore a previously saved state or set up specific cube configurations.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
184
|
+
import { Movements } from '@houstonp/rubiks-cube/core';
|
|
87
185
|
|
|
88
|
-
|
|
89
|
-
- `cube.rotate(rotation)` – rotates the entire cube and resolves with the new state string.
|
|
90
|
-
- `cube.reset()` – resets the cube to the solved state and resolves with the new state string.
|
|
91
|
-
- `cube.peek(peekType)` – animates the camera to a new “peek” position and resolves with the new peek state.
|
|
186
|
+
const cube = document.querySelector('rubiks-cube');
|
|
92
187
|
|
|
93
|
-
|
|
188
|
+
// Save current state
|
|
189
|
+
const currentState = await cube.move(Movements.Single.R);
|
|
190
|
+
|
|
191
|
+
// Later, restore that state
|
|
192
|
+
try {
|
|
193
|
+
const restoredState = await cube.setState(currentState);
|
|
194
|
+
console.log('State restored:', restoredState);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Failed to set state:', error);
|
|
197
|
+
// Error occurs if the state string is invalid for the current cube type
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Set a specific scrambled state (example for 3x3)
|
|
201
|
+
const scrambledState = 'UULUUFUUFRRUBRRURRFFDFFUFFFDDRDDDDDDBLLLLLLLLBRRBBBBBB';
|
|
202
|
+
await cube.setState(scrambledState);
|
|
203
|
+
```
|
|
94
204
|
|
|
95
|
-
|
|
205
|
+
### Peek
|
|
96
206
|
|
|
97
|
-
|
|
207
|
+
Animates the camera to a new "peek" position and resolves with the new peek state.
|
|
98
208
|
|
|
99
209
|
```js
|
|
100
210
|
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
101
|
-
import {
|
|
211
|
+
import { PeekTypes, PeekStates } from '@houstonp/rubiks-cube/core';
|
|
212
|
+
|
|
213
|
+
const cube = document.querySelector('rubiks-cube');
|
|
214
|
+
|
|
215
|
+
// Peek in different directions
|
|
216
|
+
await cube.peek(PeekTypes.Right); // Peek right
|
|
217
|
+
await cube.peek(PeekTypes.Left); // Peek left
|
|
218
|
+
await cube.peek(PeekTypes.Up); // Peek up
|
|
219
|
+
await cube.peek(PeekTypes.Down); // Peek down
|
|
220
|
+
await cube.peek(PeekTypes.RightUp); // Peek right and up
|
|
221
|
+
await cube.peek(PeekTypes.RightDown); // Peek right and down
|
|
222
|
+
await cube.peek(PeekTypes.LeftUp); // Peek left and up
|
|
223
|
+
await cube.peek(PeekTypes.LeftDown); // Peek left and down
|
|
224
|
+
await cube.peek(PeekTypes.Horizontal); // Reset horizontal peek
|
|
225
|
+
await cube.peek(PeekTypes.Vertical); // Reset vertical peek
|
|
226
|
+
|
|
227
|
+
// The peek method returns the current peek state
|
|
228
|
+
const peekState = await cube.peek(PeekTypes.RightUp);
|
|
229
|
+
console.log('Current peek state:', peekState); // e.g., 'rightUp'
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Complete Example
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
import { RubiksCubeElement, AttributeNames } from '@houstonp/rubiks-cube';
|
|
236
|
+
import { Movements, Rotations, PeekTypes, CubeTypes, AnimationStyles } from '@houstonp/rubiks-cube/core';
|
|
102
237
|
|
|
103
238
|
const cube = document.querySelector('rubiks-cube');
|
|
104
|
-
|
|
105
|
-
cube
|
|
239
|
+
|
|
240
|
+
// Configure cube settings
|
|
241
|
+
cube.setAttribute(AttributeNames.cubeType, CubeTypes.Four); // Use 4x4 cube
|
|
242
|
+
cube.setAttribute(AttributeNames.animationSpeed, '800');
|
|
243
|
+
cube.setAttribute(AttributeNames.animationStyle, AnimationStyles.Exponential);
|
|
244
|
+
|
|
245
|
+
// Perform a sequence of moves
|
|
246
|
+
await cube.move(Movements.Single.R);
|
|
247
|
+
await cube.move(Movements.Single.U);
|
|
248
|
+
await cube.rotate(Rotations.y);
|
|
249
|
+
await cube.move(Movements.Wide.Rw);
|
|
250
|
+
|
|
251
|
+
// Peek to see a different angle
|
|
252
|
+
await cube.peek(PeekTypes.RightUp);
|
|
253
|
+
|
|
254
|
+
// Save the current state
|
|
255
|
+
const currentState = await cube.move(Movements.Single.F);
|
|
256
|
+
|
|
257
|
+
// Reset and restore
|
|
258
|
+
await cube.reset();
|
|
259
|
+
await cube.setState(currentState);
|
|
106
260
|
```
|
|
107
261
|
|
|
262
|
+
All methods return promises that resolve with the new state string (or peek state for `peek`). They reject if the operation fails or times out.
|
|
263
|
+
|
|
108
264
|
## Rubiks Cube Notation
|
|
109
265
|
|
|
110
266
|
Notations can include the number of rotations of a face. For example, `U2` means rotate the upper face 180 degrees.
|
|
111
267
|
|
|
112
268
|
Notations can also include a prime symbol `'` to indicate a counter‑clockwise rotation. For example, `U'` means rotate the upper face counter‑clockwise. The direction is always determined relative to the face being moved.
|
|
113
269
|
|
|
270
|
+
Notations can also include a layer identifier for larger cubes. For example `3R2'` means rotate the Third layer from the right face counter-clockwise twice.
|
|
271
|
+
|
|
114
272
|
When both a number and a prime symbol are included, the number is stated before the prime symbol. For example, `U2'` means rotate the upper face 180 degrees counter‑clockwise, and `U'2` is invalid.
|
|
115
273
|
|
|
116
|
-
Valid
|
|
274
|
+
Valid notation constants are available via the `core` export. Use these constants instead of string literals for better type safety and autocomplete support.
|
|
275
|
+
|
|
276
|
+
Duplicate or equivalent notations are not provided in the `core` export. For example `R3` and `R'` are equivalent and only `R'` is provided in the export.
|
|
117
277
|
|
|
118
278
|
```js
|
|
119
279
|
import { RubiksCubeElement } from '@houstonp/rubiks-cube';
|
|
120
|
-
import { Rotations, Movements, PeekTypes,
|
|
280
|
+
import { Rotations, Movements, PeekTypes, PeekStates, CubeTypes, AnimationStyles } from '@houstonp/rubiks-cube/core';
|
|
121
281
|
|
|
122
282
|
const cube = document.querySelector('rubiks-cube');
|
|
123
|
-
|
|
124
|
-
|
|
283
|
+
|
|
284
|
+
// Use constants for moves
|
|
285
|
+
cube.move(Movements.Single.R);
|
|
286
|
+
cube.move(Movements.Single.U2);
|
|
287
|
+
cube.move(Movements.Single.FP);
|
|
288
|
+
|
|
289
|
+
// Use constants for rotations
|
|
290
|
+
cube.rotate(Rotations.x);
|
|
291
|
+
cube.rotate(Rotations.y2);
|
|
292
|
+
cube.rotate(Rotations.zP);
|
|
293
|
+
|
|
294
|
+
// Use constants for peek types
|
|
295
|
+
cube.peek(PeekTypes.Right);
|
|
296
|
+
cube.peek(PeekTypes.RightUp);
|
|
297
|
+
|
|
298
|
+
// Use constants for cube types
|
|
299
|
+
cube.setAttribute(AttributeNames.CubeType, CubeTypes.Four);
|
|
300
|
+
|
|
301
|
+
// Use constants for animation styles
|
|
302
|
+
cube.setAttribute(AttributeNames.AnimationStyle, AnimationStyles.Exponential);
|
|
125
303
|
```
|
|
126
304
|
|
|
127
|
-
|
|
305
|
+
Notation must match the following Regex
|
|
306
|
+
|
|
307
|
+
`/([1234567]|[123456]-[1234567])?([RLUDFB]w|[RLUDFBMES]|[rludfbmes])([123])?(\')?$/`
|
|
308
|
+
some notation may not work as intended as there is no known interpretation. eg `2M`
|
|
309
|
+
|
|
310
|
+
Standard Notation
|
|
311
|
+
|
|
312
|
+
| Notation | Movement |
|
|
313
|
+
| -------- | ------------------------------------------ |
|
|
314
|
+
| U | Top face clockwise |
|
|
315
|
+
| u | Top two layers clockwise |
|
|
316
|
+
| D | Bottom face clockwise |
|
|
317
|
+
| d | Bottom two layers clockwise |
|
|
318
|
+
| L | Left face clockwise |
|
|
319
|
+
| l | Left two layers clockwise |
|
|
320
|
+
| R | Right face clockwise |
|
|
321
|
+
| r | Right two layers clockwise |
|
|
322
|
+
| F | Front face clockwise |
|
|
323
|
+
| f | Front two layers clockwise |
|
|
324
|
+
| B | Back face clockwise |
|
|
325
|
+
| b | Back two layers clockwise |
|
|
326
|
+
| M | Middle layer clockwise (relative to L) |
|
|
327
|
+
| E | Equatorial layer clockwise (relative to D) |
|
|
328
|
+
| S | Standing layer clockwise (relative to F) |
|
|
329
|
+
|
|
330
|
+
Big Cube Notation. Not all listed for brevity.
|
|
331
|
+
|
|
332
|
+
| Notation | Movement |
|
|
333
|
+
| -------- | ----------------------------------------------- |
|
|
334
|
+
| NR | Nth Right most layer |
|
|
335
|
+
| NRw | All Right layers up to the Nth Right most layer |
|
|
336
|
+
| Nr | All Right layers up to the Nth Right most layer |
|
|
337
|
+
|
|
338
|
+
Rotation Notation
|
|
339
|
+
|
|
340
|
+
| Notation | Rotation |
|
|
128
341
|
| -------- | ------------------------------------------------ |
|
|
129
|
-
| U | Top face clockwise |
|
|
130
|
-
| u | Top two layers clockwise |
|
|
131
|
-
| D | Bottom face clockwise |
|
|
132
|
-
| d | Bottom two layers clockwise |
|
|
133
|
-
| L | Left face clockwise |
|
|
134
|
-
| l | Left two layers clockwise |
|
|
135
|
-
| R | Right face clockwise |
|
|
136
|
-
| r | Right two layers clockwise |
|
|
137
|
-
| F | Front face clockwise |
|
|
138
|
-
| f | Front two layers clockwise |
|
|
139
|
-
| B | Back face clockwise |
|
|
140
|
-
| b | Back two layers clockwise |
|
|
141
|
-
| M | Middle layer clockwise (relative to L) |
|
|
142
|
-
| E | Equatorial layer clockwise (relative to D) |
|
|
143
|
-
| S | Standing layer clockwise (relative to F) |
|
|
144
342
|
| x | Rotate cube on x axis clockwise (direction of R) |
|
|
145
343
|
| y | Rotate cube on y axis clockwise (direction of U) |
|
|
146
344
|
| z | Rotate cube on z axis clockwise (direction of F) |
|
|
147
345
|
|
|
148
|
-
These symbols align with the movements and rotations accepted by the component
|
|
346
|
+
These symbols align with the movements and rotations accepted by the component's API.
|
|
149
347
|
|
|
150
348
|
## Development
|
|
151
349
|
|
|
@@ -157,6 +355,12 @@ This repository is set up as an npm package and uses **Bun** for scripts and typ
|
|
|
157
355
|
bun install
|
|
158
356
|
```
|
|
159
357
|
|
|
358
|
+
- **Run Tests**
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
bun run test
|
|
362
|
+
```
|
|
363
|
+
|
|
160
364
|
- **Generate TypeScript declaration files**
|
|
161
365
|
|
|
162
366
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@houstonp/rubiks-cube",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Rubiks Cube Web Component built with threejs",
|
|
5
5
|
"author": "Houston Pearse",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
"types": "./types/index.d.ts",
|
|
19
19
|
"default": "./src/index.js"
|
|
20
20
|
},
|
|
21
|
-
"./schema": {
|
|
22
|
-
"types": "./types/schema.d.ts",
|
|
23
|
-
"default": "./src/schema.js"
|
|
24
|
-
},
|
|
25
21
|
"./core": {
|
|
26
22
|
"types": "./types/core.d.ts",
|
|
27
23
|
"default": "./src/core.js"
|
|
@@ -29,7 +25,8 @@
|
|
|
29
25
|
},
|
|
30
26
|
"scripts": {
|
|
31
27
|
"build:types": "tsc",
|
|
32
|
-
"watch:types": "tsc --watch"
|
|
28
|
+
"watch:types": "tsc --watch",
|
|
29
|
+
"test": "bun test"
|
|
33
30
|
},
|
|
34
31
|
"dependencies": {
|
|
35
32
|
"gsap": "^3.14.2",
|
|
@@ -44,7 +41,10 @@
|
|
|
44
41
|
},
|
|
45
42
|
"homepage": "https://github.com/houstonpearse/rubiks-cube#readme",
|
|
46
43
|
"devDependencies": {
|
|
44
|
+
"@types/bun": "^1.3.9",
|
|
45
|
+
"@types/jsdom": "^27.0.0",
|
|
47
46
|
"@types/three": "^0.182.0",
|
|
47
|
+
"jsdom": "^28.1.0",
|
|
48
48
|
"typescript": "^5.9.3"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
import { PeekStates, PeekTypes } from '
|
|
2
|
+
import { PeekStates, PeekTypes } from '../core';
|
|
3
3
|
|
|
4
4
|
export class CameraState {
|
|
5
5
|
/**
|
|
@@ -14,7 +14,7 @@ export class CameraState {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* @param {import("
|
|
17
|
+
* @param {import("../core").PeekType} peekType
|
|
18
18
|
*/
|
|
19
19
|
peekCamera(peekType) {
|
|
20
20
|
switch (peekType) {
|
|
@@ -58,7 +58,7 @@ export class CameraState {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* @returns {import("
|
|
61
|
+
* @returns {import("../core").PeekState}
|
|
62
62
|
*/
|
|
63
63
|
toPeekState() {
|
|
64
64
|
if (this.Right && this.Up) {
|