even-toolkit 0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/dist/action-bar.d.ts +25 -0
  4. package/dist/action-bar.d.ts.map +1 -0
  5. package/dist/action-bar.js +47 -0
  6. package/dist/action-bar.js.map +1 -0
  7. package/dist/action-map.d.ts +4 -0
  8. package/dist/action-map.d.ts.map +1 -0
  9. package/dist/action-map.js +46 -0
  10. package/dist/action-map.js.map +1 -0
  11. package/dist/bridge.d.ts +43 -0
  12. package/dist/bridge.d.ts.map +1 -0
  13. package/dist/bridge.js +255 -0
  14. package/dist/bridge.js.map +1 -0
  15. package/dist/canvas-renderer.d.ts +5 -0
  16. package/dist/canvas-renderer.d.ts.map +1 -0
  17. package/dist/canvas-renderer.js +73 -0
  18. package/dist/canvas-renderer.js.map +1 -0
  19. package/dist/composer.d.ts +4 -0
  20. package/dist/composer.d.ts.map +1 -0
  21. package/dist/composer.js +60 -0
  22. package/dist/composer.js.map +1 -0
  23. package/dist/gestures.d.ts +6 -0
  24. package/dist/gestures.d.ts.map +1 -0
  25. package/dist/gestures.js +47 -0
  26. package/dist/gestures.js.map +1 -0
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +8 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/keep-alive.d.ts +3 -0
  32. package/dist/keep-alive.d.ts.map +1 -0
  33. package/dist/keep-alive.js +29 -0
  34. package/dist/keep-alive.js.map +1 -0
  35. package/dist/keyboard.d.ts +3 -0
  36. package/dist/keyboard.d.ts.map +1 -0
  37. package/dist/keyboard.js +62 -0
  38. package/dist/keyboard.js.map +1 -0
  39. package/dist/layout.d.ts +75 -0
  40. package/dist/layout.d.ts.map +1 -0
  41. package/dist/layout.js +89 -0
  42. package/dist/layout.js.map +1 -0
  43. package/dist/png-utils.d.ts +19 -0
  44. package/dist/png-utils.d.ts.map +1 -0
  45. package/dist/png-utils.js +73 -0
  46. package/dist/png-utils.js.map +1 -0
  47. package/dist/text-utils.d.ts +28 -0
  48. package/dist/text-utils.d.ts.map +1 -0
  49. package/dist/text-utils.js +41 -0
  50. package/dist/text-utils.js.map +1 -0
  51. package/dist/timer-display.d.ts +29 -0
  52. package/dist/timer-display.d.ts.map +1 -0
  53. package/dist/timer-display.js +74 -0
  54. package/dist/timer-display.js.map +1 -0
  55. package/dist/types.d.ts +39 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +8 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/useFlashPhase.d.ts +9 -0
  60. package/dist/useFlashPhase.d.ts.map +1 -0
  61. package/dist/useFlashPhase.js +24 -0
  62. package/dist/useFlashPhase.js.map +1 -0
  63. package/dist/useGlasses.d.ts +18 -0
  64. package/dist/useGlasses.d.ts.map +1 -0
  65. package/dist/useGlasses.js +143 -0
  66. package/dist/useGlasses.js.map +1 -0
  67. package/package.json +115 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shared text utilities for G2 glasses display.
