@bedard/hexboard 0.0.2 → 0.0.4

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/package.json CHANGED
@@ -58,5 +58,5 @@
58
58
  "license": "MIT",
59
59
  "type": "module",
60
60
  "types": "dist/index.d.ts",
61
- "version": "0.0.2"
61
+ "version": "0.0.4"
62
62
  }
@@ -190,9 +190,8 @@ import {
190
190
  } from './constants'
191
191
  import { d } from './dom'
192
192
  import { x, y } from './geometry'
193
- import { hapticConfirm } from './haptics'
194
193
  import GiocoPieces from './pieces/Gioco.vue'
195
- import type { HexboardOptions } from './types'
194
+ import type { HexboardOptions, Rect } from './types'
196
195
 
197
196
  //
198
197
  // props
@@ -264,7 +263,7 @@ const pointerCoords = shallowRef({ x: 0, y: 0 })
264
263
  const pointerdownPosition = shallowRef<number | null>(null)
265
264
 
266
265
  /** rect of promotion anchor element */
267
- const promotionRect = shallowRef<DOMRect>(new DOMRect())
266
+ const promotionRect = shallowRef(rect())
268
267
 
269
268
  /** staging display data */
270
269
  const staging = shallowRef<{
@@ -285,7 +284,7 @@ const staging = shallowRef<{
285
284
  const svgEl = useTemplateRef('svgEl')
286
285
 
287
286
  /** rect of svg element on pointerdown */
288
- const svgRect = shallowRef<DOMRect>(new DOMRect())
287
+ const svgRect = shallowRef<Rect>(rect())
289
288
 
290
289
  /** flag to skip click handling after promotion cancel */
291
290
  let skipNextClick = false
@@ -582,7 +581,7 @@ function listen() {
582
581
  /** measure promotion element rect */
583
582
  function measurePromotionRect() {
584
583
  promotionRect.value
585
- = staging.value.promotionEl?.getBoundingClientRect() ?? new DOMRect()
584
+ = staging.value.promotionEl?.getBoundingClientRect() ?? rect()
586
585
  }
587
586
 
588
587
  /** click position */
@@ -674,7 +673,7 @@ function onPointerupPosition(index: number, evt: PointerEvent) {
674
673
 
675
674
  // Keep selection but reset drag state
676
675
  pointerdownPosition.value = null
677
- svgRect.value = new DOMRect()
676
+ svgRect.value = rect()
678
677
  return
679
678
  }
680
679
 
@@ -701,7 +700,7 @@ function onPointerupPosition(index: number, evt: PointerEvent) {
701
700
  // If clicking on any piece, keep the selection (it was set in pointerdown)
702
701
  if (props.hexchess?.board[index]) {
703
702
  pointerdownPosition.value = null
704
- svgRect.value = new DOMRect()
703
+ svgRect.value = rect()
705
704
  return
706
705
  }
707
706
 
@@ -734,8 +733,6 @@ function cancelPromotion() {
734
733
  function onPointerdownPosition(index: number, evt: PointerEvent) {
735
734
  evt.preventDefault()
736
735
 
737
- hapticConfirm()
738
-
739
736
  // Don't start new interactions during promotion
740
737
  if (staging.value.hexchess) {
741
738
  return
@@ -750,10 +747,6 @@ function onPointerdownPosition(index: number, evt: PointerEvent) {
750
747
  if (props.autoselect) {
751
748
  selected.value = index
752
749
  targets.value = props.hexchess?.movesFrom(index).map(san => san.to) ?? []
753
-
754
- if (normalizedOptions.value.haptics) {
755
- hapticConfirm()
756
- }
757
750
  }
758
751
 
759
752
  if (!isPlayingPosition(index)) {
@@ -813,7 +806,7 @@ function onPointerupWindow() {
813
806
  // If dragging a piece, keep the selection but reset drag state
814
807
  if (pointerdownPosition.value !== null) {
815
808
  pointerdownPosition.value = null
816
- svgRect.value = new DOMRect()
809
+ svgRect.value = rect()
817
810
  return
818
811
  }
819
812
 
@@ -836,6 +829,20 @@ function promote(promotion: 'n' | 'b' | 'r' | 'q') {
836
829
  }
837
830
  }
838
831
 
832
+ function rect(data: Partial<Rect> = {}): Rect {
833
+ return {
834
+ bottom: 0,
835
+ height: 0,
836
+ left: 0,
837
+ right: 0,
838
+ top: 0,
839
+ width: 0,
840
+ x: 0,
841
+ y: 0,
842
+ ...data,
843
+ }
844
+ }
845
+
839
846
  /** reset state */
840
847
  function resetState() {
841
848
  document.body.style.setProperty('cursor', null)
@@ -848,7 +855,7 @@ function resetState() {
848
855
  promotionTo: null,
849
856
  selected: null,
850
857
  }
851
- svgRect.value = new DOMRect()
858
+ svgRect.value = rect()
852
859
  targets.value = []
853
860
  }
854
861
 
@@ -10,7 +10,6 @@ export const defaultOptions: HexboardOptions = {
10
10
  'oklch(0.8366 0.1165 66.29)',
11
11
  'oklch(0.6806 0.1423 75.83)',
12
12
  ],
13
- haptics: true,
14
13
  highlightColor: 'oklch(90.5% 0.182 98.111 / 75%)', // yellow-300 / 75% opacity
15
14
  labelActiveColor: 'oklch(76.9% 0.188 70.08)', // amber-500
16
15
  labelColor: 'oklch(55.4% 0.046 257.417)', // slate-500
@@ -2,8 +2,6 @@
2
2
  export interface HexboardOptions {
3
3
  /** position colors */
4
4
  colors: [string, string, string]
5
- /** haptic feedback vibrations */
6
- haptics: boolean
7
5
  /** color of highlighted position */
8
6
  highlightColor: string
9
7
  /** color of active label relative to mouseover */
@@ -20,6 +18,18 @@ export interface HexboardOptions {
20
18
  selectedColor: string
21
19
  }
22
20
 
21
+ /** rect */
22
+ export type Rect = {
23
+ bottom: number
24
+ height: number
25
+ left: number
26
+ right: number
27
+ top: number
28
+ width: number
29
+ x: number
30
+ y: number
31
+ }
32
+
23
33
  /** uniform tuple of length `T`, `number` by default */
24
34
  export type Vec<
25
35
  T extends number,
@@ -10,7 +10,48 @@
10
10
  :hexchess
11
11
  :playing="true"
12
12
  @move="onMove"
13
- />
13
+ >
14
+ <template #promotion="{ b, n, q, r, promote }">
15
+ <div class="absolute bg-gray-50 cursor-pointer flex left-1/2 bottom-full rounded-md shadow-md overflow-hidden -translate-x-1/2">
16
+ <button
17
+ class="aspect-square border-r border-gray-200 cursor-pointer flex items-center justify-center size-12 hover:bg-gray-200"
18
+ @click="promote('b')"
19
+ >
20
+ <Component
21
+ class="size-3/4"
22
+ :is="b"
23
+ />
24
+ </button>
25
+ <button
26
+ class="aspect-square border-r border-gray-200 cursor-pointer flex items-center justify-center size-12 hover:bg-gray-200"
27
+ @click="promote('n')"
28
+ >
29
+ <Component
30
+ class="size-3/4"
31
+ :is="n"
32
+ />
33
+ </button>
34
+ <button
35
+ class="aspect-square border-r border-gray-200 cursor-pointer flex items-center justify-center size-12 hover:bg-gray-200"
36
+ @click="promote('r')"
37
+ >
38
+ <Component
39
+ class="size-3/4"
40
+ :is="r"
41
+ />
42
+ </button>
43
+ <button
44
+ class="aspect-square cursor-pointer flex items-center justify-center size-12 hover:bg-gray-200"
45
+ @click="promote('q')"
46
+ >
47
+ <Component
48
+ class="size-3/4"
49
+ :is="q"
50
+ />
51
+ </button>
52
+ </div>
53
+ </template>
54
+ </Hexboard>
14
55
  </div>
15
56
  </template>
16
57
 
@@ -1,56 +0,0 @@
1
- /** check if haptics are supported */
2
- export const supportsHaptics
3
- = typeof window === 'undefined'
4
- ? false
5
- : window.matchMedia('(pointer: coarse)').matches
6
-
7
- /** trigger haptic feedback */
8
- function tick() {
9
- try {
10
- // use the native api if supported
11
- if (navigator.vibrate) {
12
- navigator.vibrate(50)
13
- return
14
- }
15
-
16
- if (!supportsHaptics) return
17
-
18
- // otherwise simulate a tep using a checkbox
19
- const labelEl = document.createElement('label')
20
- labelEl.ariaHidden = 'true'
21
- labelEl.style.display = 'none'
22
-
23
- const inputEl = document.createElement('input')
24
- inputEl.type = 'checkbox'
25
- inputEl.setAttribute('switch', '')
26
- labelEl.appendChild(inputEl)
27
-
28
- document.head.appendChild(labelEl)
29
- labelEl.click()
30
- document.head.removeChild(labelEl)
31
- }
32
- catch {
33
- // do nothing
34
- }
35
- }
36
-
37
- export function hapticConfirm() {
38
- if (navigator.vibrate) {
39
- navigator.vibrate([50, 70, 50])
40
- return
41
- }
42
-
43
- tick()
44
- setTimeout(tick, 120)
45
- }
46
-
47
- export function hapticError() {
48
- if (navigator.vibrate) {
49
- navigator.vibrate([50, 70, 50, 70, 50])
50
- return
51
- }
52
-
53
- tick()
54
- setTimeout(tick, 120)
55
- setTimeout(tick, 240)
56
- }