even-toolkit 1.4.0 → 1.4.1
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 +162 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Design system & component library for **Even Realities G2** smart glasses apps.
|
|
4
4
|
|
|
5
|
-
55+ web components, 191 pixel-art icons, glasses SDK bridge, light/dark themes, and design tokens — all following the Even Realities 2025 UIUX Design Guidelines.
|
|
5
|
+
55+ web components, 191 pixel-art icons, glasses SDK bridge with per-screen architecture, speech-to-text module, light/dark themes, and design tokens — all following the Even Realities 2025 UIUX Design Guidelines.
|
|
6
6
|
|
|
7
7
|
**[Live Demo → even-demo.vercel.app](https://even-demo.vercel.app)**
|
|
8
8
|
|
|
@@ -12,6 +12,12 @@ Design system & component library for **Even Realities G2** smart glasses apps.
|
|
|
12
12
|
npm install even-toolkit
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Scaffold a new app instantly:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx create-even-app my-app
|
|
19
|
+
```
|
|
20
|
+
|
|
15
21
|
## What's Inside
|
|
16
22
|
|
|
17
23
|
### `/web` — Web Component Library
|
|
@@ -44,38 +50,173 @@ import { IcChevronBack, IcTrash, IcSettings } from 'even-toolkit/web/icons/svg-i
|
|
|
44
50
|
|
|
45
51
|
**Categories:** Edit & Settings (32), Feature & Function (50), Guide System (20), Menu Bar (8), Navigate (23), Status (54), Health (12)
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
---
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
## Glasses SDK
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
Everything needed to build G2 glasses apps with a clean, per-screen architecture.
|
|
58
|
+
|
|
59
|
+
### Per-Screen Architecture (v1.4)
|
|
60
|
+
|
|
61
|
+
Each glasses screen lives in its own file with co-located display + action logic:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
src/glass/
|
|
65
|
+
shared.ts — Snapshot type + actions interface
|
|
66
|
+
selectors.ts — Screen router (3 lines of wiring)
|
|
67
|
+
splash.ts — Splash image + loading text
|
|
68
|
+
AppGlasses.tsx — useGlasses hook setup
|
|
69
|
+
screens/
|
|
70
|
+
home.ts — { display, action }
|
|
71
|
+
detail.ts — { display, action }
|
|
72
|
+
active.ts — { display, action }
|
|
55
73
|
```
|
|
56
74
|
|
|
57
|
-
|
|
75
|
+
#### Define a screen
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import type { GlassScreen } from 'even-toolkit/glass-screen-router';
|
|
79
|
+
import { buildScrollableList } from 'even-toolkit/glass-display-builders';
|
|
80
|
+
import { moveHighlight } from 'even-toolkit/glass-nav';
|
|
81
|
+
|
|
82
|
+
export const homeScreen: GlassScreen<MySnapshot, MyActions> = {
|
|
83
|
+
display(snapshot, nav) {
|
|
84
|
+
return {
|
|
85
|
+
lines: buildScrollableList({
|
|
86
|
+
items: snapshot.items,
|
|
87
|
+
highlightedIndex: nav.highlightedIndex,
|
|
88
|
+
maxVisible: 5,
|
|
89
|
+
formatter: (item) => item.title,
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
action(action, nav, snapshot, ctx) {
|
|
95
|
+
if (action.type === 'HIGHLIGHT_MOVE') {
|
|
96
|
+
return { ...nav, highlightedIndex: moveHighlight(nav.highlightedIndex, action.direction, snapshot.items.length - 1) };
|
|
97
|
+
}
|
|
98
|
+
if (action.type === 'SELECT_HIGHLIGHTED') {
|
|
99
|
+
ctx.navigate(`/item/${snapshot.items[nav.highlightedIndex].id}`);
|
|
100
|
+
return nav;
|
|
101
|
+
}
|
|
102
|
+
return nav;
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
```
|
|
58
106
|
|
|
59
|
-
|
|
107
|
+
#### Wire screens together
|
|
60
108
|
|
|
61
|
-
|
|
109
|
+
```ts
|
|
110
|
+
import { createGlassScreenRouter } from 'even-toolkit/glass-screen-router';
|
|
111
|
+
import { homeScreen } from './screens/home';
|
|
112
|
+
import { detailScreen } from './screens/detail';
|
|
62
113
|
|
|
63
|
-
|
|
114
|
+
export const { toDisplayData, onGlassAction } = createGlassScreenRouter({
|
|
115
|
+
'home': homeScreen,
|
|
116
|
+
'detail': detailScreen,
|
|
117
|
+
}, 'home');
|
|
118
|
+
```
|
|
64
119
|
|
|
65
|
-
|
|
120
|
+
### Navigation Helpers (`glass-nav`)
|
|
66
121
|
|
|
67
|
-
|
|
122
|
+
```ts
|
|
123
|
+
import { moveHighlight, clampIndex, calcMaxScroll, wrapIndex } from 'even-toolkit/glass-nav';
|
|
68
124
|
|
|
69
|
-
|
|
70
|
-
|
|
125
|
+
// Clamped movement (0 to max)
|
|
126
|
+
moveHighlight(current, 'up', max) // Math.max(0, Math.min(max, current - 1))
|
|
127
|
+
moveHighlight(current, 'down', max) // Math.max(0, Math.min(max, current + 1))
|
|
128
|
+
|
|
129
|
+
// Clamp index to button count
|
|
130
|
+
clampIndex(index, buttonCount) // Math.min(Math.max(0, index), count - 1)
|
|
131
|
+
|
|
132
|
+
// Max scroll offset
|
|
133
|
+
calcMaxScroll(totalLines, slots) // Math.max(0, totalLines - slots)
|
|
134
|
+
|
|
135
|
+
// Wrapping movement (loops around)
|
|
136
|
+
wrapIndex(current, 'down', count) // (current + 1) % count
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Display Builders (`glass-display-builders`)
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import {
|
|
143
|
+
buildScrollableList,
|
|
144
|
+
buildScrollableContent,
|
|
145
|
+
slidingWindowStart,
|
|
146
|
+
G2_TEXT_LINES, // 10
|
|
147
|
+
DEFAULT_CONTENT_SLOTS, // 7 (below glassHeader)
|
|
148
|
+
} from 'even-toolkit/glass-display-builders';
|
|
149
|
+
|
|
150
|
+
// Scrollable highlighted list with scroll indicators
|
|
151
|
+
const lines = buildScrollableList({
|
|
152
|
+
items: recipes,
|
|
153
|
+
highlightedIndex: nav.highlightedIndex,
|
|
154
|
+
maxVisible: 5,
|
|
155
|
+
formatter: (r) => r.title,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Header + scrollable content with indicators
|
|
159
|
+
const display = buildScrollableContent({
|
|
160
|
+
title: 'Recipe Detail',
|
|
161
|
+
actionBar: buildStaticActionBar(['Start'], 0),
|
|
162
|
+
contentLines: ['Line 1', 'Line 2', ...],
|
|
163
|
+
scrollPos: nav.highlightedIndex,
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Mode Encoding (`glass-mode`)
|
|
168
|
+
|
|
169
|
+
Pack multiple navigation modes into a single `highlightedIndex`:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { createModeEncoder } from 'even-toolkit/glass-mode';
|
|
173
|
+
|
|
174
|
+
const mode = createModeEncoder({
|
|
175
|
+
buttons: 0, // 0-99: button selection
|
|
176
|
+
scroll: 100, // 100+: scroll mode (offset = index - 100)
|
|
177
|
+
links: 200, // 200+: link navigation
|
|
178
|
+
});
|
|
71
179
|
|
|
72
|
-
//
|
|
73
|
-
|
|
180
|
+
mode.getMode(150) // 'scroll'
|
|
181
|
+
mode.getOffset(150) // 50
|
|
182
|
+
mode.encode('scroll', 25) // 125
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Route Mapping (`glass-router`)
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { createScreenMapper, createIdExtractor, getHomeTiles } from 'even-toolkit/glass-router';
|
|
74
189
|
|
|
75
|
-
|
|
76
|
-
|
|
190
|
+
const deriveScreen = createScreenMapper([
|
|
191
|
+
{ pattern: '/', screen: 'home' },
|
|
192
|
+
{ pattern: /^\/item\/[^/]+$/, screen: 'detail' },
|
|
193
|
+
], 'home');
|
|
194
|
+
|
|
195
|
+
const extractId = createIdExtractor(/^\/item\/([^/]+)/);
|
|
196
|
+
const homeTiles = getHomeTiles(appSplash);
|
|
77
197
|
```
|
|
78
198
|
|
|
199
|
+
### Core Glasses Modules
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { useGlasses } from 'even-toolkit/useGlasses';
|
|
203
|
+
import { useFlashPhase } from 'even-toolkit/useFlashPhase';
|
|
204
|
+
import { EvenHubBridge } from 'even-toolkit/bridge';
|
|
205
|
+
import { line, separator, glassHeader } from 'even-toolkit/types';
|
|
206
|
+
import { buildActionBar, buildStaticActionBar } from 'even-toolkit/action-bar';
|
|
207
|
+
import { truncate, applyScrollIndicators } from 'even-toolkit/text-utils';
|
|
208
|
+
import { renderTimerLines } from 'even-toolkit/timer-display';
|
|
209
|
+
import { createSplash, TILE_PRESETS } from 'even-toolkit/splash';
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Display:** 576x288px, 10 text lines, text/columns/chart/home page modes, image tiles (max 288x144)
|
|
213
|
+
|
|
214
|
+
**Input:** action-map (tap/double-tap/scroll events), gestures (debounce), keyboard bindings
|
|
215
|
+
|
|
216
|
+
**Utilities:** splash screens, PNG encoding, text cleaning, pagination, keep-alive
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
79
220
|
## Speech-to-Text (STT)
|
|
80
221
|
|
|
81
222
|
Provider-agnostic speech-to-text module for voice input in G2 glasses apps.
|
|
@@ -130,9 +271,10 @@ Automatically detects the best audio source:
|
|
|
130
271
|
- **Browser mic** — via `getUserMedia` (desktop)
|
|
131
272
|
- Custom `AudioSource` — pass your own
|
|
132
273
|
|
|
274
|
+
---
|
|
275
|
+
|
|
133
276
|
## SDK 0.0.9 Support
|
|
134
277
|
|
|
135
|
-
- Container limit increased to 12 (8 text + 4 image)
|
|
136
278
|
- Max image size: 288x144
|
|
137
279
|
- IMU control: `bridge.imuEnable()` / `bridge.imuDisable()`
|
|
138
280
|
- Launch source detection: `LaunchSource` type
|
|
@@ -177,7 +319,6 @@ Light theme following Even Realities 2025 guidelines:
|
|
|
177
319
|
## Quick Start
|
|
178
320
|
|
|
179
321
|
```tsx
|
|
180
|
-
// App.tsx
|
|
181
322
|
import { AppShell, NavBar, ScreenHeader, Button, Card } from 'even-toolkit/web';
|
|
182
323
|
import type { NavItem } from 'even-toolkit/web';
|
|
183
324
|
|
|
@@ -200,7 +341,6 @@ export function App() {
|
|
|
200
341
|
```
|
|
201
342
|
|
|
202
343
|
```css
|
|
203
|
-
/* app.css */
|
|
204
344
|
@import "tailwindcss";
|
|
205
345
|
@import "even-toolkit/web/theme-light.css";
|
|
206
346
|
@import "even-toolkit/web/typography.css";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "even-toolkit",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Design system & component library for Even Realities G2 smart glasses apps — 55+ web components, 191 pixel-art icons, glasses SDK bridge, and design tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/glasses/index.js",
|