3
+ */
4
+ /** Truncate text to maxLen, appending ~ if truncated */
5
+ export declare function truncate(text: string, maxLen: number): string;
6
+ /** Up arrow scroll indicator */
7
+ export declare const SCROLL_UP = "\u25B2";
8
+ /** Down arrow scroll indicator */
9
+ export declare const SCROLL_DOWN = "\u25BC";
10
+ /**
11
+ * Build a header line with title on the left and action bar on the right.
12
+ *
13
+ * @param title Left-side text (e.g. "Step 1/4: Toast the pepper")
14
+ * @param actionBar Right-side action bar string from buildActionBar()
15
+ */
16
+ export declare function buildHeaderLine(title: string, actionBar: string): string;
17
+ /**
18
+ * Apply scroll indicators to a windowed line array.
19
+ * Replaces the first/last visible line with ▲/▼ if there's more content above/below.
20
+ *
21
+ * @param lines The visible lines array (will be mutated)
22
+ * @param start Start index into the full content
23
+ * @param totalCount Total number of content lines
24
+ * @param visibleCount Number of visible lines in the window
25
+ * @param lineFactory Function to create a DisplayLine (e.g. `(text) => line(text, 'meta', false)`)
26
+ */
27
+ export declare function applyScrollIndicators<T>(lines: T[], start: number, totalCount: number, visibleCount: number, lineFactory: (text: string) => T): void;
28
+ //# sourceMappingURL=text-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-utils.d.ts","sourceRoot":"","sources":["../text-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,gCAAgC;AAChC,eAAO,MAAM,SAAS,WAAW,CAAC;AAElC,kCAAkC;AAClC,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,GAC/B,IAAI,CAQN"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared text utilities for G2 glasses display.
3
+ */
4
+ /** Truncate text to maxLen, appending ~ if truncated */
5
+ export function truncate(text, maxLen) {
6
+ return text.length > maxLen ? text.slice(0, maxLen - 1) + '~' : text;
7
+ }
8
+ /** Up arrow scroll indicator */
9
+ export const SCROLL_UP = '\u25B2'; // ▲
10
+ /** Down arrow scroll indicator */
11
+ export const SCROLL_DOWN = '\u25BC'; // ▼
12
+ /**
13
+ * Build a header line with title on the left and action bar on the right.
14
+ *
15
+ * @param title Left-side text (e.g. "Step 1/4: Toast the pepper")
16
+ * @param actionBar Right-side action bar string from buildActionBar()
17
+ */
18
+ export function buildHeaderLine(title, actionBar) {
19
+ return `${title} ${actionBar}`;
20
+ }
21
+ /**
22
+ * Apply scroll indicators to a windowed line array.
23
+ * Replaces the first/last visible line with ▲/▼ if there's more content above/below.
24
+ *
25
+ * @param lines The visible lines array (will be mutated)
26
+ * @param start Start index into the full content
27
+ * @param totalCount Total number of content lines
28
+ * @param visibleCount Number of visible lines in the window
29
+ * @param lineFactory Function to create a DisplayLine (e.g. `(text) => line(text, 'meta', false)`)
30
+ */
31
+ export function applyScrollIndicators(lines, start, totalCount, visibleCount, lineFactory) {
32
+ if (lines.length === 0)
33
+ return;
34
+ if (start > 0) {
35
+ lines[0] = lineFactory(SCROLL_UP);
36
+ }
37
+ if (start + visibleCount < totalCount) {
38
+ lines[lines.length - 1] = lineFactory(SCROLL_DOWN);
39
+ }
40
+ }
41
+ //# sourceMappingURL=text-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-utils.js","sourceRoot":"","sources":["../text-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wDAAwD;AACxD,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAc;IACnD,OAAO,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACvE,CAAC;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAE,IAAI;AAExC,kCAAkC;AAClC,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAE,IAAI;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,SAAiB;IAC9D,OAAO,GAAG,KAAK,KAAK,SAAS,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAU,EACV,KAAa,EACb,UAAkB,EAClB,YAAoB,EACpB,WAAgC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,KAAK,GAAG,YAAY,GAAG,UAAU,EAAE,CAAC;QACtC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Unicode timer display for G2 glasses.
3
+ *
4
+ * Confirmed working on G2: █ (full block), ─ (box drawing horizontal)
5
+ * NOT working on G2: ░ ▒ ▓ (shading), ╔═╗║ (double box drawing), ▀▄ (half blocks)
6
+ *
7
+ * Renders as 2 lines — text centered using ─ padding to match bar width:
8
+ * ─────── ▶ 06:44 ───────
9
+ * ████████████────────────
10
+ */
11
+ export interface TimerState {
12
+ running: boolean;
13
+ remaining: number;
14
+ total: number;
15
+ }
16
+ /**
17
+ * Render a 2-line timer display for the G2 glasses.
18
+ * Line 1: ─── icon MM:SS ─── (centered with ─ filler, same visual width as bar)
19
+ * Line 2: ████████████──────── (progress bar)
20
+ *
21
+ * @param timer Current timer state
22
+ * @param barWidth Number of characters for the progress bar (default 24)
23
+ */
24
+ export declare function renderTimerLines(timer: TimerState, barWidth?: number): string[];
25
+ /**
26
+ * Render a single-line compact timer (for tight spaces).
27
+ */
28
+ export declare function renderTimerCompact(timer: TimerState): string;
29
+ //# sourceMappingURL=timer-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer-display.d.ts","sourceRoot":"","sources":["../timer-display.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAcD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,SAAK,GAAG,MAAM,EAAE,CA4B3E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAa5D"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Unicode timer display for G2 glasses.
3
+ *
4
+ * Confirmed working on G2: █ (full block), ─ (box drawing horizontal)
5
+ * NOT working on G2: ░ ▒ ▓ (shading), ╔═╗║ (double box drawing), ▀▄ (half blocks)
6
+ *
7
+ * Renders as 2 lines — text centered using ─ padding to match bar width:
8
+ * ─────── ▶ 06:44 ───────
9
+ * ████████████────────────
10
+ */
11
+ const BLOCK_FULL = '\u2588'; // █ (filled portion)
12
+ const LINE_THIN = '\u2500'; // ─ (remaining portion + centering filler)
13
+ const ICON_PLAY = '\u25B6'; // ▶
14
+ const ICON_PAUSE = '\u2588'; // █ (single block for paused)
15
+ const ICON_DONE = 'OK';
16
+ const ICON_IDLE = '--';
17
+ function formatTime(seconds) {
18
+ const m = Math.floor(seconds / 60);
19
+ const s = seconds % 60;
20
+ return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
21
+ }
22
+ /** Center text above bar — spaces are ~4.5x narrower than █/─ on G2 font */
23
+ function center(text, barWidth) {
24
+ const pad = Math.max(0, Math.floor((barWidth - text.length) / 2));
25
+ return ' '.repeat(Math.round(pad * 6.7)) + text;
26
+ }
27
+ /**
28
+ * Render a 2-line timer display for the G2 glasses.
29
+ * Line 1: ─── icon MM:SS ─── (centered with ─ filler, same visual width as bar)
30
+ * Line 2: ████████████──────── (progress bar)
31
+ *
32
+ * @param timer Current timer state
33
+ * @param barWidth Number of characters for the progress bar (default 24)
34
+ */
35
+ export function renderTimerLines(timer, barWidth = 18) {
36
+ const { running, remaining, total } = timer;
37
+ if (total === 0 && remaining === 0) {
38
+ return [
39
+ center(` ${ICON_IDLE} 00:00 `, barWidth),
40
+ LINE_THIN.repeat(barWidth),
41
+ ];
42
+ }
43
+ if (remaining <= 0 && total > 0) {
44
+ return [
45
+ center(` ${ICON_DONE} 00:00 `, barWidth),
46
+ BLOCK_FULL.repeat(barWidth),
47
+ ];
48
+ }
49
+ const icon = running ? ICON_PLAY : ICON_PAUSE;
50
+ const time = formatTime(remaining);
51
+ const progress = total > 0 ? (total - remaining) / total : 0;
52
+ const filled = Math.round(progress * barWidth);
53
+ const empty = barWidth - filled;
54
+ const bar = BLOCK_FULL.repeat(filled) + LINE_THIN.repeat(empty);
55
+ return [
56
+ center(` ${icon} ${time} `, barWidth),
57
+ bar,
58
+ ];
59
+ }
60
+ /**
61
+ * Render a single-line compact timer (for tight spaces).
62
+ */
63
+ export function renderTimerCompact(timer) {
64
+ const { running, remaining, total } = timer;
65
+ if (total === 0 && remaining === 0) {
66
+ return `${ICON_IDLE} 00:00`;
67
+ }
68
+ if (remaining <= 0 && total > 0) {
69
+ return `${ICON_DONE} DONE`;
70
+ }
71
+ const icon = running ? ICON_PLAY : ICON_PAUSE;
72
+ return `${icon} ${formatTime(remaining)}`;
73
+ }
74
+ //# sourceMappingURL=timer-display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer-display.js","sourceRoot":"","sources":["../timer-display.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export type LineStyle = 'normal' | 'meta' | 'separator' | 'inverted';
2
+ export interface DisplayLine {
3
+ text: string;
4
+ inverted: boolean;
5
+ style: LineStyle;
6
+ }
7
+ export interface DisplayData {
8
+ lines: DisplayLine[];
9
+ }
10
+ export declare function line(text: string, style?: LineStyle, inverted?: boolean): DisplayLine;
11
+ export declare function separator(): DisplayLine;
12
+ export interface ColumnData {
13
+ /** One string per column — each column is a separate text container at a fixed pixel position */
14
+ columns: string[];
15
+ }
16
+ export interface ImageTileData {
17
+ tiles: {
18
+ id: number;
19
+ name: string;
20
+ bytes: Uint8Array;
21
+ }[];
22
+ /** Text shown below images (or empty for no-bounce overlay) */
23
+ text?: string;
24
+ }
25
+ export type PageMode = 'splash' | 'text' | 'columns' | 'home' | 'chart';
26
+ export type GlassActionType = 'HIGHLIGHT_MOVE' | 'SELECT_HIGHLIGHTED' | 'GO_BACK';
27
+ export type GlassAction = {
28
+ type: 'HIGHLIGHT_MOVE';
29
+ direction: 'up' | 'down';
30
+ } | {
31
+ type: 'SELECT_HIGHLIGHTED';
32
+ } | {
33
+ type: 'GO_BACK';
34
+ };
35
+ export interface GlassNavState {
36
+ highlightedIndex: number;
37
+ screen: string;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,SAAoB,EAAE,QAAQ,UAAQ,GAAG,WAAW,CAE7F;AAED,wBAAgB,SAAS,IAAI,WAAW,CAEvC;AAID,MAAM,WAAW,UAAU;IACzB,iGAAiG;IACjG,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAID,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IACzD,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAIZ,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,SAAS,CAAC;AAElF,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ // ── Display line types (legacy, still used for single-text pages) ──
2
+ export function line(text, style = 'normal', inverted = false) {
3
+ return { text, inverted, style };
4
+ }
5
+ export function separator() {
6
+ return { text: '', inverted: false, style: 'separator' };
7
+ }
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,sEAAsE;AActE,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,QAAmB,QAAQ,EAAE,QAAQ,GAAG,KAAK;IAC9E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared flash phase hook for blinking action button indicators.
3
+ * Toggles a boolean every 500ms when active.
4
+ *
5
+ * Usage:
6
+ * const flashPhase = useFlashPhase(isInActiveMode);
7
+ */
8
+ export declare function useFlashPhase(active: boolean): boolean;
9
+ //# sourceMappingURL=useFlashPhase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFlashPhase.d.ts","sourceRoot":"","sources":["../useFlashPhase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAiBtD"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared flash phase hook for blinking action button indicators.
3
+ * Toggles a boolean every 500ms when active.
4
+ *
5
+ * Usage:
6
+ * const flashPhase = useFlashPhase(isInActiveMode);
7
+ */
8
+ import { useState, useEffect } from 'react';
9
+ const FLASH_INTERVAL_MS = 500;
10
+ export function useFlashPhase(active) {
11
+ const [phase, setPhase] = useState(false);
12
+ useEffect(() => {
13
+ if (!active) {
14
+ setPhase(false);
15
+ return;
16
+ }
17
+ const interval = setInterval(() => {
18
+ setPhase((prev) => !prev);
19
+ }, FLASH_INTERVAL_MS);
20
+ return () => clearInterval(interval);
21
+ }, [active]);
22
+ return phase;
23
+ }
24
+ //# sourceMappingURL=useFlashPhase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFlashPhase.js","sourceRoot":"","sources":["../useFlashPhase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAEtB,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { DisplayData, GlassAction, GlassNavState, ColumnData } from './types';
2
+ import { type ColumnConfig } from './bridge';
3
+ export interface UseGlassesConfig<S> {
4
+ getSnapshot: () => S;
5
+ /** Convert snapshot to single text display (for 'text' mode) */
6
+ toDisplayData: (snapshot: S, nav: GlassNavState) => DisplayData;
7
+ /** Convert snapshot to column data (for 'columns' mode) — optional */
8
+ toColumns?: (snapshot: S, nav: GlassNavState) => ColumnData;
9
+ onGlassAction: (action: GlassAction, nav: GlassNavState, snapshot: S) => GlassNavState;
10
+ deriveScreen: (path: string) => string;
11
+ appName: string;
12
+ /** Page mode per screen — return 'text' or 'columns'. Default: 'text' */
13
+ getPageMode?: (screen: string) => 'text' | 'columns';
14
+ /** Column layout config — default: 3 equal columns across 576px */
15
+ columns?: ColumnConfig[];
16
+ }
17
+ export declare function useGlasses<S>(config: UseGlassesConfig<S>): void;
18
+ //# sourceMappingURL=useGlasses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGlasses.d.ts","sourceRoot":"","sources":["../useGlasses.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnF,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAK5D,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,gEAAgE;IAChE,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,aAAa,KAAK,WAAW,CAAC;IAChE,sEAAsE;IACtE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,aAAa,KAAK,UAAU,CAAC;IAC5D,aAAa,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,aAAa,CAAC;IACvF,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD,mEAAmE;IACnE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CA4I/D"}
@@ -0,0 +1,143 @@
1
+ import { useEffect, useRef, useCallback } from 'react';
2
+ import { useLocation, useNavigate } from 'react-router';
3
+ import { EvenHubBridge } from './bridge';
4
+ import { mapGlassEvent } from './action-map';
5
+ import { bindKeyboard } from './keyboard';
6
+ import { activateKeepAlive, deactivateKeepAlive } from './keep-alive';
7
+ export function useGlasses(config) {
8
+ const location = useLocation();
9
+ const navigate = useNavigate();
10
+ const hubRef = useRef(null);
11
+ const navRef = useRef({ highlightedIndex: 0, screen: '' });
12
+ const lastSnapshotRef = useRef(null);
13
+ const sendingRef = useRef(false);
14
+ const pendingRef = useRef(false);
15
+ const navigateRef = useRef(navigate);
16
+ navigateRef.current = navigate;
17
+ const configRef = useRef(config);
18
+ configRef.current = config;
19
+ const sendDisplay = useCallback(async () => {
20
+ if (sendingRef.current || !hubRef.current) {
21
+ // Queue a retry — the current in-flight send has stale data
22
+ pendingRef.current = true;
23
+ return;
24
+ }
25
+ sendingRef.current = true;
26
+ pendingRef.current = false;
27
+ try {
28
+ const hub = hubRef.current;
29
+ const snapshot = configRef.current.getSnapshot();
30
+ const nav = navRef.current;
31
+ const getMode = configRef.current.getPageMode ?? (() => 'text');
32
+ const mode = getMode(nav.screen);
33
+ if (mode === 'columns' && configRef.current.toColumns) {
34
+ const cols = configRef.current.toColumns(snapshot, nav);
35
+ if (hub.currentMode === 'columns') {
36
+ await hub.updateColumns(cols.columns);
37
+ }
38
+ else {
39
+ await hub.showColumnPage(cols.columns);
40
+ }
41
+ }
42
+ else {
43
+ const data = configRef.current.toDisplayData(snapshot, nav);
44
+ const text = data.lines.map(l => {
45
+ if (l.style === 'separator')
46
+ return '\u2500'.repeat(44);
47
+ if (l.inverted)
48
+ return `\u25B6 ${l.text}`;
49
+ return ` ${l.text}`;
50
+ }).join('\n');
51
+ if (hub.currentMode === 'text') {
52
+ await hub.updateText(text);
53
+ }
54
+ else {
55
+ await hub.showTextPage(text);
56
+ }
57
+ }
58
+ }
59
+ catch {
60
+ // SDK unavailable — glasses panel won't update, web still works
61
+ }
62
+ finally {
63
+ sendingRef.current = false;
64
+ // If a send was queued while we were busy, flush again with fresh data
65
+ if (pendingRef.current) {
66
+ pendingRef.current = false;
67
+ sendDisplay();
68
+ }
69
+ }
70
+ }, []);
71
+ const flushDisplay = useCallback(() => {
72
+ sendDisplay();
73
+ }, [sendDisplay]);
74
+ const handleAction = useCallback((action) => {
75
+ const snapshot = configRef.current.getSnapshot();
76
+ const newNav = configRef.current.onGlassAction(action, navRef.current, snapshot);
77
+ navRef.current = newNav;
78
+ flushDisplay();
79
+ }, [flushDisplay]);
80
+ // Update screen from URL changes
81
+ useEffect(() => {
82
+ const newScreen = configRef.current.deriveScreen(location.pathname);
83
+ if (newScreen !== navRef.current.screen) {
84
+ navRef.current = { highlightedIndex: 0, screen: newScreen };
85
+ flushDisplay();
86
+ }
87
+ }, [location.pathname, flushDisplay]);
88
+ // Initialize bridge, keyboard, keep-alive, and polling
89
+ useEffect(() => {
90
+ let pollTimer = null;
91
+ let disposed = false;
92
+ const hub = new EvenHubBridge(configRef.current.columns);
93
+ hubRef.current = hub;
94
+ navRef.current = {
95
+ highlightedIndex: 0,
96
+ screen: configRef.current.deriveScreen(location.pathname),
97
+ };
98
+ async function initBridge() {
99
+ try {
100
+ await hub.init();
101
+ if (disposed)
102
+ return;
103
+ // Show initial splash text
104
+ await hub.showTextPage(`\n\n ${configRef.current.appName}`);
105
+ if (disposed)
106
+ return;
107
+ hub.onEvent((event) => {
108
+ const action = mapGlassEvent(event);
109
+ if (action)
110
+ handleAction(action);
111
+ });
112
+ }
113
+ catch {
114
+ // SDK not available — app continues without glasses
115
+ }
116
+ // Start polling for state changes
117
+ if (!disposed) {
118
+ flushDisplay();
119
+ pollTimer = setInterval(() => {
120
+ const snapshot = configRef.current.getSnapshot();
121
+ if (snapshot !== lastSnapshotRef.current) {
122
+ lastSnapshotRef.current = snapshot;
123
+ flushDisplay();
124
+ }
125
+ }, 100);
126
+ }
127
+ }
128
+ initBridge();
129
+ const unbindKeyboard = bindKeyboard(handleAction);
130
+ activateKeepAlive(`${configRef.current.appName}_keep_alive`);
131
+ return () => {
132
+ disposed = true;
133
+ if (pollTimer)
134
+ clearInterval(pollTimer);
135
+ unbindKeyboard();
136
+ hub.dispose();
137
+ hubRef.current = null;
138
+ deactivateKeepAlive();
139
+ };
140
+ // eslint-disable-next-line react-hooks/exhaustive-deps
141
+ }, []);
142
+ }
143
+ //# sourceMappingURL=useGlasses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGlasses.js","sourceRoot":"","sources":["../useGlasses.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "even-toolkit",
3
+ "version": "0.1.0",
4
+ "description": "Shared library for building Even Realities G2 glasses apps — bridge, display, gestures, action bars, timers, and more.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./types": {
14
+ "types": "./dist/types.d.ts",
15
+ "import": "./dist/types.js"
16
+ },
17
+ "./bridge": {
18
+ "types": "./dist/bridge.d.ts",
19
+ "import": "./dist/bridge.js"
20
+ },
21
+ "./useGlasses": {
22
+ "types": "./dist/useGlasses.d.ts",
23
+ "import": "./dist/useGlasses.js"
24
+ },
25
+ "./useFlashPhase": {
26
+ "types": "./dist/useFlashPhase.d.ts",
27
+ "import": "./dist/useFlashPhase.js"
28
+ },
29
+ "./action-bar": {
30
+ "types": "./dist/action-bar.d.ts",
31
+ "import": "./dist/action-bar.js"
32
+ },
33
+ "./action-map": {
34
+ "types": "./dist/action-map.d.ts",
35
+ "import": "./dist/action-map.js"
36
+ },
37
+ "./gestures": {
38
+ "types": "./dist/gestures.d.ts",
39
+ "import": "./dist/gestures.js"
40
+ },
41
+ "./keyboard": {
42
+ "types": "./dist/keyboard.d.ts",
43
+ "import": "./dist/keyboard.js"
44
+ },
45
+ "./timer-display": {
46
+ "types": "./dist/timer-display.d.ts",
47
+ "import": "./dist/timer-display.js"
48
+ },
49
+ "./text-utils": {
50
+ "types": "./dist/text-utils.d.ts",
51
+ "import": "./dist/text-utils.js"
52
+ },
53
+ "./layout": {
54
+ "types": "./dist/layout.d.ts",
55
+ "import": "./dist/layout.js"
56
+ },
57
+ "./canvas-renderer": {
58
+ "types": "./dist/canvas-renderer.d.ts",
59
+ "import": "./dist/canvas-renderer.js"
60
+ },
61
+ "./composer": {
62
+ "types": "./dist/composer.d.ts",
63
+ "import": "./dist/composer.js"
64
+ },
65
+ "./png-utils": {
66
+ "types": "./dist/png-utils.d.ts",
67
+ "import": "./dist/png-utils.js"
68
+ },
69
+ "./keep-alive": {
70
+ "types": "./dist/keep-alive.d.ts",
71
+ "import": "./dist/keep-alive.js"
72
+ }
73
+ },
74
+ "files": [
75
+ "dist",
76
+ "README.md",
77
+ "LICENSE"
78
+ ],
79
+ "scripts": {
80
+ "build": "tsc -p tsconfig.build.json",
81
+ "prepublishOnly": "npm run build"
82
+ },
83
+ "peerDependencies": {
84
+ "react": ">=18.0.0",
85
+ "react-router": ">=7.0.0",
86
+ "@evenrealities/even_hub_sdk": ">=0.0.7",
87
+ "@jappyjan/even-better-sdk": ">=0.0.10"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "react": { "optional": true },
91
+ "react-router": { "optional": true }
92
+ },
93
+ "devDependencies": {
94
+ "@evenrealities/even_hub_sdk": "^0.0.7",
95
+ "@jappyjan/even-better-sdk": "^0.0.10",
96
+ "@types/react": "^19.0.0",
97
+ "react": "^19.0.0",
98
+ "react-router": "^7.0.0",
99
+ "typescript": "~5.4.0"
100
+ },
101
+ "keywords": [
102
+ "even-realities",
103
+ "g2-glasses",
104
+ "smart-glasses",
105
+ "ar",
106
+ "wearable",
107
+ "even-hub"
108
+ ],
109
+ "author": "fabioglimb",
110
+ "license": "MIT",
111
+ "repository": {
112
+ "type": "git",
113
+ "url": "https://github.com/fabioglimb/even-glass"
114
+ }
115
+ }