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,73 @@
1
+ import { DISPLAY_W, DISPLAY_H } from './layout';
2
+ import { canvasToPngBytes } from './png-utils';
3
+ const FONT_SIZE = 22;
4
+ const LINE_HEIGHT = 28;
5
+ const PADDING_LEFT = 12;
6
+ const PADDING_TOP = 8;
7
+ const FONT = `${FONT_SIZE}px "Courier New", monospace`;
8
+ let canvas = null;
9
+ let ctx = null;
10
+ function ensureCanvas() {
11
+ if (!canvas) {
12
+ canvas = document.createElement('canvas');
13
+ canvas.width = DISPLAY_W;
14
+ canvas.height = DISPLAY_H;
15
+ const container = document.getElementById('glasses-canvas');
16
+ if (container)
17
+ container.appendChild(canvas);
18
+ }
19
+ if (!ctx) {
20
+ ctx = canvas.getContext('2d');
21
+ }
22
+ return ctx;
23
+ }
24
+ export function getCanvas() {
25
+ ensureCanvas();
26
+ return canvas;
27
+ }
28
+ function drawLine(ctx, line, y) {
29
+ const x = PADDING_LEFT;
30
+ if (line.style === 'separator') {
31
+ ctx.strokeStyle = '#333333';
32
+ ctx.lineWidth = 1;
33
+ ctx.beginPath();
34
+ ctx.moveTo(x, y + LINE_HEIGHT / 2);
35
+ ctx.lineTo(DISPLAY_W - PADDING_LEFT, y + LINE_HEIGHT / 2);
36
+ ctx.stroke();
37
+ return;
38
+ }
39
+ if (line.inverted) {
40
+ ctx.fillStyle = '#606060';
41
+ ctx.fillRect(0, y, DISPLAY_W, LINE_HEIGHT);
42
+ ctx.fillStyle = '#000000';
43
+ ctx.font = FONT;
44
+ ctx.fillText(line.text, x, y + FONT_SIZE);
45
+ return;
46
+ }
47
+ ctx.font = FONT;
48
+ switch (line.style) {
49
+ case 'meta':
50
+ ctx.fillStyle = '#808080';
51
+ break;
52
+ case 'normal':
53
+ default:
54
+ ctx.fillStyle = '#e0e0e0';
55
+ break;
56
+ }
57
+ ctx.fillText(line.text, x, y + FONT_SIZE);
58
+ }
59
+ export function drawToCanvas(data) {
60
+ const c = ensureCanvas();
61
+ c.fillStyle = '#000000';
62
+ c.fillRect(0, 0, DISPLAY_W, DISPLAY_H);
63
+ let y = PADDING_TOP;
64
+ for (const line of data.lines) {
65
+ drawLine(c, line, y);
66
+ y += LINE_HEIGHT;
67
+ }
68
+ }
69
+ export async function renderToImage(data) {
70
+ drawToCanvas(data);
71
+ return canvasToPngBytes(canvas);
72
+ }
73
+ //# sourceMappingURL=canvas-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-renderer.js","sourceRoot":"","sources":["../canvas-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { CreateStartUpPageContainer, RebuildPageContainer } from '@evenrealities/even_hub_sdk';
2
+ export declare function composeStartupPage(): CreateStartUpPageContainer;
3
+ export declare function composeRebuildPage(): RebuildPageContainer;
4
+ //# sourceMappingURL=composer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../composer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EAGrB,MAAM,6BAA6B,CAAC;AAiDrC,wBAAgB,kBAAkB,IAAI,0BAA0B,CAM/D;AAED,wBAAgB,kBAAkB,IAAI,oBAAoB,CAMzD"}
@@ -0,0 +1,60 @@
1
+ import { CreateStartUpPageContainer, RebuildPageContainer, ImageContainerProperty, TextContainerProperty, } from '@evenrealities/even_hub_sdk';
2
+ import { MAIN_SLOT, dummySlot } from './layout';
3
+ function imageContainer() {
4
+ return new ImageContainerProperty({
5
+ containerID: MAIN_SLOT.id,
6
+ containerName: MAIN_SLOT.name,
7
+ xPosition: MAIN_SLOT.x,
8
+ yPosition: MAIN_SLOT.y,
9
+ width: MAIN_SLOT.w,
10
+ height: MAIN_SLOT.h,
11
+ });
12
+ }
13
+ function eventCaptureContainer() {
14
+ return new TextContainerProperty({
15
+ containerID: 2,
16
+ containerName: 'events',
17
+ xPosition: MAIN_SLOT.x,
18
+ yPosition: MAIN_SLOT.y,
19
+ width: MAIN_SLOT.w,
20
+ height: MAIN_SLOT.h,
21
+ borderWidth: 0,
22
+ borderColor: 0,
23
+ borderRdaius: 0,
24
+ paddingLength: 0,
25
+ content: '',
26
+ isEventCapture: 1,
27
+ });
28
+ }
29
+ function dummy() {
30
+ const s = dummySlot(2);
31
+ return new TextContainerProperty({
32
+ containerID: s.id,
33
+ containerName: s.name,
34
+ xPosition: s.x,
35
+ yPosition: s.y,
36
+ width: s.w,
37
+ height: s.h,
38
+ borderWidth: 0,
39
+ borderColor: 0,
40
+ borderRdaius: 0,
41
+ paddingLength: 0,
42
+ content: '',
43
+ isEventCapture: 0,
44
+ });
45
+ }
46
+ export function composeStartupPage() {
47
+ return new CreateStartUpPageContainer({
48
+ containerTotalNum: 3,
49
+ imageObject: [imageContainer()],
50
+ textObject: [eventCaptureContainer(), dummy()],
51
+ });
52
+ }
53
+ export function composeRebuildPage() {
54
+ return new RebuildPageContainer({
55
+ containerTotalNum: 3,
56
+ imageObject: [imageContainer()],
57
+ textObject: [eventCaptureContainer(), dummy()],
58
+ });
59
+ }
60
+ //# sourceMappingURL=composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer.js","sourceRoot":"","sources":["../composer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEhD,SAAS,cAAc;IACrB,OAAO,IAAI,sBAAsB,CAAC;QAChC,WAAW,EAAE,SAAS,CAAC,EAAE;QACzB,aAAa,EAAE,SAAS,CAAC,IAAI;QAC7B,SAAS,EAAE,SAAS,CAAC,CAAC;QACtB,SAAS,EAAE,SAAS,CAAC,CAAC;QACtB,KAAK,EAAE,SAAS,CAAC,CAAC;QAClB,MAAM,EAAE,SAAS,CAAC,CAAC;KACpB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,IAAI,qBAAqB,CAAC;QAC/B,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,QAAQ;QACvB,SAAS,EAAE,SAAS,CAAC,CAAC;QACtB,SAAS,EAAE,SAAS,CAAC,CAAC;QACtB,KAAK,EAAE,SAAS,CAAC,CAAC;QAClB,MAAM,EAAE,SAAS,CAAC,CAAC;QACnB,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE;QACX,cAAc,EAAE,CAAC;KAClB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,KAAK;IACZ,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,IAAI,qBAAqB,CAAC;QAC/B,WAAW,EAAE,CAAC,CAAC,EAAE;QACjB,aAAa,EAAE,CAAC,CAAC,IAAI;QACrB,SAAS,EAAE,CAAC,CAAC,CAAC;QACd,SAAS,EAAE,CAAC,CAAC,CAAC;QACd,KAAK,EAAE,CAAC,CAAC,CAAC;QACV,MAAM,EAAE,CAAC,CAAC,CAAC;QACX,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE;QACX,cAAc,EAAE,CAAC;KAClB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,0BAA0B,CAAC;QACpC,iBAAiB,EAAE,CAAC;QACpB,WAAW,EAAE,CAAC,cAAc,EAAE,CAAC;QAC/B,UAAU,EAAE,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,CAAC;KAC/C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,oBAAoB,CAAC;QAC9B,iBAAiB,EAAE,CAAC;QACpB,WAAW,EAAE,CAAC,cAAc,EAAE,CAAC;QAC/B,UAAU,EAAE,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,CAAC;KAC/C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function tryConsumeTap(kind: 'tap' | 'double'): boolean;
2
+ export declare function isScrollSuppressed(): boolean;
3
+ /** Call after every text container update to suppress spurious G2 scroll events */
4
+ export declare function notifyTextUpdate(): void;
5
+ export declare function isScrollDebounced(direction: 'prev' | 'next'): boolean;
6
+ //# sourceMappingURL=gestures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gestures.d.ts","sourceRoot":"","sources":["../gestures.ts"],"names":[],"mappings":"AAaA,wBAAgB,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAiB7D;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAMD,mFAAmF;AACnF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAcrE"}
@@ -0,0 +1,47 @@
1
+ const TAP_COOLDOWN_MS = 220;
2
+ const TAP_DUPLICATE_DEBOUNCE_MS = 90;
3
+ const DOUBLE_TAP_DUPLICATE_DEBOUNCE_MS = 140;
4
+ const SCROLL_SUPPRESS_AFTER_TAP_MS = 110;
5
+ // Tuned for G2 hardware — prevents double-scroll from duplicate events
6
+ const SAME_DIRECTION_DEBOUNCE_MS = 350;
7
+ const DIRECTION_CHANGE_DEBOUNCE_MS = 50;
8
+ const SCROLL_SUPPRESS_AFTER_TEXT_MS = 80;
9
+ let lastTapTime = 0;
10
+ let lastTapKind = null;
11
+ export function tryConsumeTap(kind) {
12
+ const now = Date.now();
13
+ const elapsed = now - lastTapTime;
14
+ const duplicateMs = kind === 'double' ? DOUBLE_TAP_DUPLICATE_DEBOUNCE_MS : TAP_DUPLICATE_DEBOUNCE_MS;
15
+ if (kind === lastTapKind && elapsed < duplicateMs) {
16
+ return false;
17
+ }
18
+ if (elapsed < TAP_COOLDOWN_MS && lastTapKind !== null) {
19
+ return false;
20
+ }
21
+ lastTapTime = now;
22
+ lastTapKind = kind;
23
+ return true;
24
+ }
25
+ export function isScrollSuppressed() {
26
+ return Date.now() - lastTapTime < SCROLL_SUPPRESS_AFTER_TAP_MS;
27
+ }
28
+ let lastScrollTime = 0;
29
+ let lastScrollDir = null;
30
+ let textUpdateTime = 0;
31
+ /** Call after every text container update to suppress spurious G2 scroll events */
32
+ export function notifyTextUpdate() {
33
+ textUpdateTime = Date.now();
34
+ }
35
+ export function isScrollDebounced(direction) {
36
+ const now = Date.now();
37
+ // Suppress scrolls briefly after a text update (G2 re-layout fires spurious events)
38
+ if (now - textUpdateTime < SCROLL_SUPPRESS_AFTER_TEXT_MS)
39
+ return true;
40
+ const threshold = direction === lastScrollDir ? SAME_DIRECTION_DEBOUNCE_MS : DIRECTION_CHANGE_DEBOUNCE_MS;
41
+ if (now - lastScrollTime < threshold)
42
+ return true;
43
+ lastScrollTime = now;
44
+ lastScrollDir = direction;
45
+ return false;
46
+ }
47
+ //# sourceMappingURL=gestures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gestures.js","sourceRoot":"","sources":["../gestures.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,yBAAyB,GAAG,EAAE,CAAC;AACrC,MAAM,gCAAgC,GAAG,GAAG,CAAC;AAC7C,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEzC,uEAAuE;AACvE,MAAM,0BAA0B,GAAG,GAAG,CAAC;AACvC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AACxC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEzC,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,IAAI,WAAW,GAA4B,IAAI,CAAC;AAEhD,MAAM,UAAU,aAAa,CAAC,IAAsB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,GAAG,GAAG,WAAW,CAAC;IAClC,MAAM,WAAW,GACf,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,yBAAyB,CAAC;IAEnF,IAAI,IAAI,KAAK,WAAW,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,GAAG,eAAe,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW,GAAG,GAAG,CAAC;IAClB,WAAW,GAAG,IAAI,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,4BAA4B,CAAC;AACjE,CAAC;AAED,IAAI,cAAc,GAAG,CAAC,CAAC;AACvB,IAAI,aAAa,GAA2B,IAAI,CAAC;AACjD,IAAI,cAAc,GAAG,CAAC,CAAC;AAEvB,mFAAmF;AACnF,MAAM,UAAU,gBAAgB;IAC9B,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAA0B;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,oFAAoF;IACpF,IAAI,GAAG,GAAG,cAAc,GAAG,6BAA6B;QAAE,OAAO,IAAI,CAAC;IAEtE,MAAM,SAAS,GACb,SAAS,KAAK,aAAa,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,4BAA4B,CAAC;IAE1F,IAAI,GAAG,GAAG,cAAc,GAAG,SAAS;QAAE,OAAO,IAAI,CAAC;IAElD,cAAc,GAAG,GAAG,CAAC;IACrB,aAAa,GAAG,SAAS,CAAC;IAC1B,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+ export * from './action-bar';
3
+ export * from './text-utils';
4
+ export * from './timer-display';
5
+ export * from './gestures';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // even-g2-sdk — Shared library for Even Realities G2 glasses apps
2
+ // Import individual modules via deep paths: 'even-g2-sdk/types', 'even-g2-sdk/bridge', etc.
3
+ export * from './types';
4
+ export * from './action-bar';
5
+ export * from './text-utils';
6
+ export * from './timer-display';
7
+ export * from './gestures';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,4FAA4F;AAE5F,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function activateKeepAlive(lockName?: string): void;
2
+ export declare function deactivateKeepAlive(): void;
3
+ //# sourceMappingURL=keep-alive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keep-alive.d.ts","sourceRoot":"","sources":["../keep-alive.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,QAAQ,SAAyB,GAAG,IAAI,CAiBzE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
@@ -0,0 +1,29 @@
1
+ let audioCtx = null;
2
+ let oscillator = null;
3
+ let lockPromise = null;
4
+ export function activateKeepAlive(lockName = 'evenglass_keep_alive') {
5
+ try {
6
+ audioCtx = new AudioContext();
7
+ oscillator = audioCtx.createOscillator();
8
+ oscillator.frequency.value = 1;
9
+ const gain = audioCtx.createGain();
10
+ gain.gain.value = 0.001;
11
+ oscillator.connect(gain);
12
+ gain.connect(audioCtx.destination);
13
+ oscillator.start();
14
+ }
15
+ catch { /* ignore */ }
16
+ if (navigator.locks) {
17
+ lockPromise = navigator.locks.request(lockName, () => {
18
+ return new Promise(() => { });
19
+ });
20
+ }
21
+ }
22
+ export function deactivateKeepAlive() {
23
+ oscillator?.stop();
24
+ audioCtx?.close();
25
+ oscillator = null;
26
+ audioCtx = null;
27
+ lockPromise = null;
28
+ }
29
+ //# sourceMappingURL=keep-alive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keep-alive.js","sourceRoot":"","sources":["../keep-alive.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAwB,IAAI,CAAC;AACzC,IAAI,UAAU,GAA0B,IAAI,CAAC;AAC7C,IAAI,WAAW,GAA4B,IAAI,CAAC;AAEhD,MAAM,UAAU,iBAAiB,CAAC,QAAQ,GAAG,sBAAsB;IACjE,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;QAC9B,UAAU,GAAG,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QACzC,UAAU,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACxB,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACnC,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE;YACnD,OAAO,IAAI,OAAO,CAAO,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,UAAU,EAAE,IAAI,EAAE,CAAC;IACnB,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,UAAU,GAAG,IAAI,CAAC;IAClB,QAAQ,GAAG,IAAI,CAAC;IAChB,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GlassAction } from './types';
2
+ export declare function bindKeyboard(dispatch: (action: GlassAction) => void): () => void;
3
+ //# sourceMappingURL=keyboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,wBAAgB,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CA6DhF"}
@@ -0,0 +1,62 @@
1
+ export function bindKeyboard(dispatch) {
2
+ function isInteractive(el) {
3
+ const tag = el.tagName;
4
+ if (tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA')
5
+ return true;
6
+ if (tag === 'BUTTON' || tag === 'A')
7
+ return true;
8
+ if (el.closest('button, a, [role="button"]'))
9
+ return true;
10
+ return false;
11
+ }
12
+ const keyHandler = (e) => {
13
+ const tag = e.target.tagName;
14
+ if (tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA')
15
+ return;
16
+ switch (e.key) {
17
+ case 'ArrowUp':
18
+ e.preventDefault();
19
+ dispatch({ type: 'HIGHLIGHT_MOVE', direction: 'up' });
20
+ break;
21
+ case 'ArrowDown':
22
+ e.preventDefault();
23
+ dispatch({ type: 'HIGHLIGHT_MOVE', direction: 'down' });
24
+ break;
25
+ case 'Enter':
26
+ e.preventDefault();
27
+ dispatch({ type: 'SELECT_HIGHLIGHTED' });
28
+ break;
29
+ case 'Escape':
30
+ case 'Backspace':
31
+ e.preventDefault();
32
+ dispatch({ type: 'GO_BACK' });
33
+ break;
34
+ }
35
+ };
36
+ // Mouse wheel on the glasses simulator panel for scroll navigation
37
+ let lastWheelTime = 0;
38
+ const WHEEL_DEBOUNCE_MS = 250;
39
+ const wheelHandler = (e) => {
40
+ // Only trigger on the simulator panel (monospace pre/div), not on the web app content
41
+ const target = e.target;
42
+ if (isInteractive(target))
43
+ return;
44
+ const now = Date.now();
45
+ if (now - lastWheelTime < WHEEL_DEBOUNCE_MS)
46
+ return;
47
+ lastWheelTime = now;
48
+ if (e.deltaY > 0) {
49
+ dispatch({ type: 'HIGHLIGHT_MOVE', direction: 'down' });
50
+ }
51
+ else if (e.deltaY < 0) {
52
+ dispatch({ type: 'HIGHLIGHT_MOVE', direction: 'up' });
53
+ }
54
+ };
55
+ document.addEventListener('keydown', keyHandler);
56
+ document.addEventListener('wheel', wheelHandler, { passive: true });
57
+ return () => {
58
+ document.removeEventListener('keydown', keyHandler);
59
+ document.removeEventListener('wheel', wheelHandler);
60
+ };
61
+ }
62
+ //# sourceMappingURL=keyboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../keyboard.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,QAAuC;IAClE,SAAS,aAAa,CAAC,EAAe;QACpC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;QACvB,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;QAC3E,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACjD,IAAI,EAAE,CAAC,OAAO,CAAC,4BAA4B,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAgB,EAAE,EAAE;QACtC,MAAM,GAAG,GAAI,CAAC,CAAC,MAAsB,CAAC,OAAO,CAAC;QAC9C,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,UAAU;YAAE,OAAO;QAEtE,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;YACd,KAAK,SAAS;gBACZ,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtD,MAAM;YACR,KAAK,WAAW;gBACd,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;gBACxD,MAAM;YACR,KAAK,OAAO;gBACV,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAC;gBACzC,MAAM;YACR,KAAK,QAAQ,CAAC;YACd,KAAK,WAAW;gBACd,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC9B,MAAM;QACV,CAAC;IACH,CAAC,CAAC;IAEF,mEAAmE;IACnE,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,MAAM,iBAAiB,GAAG,GAAG,CAAC;IAE9B,MAAM,YAAY,GAAG,CAAC,CAAa,EAAE,EAAE;QACrC,sFAAsF;QACtF,MAAM,MAAM,GAAG,CAAC,CAAC,MAAqB,CAAC;QACvC,IAAI,aAAa,CAAC,MAAM,CAAC;YAAE,OAAO;QAElC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,aAAa,GAAG,iBAAiB;YAAE,OAAO;QACpD,aAAa,GAAG,GAAG,CAAC;QAEpB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjB,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,QAAQ,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC;IAEF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACjD,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpE,OAAO,GAAG,EAAE;QACV,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACpD,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACtD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,75 @@
1
+ export declare const DISPLAY_W = 576;
2
+ export declare const DISPLAY_H = 288;
3
+ export declare const G2_IMAGE_MAX_W = 200;
4
+ export declare const G2_IMAGE_MAX_H = 100;
5
+ export interface TileSlot {
6
+ id: number;
7
+ name: string;
8
+ x: number;
9
+ y: number;
10
+ w: number;
11
+ h: number;
12
+ crop: {
13
+ sx: number;
14
+ sy: number;
15
+ sw: number;
16
+ sh: number;
17
+ };
18
+ }
19
+ export declare const TILE_1: TileSlot;
20
+ export declare const TILE_2: TileSlot;
21
+ export declare const TILE_3: TileSlot;
22
+ export declare const IMAGE_TILES: TileSlot[];
23
+ export declare const SPLASH_IMG: {
24
+ id: number;
25
+ name: string;
26
+ x: number;
27
+ y: number;
28
+ w: number;
29
+ h: number;
30
+ };
31
+ export declare const TEXT_FULL: {
32
+ id: number;
33
+ name: string;
34
+ x: number;
35
+ y: number;
36
+ w: number;
37
+ h: number;
38
+ };
39
+ export declare const VIEWPORT_PER_RESOLUTION: Record<string, number>;
40
+ export declare const CHART_CANVAS_W = 576;
41
+ export declare const CHART_CANVAS_H = 100;
42
+ export declare const CHART_TEXT: {
43
+ id: number;
44
+ name: string;
45
+ x: number;
46
+ y: number;
47
+ w: number;
48
+ h: number;
49
+ };
50
+ export declare const DEFAULT_COLUMNS: {
51
+ col1X: number;
52
+ col1W: number;
53
+ col2X: number;
54
+ col2W: number;
55
+ col3X: number;
56
+ col3W: number;
57
+ };
58
+ export declare const MAIN_SLOT: {
59
+ id: number;
60
+ name: string;
61
+ x: number;
62
+ y: number;
63
+ w: number;
64
+ h: number;
65
+ };
66
+ export declare const CONTAINER_IDS: readonly [1, 2, 3];
67
+ export declare function dummySlot(index: number): {
68
+ id: 1 | 2 | 3;
69
+ name: string;
70
+ x: number;
71
+ y: number;
72
+ w: number;
73
+ h: number;
74
+ };
75
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../layout.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,MAAM,CAAC;AAC7B,eAAO,MAAM,SAAS,MAAM,CAAC;AAC7B,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAIlC,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAED,eAAO,MAAM,MAAM,EAAE,QAIpB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,QAIpB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,QAIpB,CAAC;AAEF,eAAO,MAAM,WAAW,YAA2B,CAAC;AAIpD,eAAO,MAAM,UAAU;;;;;;;CAOtB,CAAC;AAIF,eAAO,MAAM,SAAS;;;;;;;CAKrB,CAAC;AAIF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQ1D,CAAC;AAIF,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAIlC,eAAO,MAAM,UAAU;;;;;;;CAOtB,CAAC;AAIF,eAAO,MAAM,eAAe;;;;;;;CAO3B,CAAC;AAIF,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC;AAEF,eAAO,MAAM,aAAa,oBAAqB,CAAC;AAEhD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM;;;;;;;EAStC"}
package/dist/layout.js ADDED
@@ -0,0 +1,89 @@
1
+ // ── G2 display dimensions ──
2
+ export const DISPLAY_W = 576;
3
+ export const DISPLAY_H = 288;
4
+ export const G2_IMAGE_MAX_W = 200;
5
+ export const G2_IMAGE_MAX_H = 100;
6
+ export const TILE_1 = {
7
+ id: 2, name: 'tile-1',
8
+ x: 0, y: 0, w: G2_IMAGE_MAX_W, h: G2_IMAGE_MAX_H,
9
+ crop: { sx: 0, sy: 0, sw: 200, sh: 100 },
10
+ };
11
+ export const TILE_2 = {
12
+ id: 3, name: 'tile-2',
13
+ x: 200, y: 0, w: G2_IMAGE_MAX_W, h: G2_IMAGE_MAX_H,
14
+ crop: { sx: 200, sy: 0, sw: 200, sh: 100 },
15
+ };
16
+ export const TILE_3 = {
17
+ id: 4, name: 'tile-3',
18
+ x: 400, y: 0, w: G2_IMAGE_MAX_W, h: G2_IMAGE_MAX_H,
19
+ crop: { sx: 400, sy: 0, sw: 176, sh: 100 },
20
+ };
21
+ export const IMAGE_TILES = [TILE_1, TILE_2, TILE_3];
22
+ // ── Splash layout (1 centered image) ──
23
+ export const SPLASH_IMG = {
24
+ id: 2,
25
+ name: 'splash',
26
+ x: Math.floor((DISPLAY_W - G2_IMAGE_MAX_W) / 2),
27
+ y: Math.floor((DISPLAY_H - G2_IMAGE_MAX_H) / 2),
28
+ w: G2_IMAGE_MAX_W,
29
+ h: G2_IMAGE_MAX_H,
30
+ };
31
+ // ── Text-only layout (full screen) ──
32
+ export const TEXT_FULL = {
33
+ id: 1,
34
+ name: 'main',
35
+ x: 0, y: 0,
36
+ w: DISPLAY_W, h: DISPLAY_H,
37
+ };
38
+ // ── Viewport size per timeframe (ideal candle count for 576px chart) ──
39
+ export const VIEWPORT_PER_RESOLUTION = {
40
+ '1': 40, // 40 min
41
+ '5': 32, // ~2.5 hours
42
+ '15': 28, // ~7 hours
43
+ '60': 24, // 1 day
44
+ 'D': 28, // ~1.5 months
45
+ 'W': 20, // ~5 months
46
+ 'M': 16, // ~1.5 years
47
+ };
48
+ // ── Chart canvas (rendered offscreen, then split into tiles) ──
49
+ export const CHART_CANVAS_W = 576;
50
+ export const CHART_CANVAS_H = 100;
51
+ // ── Chart layout text container (below images) ──
52
+ export const CHART_TEXT = {
53
+ id: 1,
54
+ name: 'main',
55
+ x: 0,
56
+ y: G2_IMAGE_MAX_H,
57
+ w: DISPLAY_W,
58
+ h: DISPLAY_H - G2_IMAGE_MAX_H,
59
+ };
60
+ // ── Default column positions for 3-column layout (apps can override) ──
61
+ export const DEFAULT_COLUMNS = {
62
+ col1X: 0,
63
+ col1W: 192,
64
+ col2X: 192,
65
+ col2W: 192,
66
+ col3X: 384,
67
+ col3W: DISPLAY_W - 384,
68
+ };
69
+ // ── Legacy compat ──
70
+ export const MAIN_SLOT = {
71
+ id: 1,
72
+ name: 'main',
73
+ x: 0,
74
+ y: 0,
75
+ w: DISPLAY_W,
76
+ h: DISPLAY_H - 2,
77
+ };
78
+ export const CONTAINER_IDS = [1, 2, 3];
79
+ export function dummySlot(index) {
80
+ return {
81
+ id: CONTAINER_IDS[index],
82
+ name: `d-${index + 1}`,
83
+ x: 0,
84
+ y: DISPLAY_H - 2,
85
+ w: 1,
86
+ h: 1,
87
+ };
88
+ }
89
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface EncodedTile {
2
+ bytes: Uint8Array;
3
+ hash: number;
4
+ }
5
+ /** Encode all tiles from a source canvas. */
6
+ export declare function encodeTilesBatch(canvas: HTMLCanvasElement, tiles: Array<{
7
+ crop: {
8
+ sx: number;
9
+ sy: number;
10
+ sw: number;
11
+ sh: number;
12
+ };
13
+ name: string;
14
+ }>, tw: number, th: number): EncodedTile[];
15
+ /** Reset cache (no-op now, kept for API compat). */
16
+ export declare function resetTileCache(): void;
17
+ /** Backward-compat: encode full canvas to PNG bytes (number[] for SDK). */
18
+ export declare function canvasToPngBytes(canvas: HTMLCanvasElement): Promise<number[]>;
19
+ //# sourceMappingURL=png-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"png-utils.d.ts","sourceRoot":"","sources":["../png-utils.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AA6DD,6CAA6C;AAC7C,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACxF,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GACrB,WAAW,EAAE,CAIf;AAED,oDAAoD;AACpD,wBAAgB,cAAc,IAAI,IAAI,CAAG;AAEzC,2EAA2E;AAC3E,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKnF"}
@@ -0,0 +1,73 @@
1
+ /** PNG encoding: 16-color (4-bit) indexed PNG via UPNG — smallest possible files for G2. */
2
+ import UPNG from 'upng-js';
3
+ function fnv32a(bytes) {
4
+ let hash = 0x811c9dc5;
5
+ for (let i = 0; i < bytes.length; i++) {
6
+ hash ^= bytes[i];
7
+ hash = Math.imul(hash, 0x01000193);
8
+ }
9
+ return hash >>> 0;
10
+ }
11
+ // Cache tile canvases
12
+ const tileCanvasCache = new Map();
13
+ function getTileCtx(key, w, h) {
14
+ let cached = tileCanvasCache.get(key);
15
+ if (!cached || cached.canvas.width !== w || cached.canvas.height !== h) {
16
+ const canvas = document.createElement('canvas');
17
+ canvas.width = w;
18
+ canvas.height = h;
19
+ cached = { canvas, ctx: canvas.getContext('2d') };
20
+ tileCanvasCache.set(key, cached);
21
+ }
22
+ return cached.ctx;
23
+ }
24
+ // Reusable RGBA buffer for UPNG encode
25
+ let rgbaBuf = null;
26
+ let rgbaBufSize = 0;
27
+ function getRgbaBuf(size) {
28
+ if (!rgbaBuf || rgbaBufSize < size) {
29
+ rgbaBuf = new Uint8Array(size);
30
+ rgbaBufSize = size;
31
+ }
32
+ return rgbaBuf;
33
+ }
34
+ function encodeTile(canvas, sx, sy, sw, sh, tw, th, key) {
35
+ const ctx = getTileCtx(key, tw, th);
36
+ ctx.fillStyle = '#000000';
37
+ ctx.fillRect(0, 0, tw, th);
38
+ const dw = Math.min(sw, tw), dh = Math.min(sh, th);
39
+ ctx.drawImage(canvas, sx, sy, dw, dh, 0, 0, dw, dh);
40
+ const imgData = ctx.getImageData(0, 0, tw, th);
41
+ const pixels = imgData.data;
42
+ const pc = tw * th;
43
+ // Quantize to 16-level greyscale for 4-bit indexed PNG
44
+ const buf = getRgbaBuf(pc * 4);
45
+ for (let i = 0; i < pc; i++) {
46
+ const si = i * 4;
47
+ const lum = Math.round(0.299 * pixels[si] + 0.587 * pixels[si + 1] + 0.114 * pixels[si + 2]);
48
+ const idx = Math.min(15, Math.round(lum / 17));
49
+ const v = idx * 17;
50
+ buf[si] = v;
51
+ buf[si + 1] = v;
52
+ buf[si + 2] = v;
53
+ buf[si + 3] = 255;
54
+ }
55
+ // 16-color indexed PNG
56
+ const pngBuf = UPNG.encode([buf.buffer.slice(0, pc * 4)], tw, th, 16);
57
+ const bytes = new Uint8Array(pngBuf);
58
+ return { bytes, hash: fnv32a(bytes) };
59
+ }
60
+ /** Encode all tiles from a source canvas. */
61
+ export function encodeTilesBatch(canvas, tiles, tw, th) {
62
+ return tiles.map((tile) => encodeTile(canvas, tile.crop.sx, tile.crop.sy, tile.crop.sw, tile.crop.sh, tw, th, tile.name));
63
+ }
64
+ /** Reset cache (no-op now, kept for API compat). */
65
+ export function resetTileCache() { }
66
+ /** Backward-compat: encode full canvas to PNG bytes (number[] for SDK). */
67
+ export async function canvasToPngBytes(canvas) {
68
+ const w = canvas.width;
69
+ const h = canvas.height;
70
+ const tile = encodeTile(canvas, 0, 0, w, h, w, h, '__full');
71
+ return Array.from(tile.bytes);
72
+ }
73
+ //# sourceMappingURL=png-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"png-utils.js","sourceRoot":"","sources":["../png-utils.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,SAAS,MAAM,CAAC,KAAiB;IAC/B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;QAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAOD,sBAAsB;AACtB,MAAM,eAAe,GAAG,IAAI,GAAG,EAAwE,CAAC;AAExG,SAAS,UAAU,CAAC,GAAW,EAAE,CAAS,EAAE,CAAS;IACnD,IAAI,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;QAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACpC,MAAM,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAE,EAAE,CAAC;QACnD,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC;AACpB,CAAC;AAED,uCAAuC;AACvC,IAAI,OAAO,GAAsB,IAAI,CAAC;AACtC,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC,OAAO,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACnC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAGD,SAAS,UAAU,CACjB,MAAyB,EACzB,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAC9C,EAAU,EAAE,EAAU,EACtB,GAAW;IAEX,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACpC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACnD,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAEpD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5B,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAEnB,uDAAuD;IACvD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,EAAE,CAAE,GAAG,KAAK,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CAAE,GAAG,KAAK,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,CAAE,CAAC,CAAC;QAChG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;QACnB,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;IACnE,CAAC;IAED,uBAAuB;IACvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,gBAAgB,CAC9B,MAAyB,EACzB,KAAwF,EACxF,EAAU,EAAE,EAAU;IAEtB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACxB,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAC9F,CAAC;AACJ,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,cAAc,KAAU,CAAC;AAEzC,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAyB;IAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}