@stacksjs/desktop 0.2.3
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 +563 -0
- package/dist/alerts.d.ts +164 -0
- package/dist/components.d.ts +942 -0
- package/dist/dialogs.d.ts +213 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.js +3015 -0
- package/dist/index.js.map +15 -0
- package/dist/modals.d.ts +201 -0
- package/dist/system-tray.d.ts +121 -0
- package/dist/types.d.ts +171 -0
- package/dist/window.d.ts +111 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
# @stacksjs/desktop
|
|
2
|
+
|
|
3
|
+
Native desktop application framework for stx powered by craft.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@stacksjs/desktop` provides a TypeScript API for creating native desktop applications with stx. It uses [Craft](https://github.com/stacksjs/craft) to deliver lightweight, fast native apps using web technologies and native WebKit views.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🪟 **Native Windows** - Create true native windows (not Electron)
|
|
12
|
+
- 🎯 **Tiny Binary** - Just 1.4MB vs 100MB+ for Electron
|
|
13
|
+
- ⚡ **Fast Startup** - <100ms startup time
|
|
14
|
+
- 🔧 **System Tray Apps** - Build menubar/system tray applications
|
|
15
|
+
- 🎨 **Rich Components** - 35 native UI components
|
|
16
|
+
- 🌍 **Cross-Platform** - macOS, Linux, Windows support
|
|
17
|
+
- 🔥 **Hot Reload** - Development mode with instant updates
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bun add @stacksjs/desktop
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
- **craft** - For native window support (linked locally or via npm)
|
|
28
|
+
- **macOS** - WebKit framework (built-in)
|
|
29
|
+
- **Linux** - `libgtk-3-dev` and `libwebkit2gtk-4.0-dev`
|
|
30
|
+
- **Windows** - WebView2 Runtime
|
|
31
|
+
|
|
32
|
+
### Setup craft Integration
|
|
33
|
+
|
|
34
|
+
For local development with craft:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Clone craft repository
|
|
38
|
+
cd /path/to/your/repos
|
|
39
|
+
git clone https://github.com/stacksjs/craft
|
|
40
|
+
|
|
41
|
+
# Build craft
|
|
42
|
+
cd craft
|
|
43
|
+
bun install
|
|
44
|
+
zig build
|
|
45
|
+
|
|
46
|
+
# Link ts-craft package
|
|
47
|
+
cd packages/typescript
|
|
48
|
+
bun link
|
|
49
|
+
|
|
50
|
+
# Link to desktop package
|
|
51
|
+
cd /path/to/stx/packages/desktop
|
|
52
|
+
bun link ts-craft
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Usage
|
|
56
|
+
|
|
57
|
+
### Quick Start with stx Dev Server
|
|
58
|
+
|
|
59
|
+
The easiest way to test native windows:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Start dev server with native window
|
|
63
|
+
stx dev examples/homepage.stx --native
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This opens a menubar application. Look for "stx Development" in your macOS menubar and click it to show the window.
|
|
67
|
+
|
|
68
|
+
### Basic Window with craft
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { createApp } from 'ts-craft'
|
|
72
|
+
|
|
73
|
+
const app = createApp({
|
|
74
|
+
url: 'http://localhost:3000',
|
|
75
|
+
window: {
|
|
76
|
+
title: 'My App',
|
|
77
|
+
width: 1200,
|
|
78
|
+
height: 800,
|
|
79
|
+
systemTray: true, // Required for craft
|
|
80
|
+
darkMode: true,
|
|
81
|
+
hotReload: true,
|
|
82
|
+
devTools: true,
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
await app.show()
|
|
87
|
+
console.log('Window created! Look for "My App" in your menubar')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Display HTML Content
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { show } from 'ts-craft'
|
|
94
|
+
|
|
95
|
+
const html = `
|
|
96
|
+
<!DOCTYPE html>
|
|
97
|
+
<html>
|
|
98
|
+
<head>
|
|
99
|
+
<style>
|
|
100
|
+
body {
|
|
101
|
+
margin: 0;
|
|
102
|
+
display: flex;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
align-items: center;
|
|
105
|
+
height: 100vh;
|
|
106
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
107
|
+
font-family: system-ui;
|
|
108
|
+
}
|
|
109
|
+
h1 {
|
|
110
|
+
color: white;
|
|
111
|
+
font-size: 48px;
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
114
|
+
</head>
|
|
115
|
+
<body>
|
|
116
|
+
<h1>Hello from craft!</h1>
|
|
117
|
+
</body>
|
|
118
|
+
</html>
|
|
119
|
+
`
|
|
120
|
+
|
|
121
|
+
await show(html, {
|
|
122
|
+
title: 'HTML Demo',
|
|
123
|
+
width: 800,
|
|
124
|
+
height: 600,
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Using with stx Desktop Package
|
|
129
|
+
|
|
130
|
+
The `@stacksjs/desktop` package provides a clean wrapper:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { openDevWindow } from '@stacksjs/desktop'
|
|
134
|
+
|
|
135
|
+
// Open dev server in native window
|
|
136
|
+
const success = await openDevWindow(3000, {
|
|
137
|
+
title: 'My Dev Server',
|
|
138
|
+
width: 1400,
|
|
139
|
+
height: 900,
|
|
140
|
+
hotReload: true,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
if (success) {
|
|
144
|
+
console.log('Native window opened!')
|
|
145
|
+
} else {
|
|
146
|
+
console.log('Fell back to browser')
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Advanced Window Options
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { createApp } from 'ts-craft'
|
|
154
|
+
|
|
155
|
+
const app = createApp({
|
|
156
|
+
url: 'http://localhost:3000',
|
|
157
|
+
window: {
|
|
158
|
+
title: 'Advanced Window',
|
|
159
|
+
width: 1000,
|
|
160
|
+
height: 700,
|
|
161
|
+
|
|
162
|
+
// Window style
|
|
163
|
+
frameless: false, // No title bar (default: false)
|
|
164
|
+
transparent: false, // Transparent window (default: false)
|
|
165
|
+
resizable: true, // Allow resizing (default: true)
|
|
166
|
+
alwaysOnTop: false, // Stay on top (default: false)
|
|
167
|
+
fullscreen: false, // Start fullscreen (default: false)
|
|
168
|
+
|
|
169
|
+
// Position (optional)
|
|
170
|
+
x: 100, // X coordinate
|
|
171
|
+
y: 100, // Y coordinate
|
|
172
|
+
|
|
173
|
+
// Appearance
|
|
174
|
+
darkMode: true, // Force dark mode
|
|
175
|
+
|
|
176
|
+
// Development
|
|
177
|
+
hotReload: true, // Enable hot reload
|
|
178
|
+
devTools: true, // Enable DevTools (right-click > Inspect)
|
|
179
|
+
|
|
180
|
+
// System integration
|
|
181
|
+
systemTray: true, // Show menubar icon (required for craft)
|
|
182
|
+
hideDockIcon: false, // Hide from dock (default: false)
|
|
183
|
+
},
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
await app.show()
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Controlling the Window from Web Content
|
|
190
|
+
|
|
191
|
+
craft provides a bridge API accessible from your web content:
|
|
192
|
+
|
|
193
|
+
```html
|
|
194
|
+
<!DOCTYPE html>
|
|
195
|
+
<html>
|
|
196
|
+
<head>
|
|
197
|
+
<title>craft Bridge Demo</title>
|
|
198
|
+
</head>
|
|
199
|
+
<body>
|
|
200
|
+
<h1>craft Bridge API</h1>
|
|
201
|
+
|
|
202
|
+
<button onclick="hideWindow()">Hide Window</button>
|
|
203
|
+
<button onclick="showWindow()">Show Window</button>
|
|
204
|
+
<button onclick="quitApp()">Quit App</button>
|
|
205
|
+
<button onclick="updateTray()">Update Tray Title</button>
|
|
206
|
+
|
|
207
|
+
<script>
|
|
208
|
+
// Access craft bridge API
|
|
209
|
+
const craft = window.craft
|
|
210
|
+
|
|
211
|
+
function hideWindow() {
|
|
212
|
+
craft.window.hide()
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function showWindow() {
|
|
216
|
+
craft.window.show()
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function quitApp() {
|
|
220
|
+
craft.app.quit()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function updateTray() {
|
|
224
|
+
craft.tray.setTitle('Updated!')
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Listen for tray icon clicks
|
|
228
|
+
craft.tray.onClick(() => {
|
|
229
|
+
console.log('Tray icon clicked!')
|
|
230
|
+
craft.window.toggle()
|
|
231
|
+
})
|
|
232
|
+
</script>
|
|
233
|
+
</body>
|
|
234
|
+
</html>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Menubar App Pattern
|
|
238
|
+
|
|
239
|
+
craft is designed for menubar applications. Here's a complete example:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { createApp } from 'ts-craft'
|
|
243
|
+
|
|
244
|
+
const app = createApp({
|
|
245
|
+
url: 'http://localhost:3000',
|
|
246
|
+
window: {
|
|
247
|
+
title: 'My Menubar App',
|
|
248
|
+
width: 400,
|
|
249
|
+
height: 500,
|
|
250
|
+
resizable: false,
|
|
251
|
+
systemTray: true, // Creates menubar icon
|
|
252
|
+
darkMode: true,
|
|
253
|
+
},
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
await app.show()
|
|
257
|
+
|
|
258
|
+
// The window is hidden by default
|
|
259
|
+
// Click the menubar icon to show/hide the window
|
|
260
|
+
// This is the standard macOS menubar app behavior
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Integration with stx CLI
|
|
264
|
+
|
|
265
|
+
When you use the `--native` flag with stx dev server:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
stx dev examples/homepage.stx --native
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
It internally calls:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { openDevWindow } from '@stacksjs/desktop'
|
|
275
|
+
|
|
276
|
+
const success = await openDevWindow(3000, {
|
|
277
|
+
title: 'stx Development',
|
|
278
|
+
width: 1400,
|
|
279
|
+
height: 900,
|
|
280
|
+
hotReload: true,
|
|
281
|
+
devTools: true,
|
|
282
|
+
})
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Modals
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { showInfoModal, showQuestionModal } from '@stacksjs/desktop'
|
|
289
|
+
|
|
290
|
+
// Show an info modal
|
|
291
|
+
await showInfoModal('Welcome', 'Welcome to my app!')
|
|
292
|
+
|
|
293
|
+
// Show a question modal
|
|
294
|
+
const result = await showQuestionModal(
|
|
295
|
+
'Confirm',
|
|
296
|
+
'Are you sure you want to continue?'
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if (!result.cancelled) {
|
|
300
|
+
console.log('User clicked button:', result.buttonIndex)
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Alerts & Toast Notifications
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
import { showSuccessToast, showErrorToast } from '@stacksjs/desktop'
|
|
308
|
+
|
|
309
|
+
// Show success toast
|
|
310
|
+
await showSuccessToast('File saved successfully!')
|
|
311
|
+
|
|
312
|
+
// Show error toast
|
|
313
|
+
await showErrorToast('Failed to save file', 5000)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## API Reference
|
|
317
|
+
|
|
318
|
+
### Window Management
|
|
319
|
+
|
|
320
|
+
#### `createWindow(url, options?)`
|
|
321
|
+
|
|
322
|
+
Create a native window.
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
const window = await createWindow('http://localhost:3000', {
|
|
326
|
+
title: 'My App',
|
|
327
|
+
width: 1200,
|
|
328
|
+
height: 800,
|
|
329
|
+
darkMode: true,
|
|
330
|
+
hotReload: true,
|
|
331
|
+
resizable: true,
|
|
332
|
+
minimizable: true,
|
|
333
|
+
maximizable: true
|
|
334
|
+
})
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Returns:** `WindowInstance | null`
|
|
338
|
+
|
|
339
|
+
#### `openDevWindow(port, options?)`
|
|
340
|
+
|
|
341
|
+
Open a development server window (used by `stx dev --native`).
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
await openDevWindow(3000, {
|
|
345
|
+
title: 'stx Development',
|
|
346
|
+
width: 1400,
|
|
347
|
+
height: 900
|
|
348
|
+
})
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Returns:** `boolean`
|
|
352
|
+
|
|
353
|
+
#### `isWebviewAvailable()`
|
|
354
|
+
|
|
355
|
+
Check if craft is available for native windows.
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
if (!isWebviewAvailable()) {
|
|
359
|
+
console.log('craft not available')
|
|
360
|
+
console.log('Ensure ts-craft is installed and craft binary is built')
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Returns:** `boolean`
|
|
365
|
+
|
|
366
|
+
### System Tray
|
|
367
|
+
|
|
368
|
+
#### `createSystemTray(options)`
|
|
369
|
+
|
|
370
|
+
Create a system tray/menubar application.
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
const tray = await createSystemTray({
|
|
374
|
+
icon: './icon.png',
|
|
375
|
+
tooltip: 'My App',
|
|
376
|
+
menu: [
|
|
377
|
+
{ label: 'Item 1', onClick: () => {} },
|
|
378
|
+
{ type: 'separator' },
|
|
379
|
+
{ label: 'Quit', onClick: () => process.exit(0) }
|
|
380
|
+
]
|
|
381
|
+
})
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Returns:** `SystemTrayInstance | null`
|
|
385
|
+
|
|
386
|
+
### Modals
|
|
387
|
+
|
|
388
|
+
#### `showModal(options)`
|
|
389
|
+
|
|
390
|
+
Show a custom modal dialog.
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
const result = await showModal({
|
|
394
|
+
title: 'Confirm Action',
|
|
395
|
+
message: 'Are you sure?',
|
|
396
|
+
type: 'question',
|
|
397
|
+
buttons: [
|
|
398
|
+
{ label: 'Cancel', style: 'default' },
|
|
399
|
+
{ label: 'OK', style: 'primary' }
|
|
400
|
+
]
|
|
401
|
+
})
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**Returns:** `Promise<ModalResult>`
|
|
405
|
+
|
|
406
|
+
#### Helper Functions
|
|
407
|
+
|
|
408
|
+
- `showInfoModal(title, message)` - Show info modal
|
|
409
|
+
- `showWarningModal(title, message)` - Show warning modal
|
|
410
|
+
- `showErrorModal(title, message)` - Show error modal
|
|
411
|
+
- `showSuccessModal(title, message)` - Show success modal
|
|
412
|
+
- `showQuestionModal(title, message)` - Show question modal
|
|
413
|
+
|
|
414
|
+
### Alerts & Toasts
|
|
415
|
+
|
|
416
|
+
#### `showToast(options)`
|
|
417
|
+
|
|
418
|
+
Show a toast notification.
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
await showToast({
|
|
422
|
+
message: 'Operation complete!',
|
|
423
|
+
type: 'success',
|
|
424
|
+
duration: 3000,
|
|
425
|
+
position: 'top-right',
|
|
426
|
+
theme: 'dark'
|
|
427
|
+
})
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Returns:** `Promise<void>`
|
|
431
|
+
|
|
432
|
+
#### Helper Functions
|
|
433
|
+
|
|
434
|
+
- `showInfoToast(message, duration?)` - Show info toast
|
|
435
|
+
- `showSuccessToast(message, duration?)` - Show success toast
|
|
436
|
+
- `showWarningToast(message, duration?)` - Show warning toast
|
|
437
|
+
- `showErrorToast(message, duration?)` - Show error toast
|
|
438
|
+
|
|
439
|
+
### Components
|
|
440
|
+
|
|
441
|
+
35 native UI components are available (documentation in progress):
|
|
442
|
+
|
|
443
|
+
**Input:** Button, TextInput, Checkbox, RadioButton, Slider, ColorPicker, DatePicker, TimePicker, Autocomplete
|
|
444
|
+
|
|
445
|
+
**Display:** Label, ImageView, ProgressBar, Avatar, Badge, Chip, Card, Tooltip, Toast
|
|
446
|
+
|
|
447
|
+
**Layout:** ScrollView, SplitView, Accordion, Stepper, Modal, Tabs, Dropdown
|
|
448
|
+
|
|
449
|
+
**Data:** ListView, Table, TreeView, DataGrid, Chart
|
|
450
|
+
|
|
451
|
+
**Advanced:** Rating, CodeEditor, MediaPlayer, FileExplorer, WebView
|
|
452
|
+
|
|
453
|
+
**Currently Implemented:**
|
|
454
|
+
- `createButton(props)` - Button component
|
|
455
|
+
- `createTextInput(props)` - Text input component
|
|
456
|
+
- `createCheckbox(props)` - Checkbox component
|
|
457
|
+
|
|
458
|
+
## Platform Support
|
|
459
|
+
|
|
460
|
+
| Platform | Status | Notes |
|
|
461
|
+
|----------|--------|-------|
|
|
462
|
+
| macOS | ✅ Working | Uses WebKit (built-in) |
|
|
463
|
+
| Linux | 🚧 Ready | Requires GTK3 + WebKit2GTK |
|
|
464
|
+
| Windows | 🚧 Ready | Requires WebView2 Runtime |
|
|
465
|
+
|
|
466
|
+
## Development
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
# Install dependencies
|
|
470
|
+
bun install
|
|
471
|
+
|
|
472
|
+
# Build the package
|
|
473
|
+
bun run build
|
|
474
|
+
|
|
475
|
+
# Run tests
|
|
476
|
+
bun test
|
|
477
|
+
|
|
478
|
+
# Run tests with coverage
|
|
479
|
+
bun test --coverage
|
|
480
|
+
|
|
481
|
+
# Type check
|
|
482
|
+
bun run typecheck
|
|
483
|
+
|
|
484
|
+
# Lint
|
|
485
|
+
bun run lint
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Examples
|
|
489
|
+
|
|
490
|
+
See the `examples/` directory for working examples:
|
|
491
|
+
|
|
492
|
+
- `basic-window.ts` - Simple window example
|
|
493
|
+
- `system-tray.ts` - System tray application
|
|
494
|
+
- `modal-demo.ts` - Modal dialogs
|
|
495
|
+
- `alerts-demo.ts` - Alerts and toasts
|
|
496
|
+
- `all-components.ts` - All 35 components showcase
|
|
497
|
+
- `dev-server-integration.ts` - Dev server integration pattern
|
|
498
|
+
|
|
499
|
+
Run any example:
|
|
500
|
+
```bash
|
|
501
|
+
cd packages/desktop
|
|
502
|
+
bun run examples/basic-window.ts
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## Testing
|
|
506
|
+
|
|
507
|
+
The desktop package has comprehensive test coverage:
|
|
508
|
+
|
|
509
|
+
**Coverage Stats:**
|
|
510
|
+
- 132 tests passing
|
|
511
|
+
- 100% function coverage
|
|
512
|
+
- 96.77% line coverage
|
|
513
|
+
- 185 expect() assertions
|
|
514
|
+
|
|
515
|
+
**Test Files:**
|
|
516
|
+
- `test/window.test.ts` - Window management (30+ tests)
|
|
517
|
+
- `test/system-tray.test.ts` - System tray (15+ tests)
|
|
518
|
+
- `test/modals.test.ts` - Modal dialogs (30+ tests)
|
|
519
|
+
- `test/alerts.test.ts` - Alerts and toasts (40+ tests)
|
|
520
|
+
- `test/components.test.ts` - UI components (20+ tests)
|
|
521
|
+
|
|
522
|
+
All business logic is fully tested with proper mocking and error handling coverage.
|
|
523
|
+
|
|
524
|
+
## Comparison with Electron
|
|
525
|
+
|
|
526
|
+
| Feature | @stacksjs/desktop | Electron |
|
|
527
|
+
|---------|------------------|----------|
|
|
528
|
+
| **Binary Size** | 1.4MB | 100MB+ |
|
|
529
|
+
| **Startup Time** | <100ms | 1-3s |
|
|
530
|
+
| **Memory Usage** | ~90MB | 200MB+ |
|
|
531
|
+
| **WebView** | System (WebKit) | Chromium (bundled) |
|
|
532
|
+
| **Distribution** | Tiny | Large |
|
|
533
|
+
|
|
534
|
+
## Contributing
|
|
535
|
+
|
|
536
|
+
Contributions are welcome! Please see the [Contributing Guide](../../CONTRIBUTING.md).
|
|
537
|
+
|
|
538
|
+
## License
|
|
539
|
+
|
|
540
|
+
MIT License - see [LICENSE.md](../../LICENSE.md)
|
|
541
|
+
|
|
542
|
+
## Implementation Status
|
|
543
|
+
|
|
544
|
+
### ✅ Working
|
|
545
|
+
- Native window creation with craft/ts-craft
|
|
546
|
+
- URL loading in native windows
|
|
547
|
+
- HTML content rendering
|
|
548
|
+
- `stx dev --native` flag integration
|
|
549
|
+
- Browser fallback when craft unavailable
|
|
550
|
+
- Hot reload and dev tools support
|
|
551
|
+
|
|
552
|
+
### 🚧 Placeholder (Coming Soon)
|
|
553
|
+
- System tray applications
|
|
554
|
+
- Modal dialogs
|
|
555
|
+
- Alerts and toasts
|
|
556
|
+
- Native UI components (35 total)
|
|
557
|
+
|
|
558
|
+
The package is fully functional for basic native windows using craft. System tray and other features are planned for future releases.
|
|
559
|
+
|
|
560
|
+
## Credits
|
|
561
|
+
|
|
562
|
+
- Powered by [Craft](https://github.com/stacksjs/craft)
|
|
563
|
+
- Part of the [stx](https://github.com/stacksjs/stx) ecosystem
|
package/dist/alerts.d.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { AlertOptions, ToastOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Request notification permission (browser)
|
|
4
|
+
*/
|
|
5
|
+
export declare function requestNotificationPermission(): Promise<boolean>;
|
|
6
|
+
/**
|
|
7
|
+
* Show an alert/notification
|
|
8
|
+
*
|
|
9
|
+
* @param options - Alert configuration options
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* await showAlert({
|
|
14
|
+
* title: 'Success',
|
|
15
|
+
* message: 'Your changes have been saved',
|
|
16
|
+
* type: 'success',
|
|
17
|
+
* duration: 3000,
|
|
18
|
+
* position: 'top-right',
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function showAlert(options: AlertOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Show a toast notification (alias for showAlert with toast-friendly defaults)
|
|
25
|
+
*/
|
|
26
|
+
export declare function showToast(options: ToastOptions): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Show an info toast
|
|
29
|
+
*/
|
|
30
|
+
export declare function showInfoToast(message: string, duration?: any): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Show a success toast
|
|
33
|
+
*/
|
|
34
|
+
export declare function showSuccessToast(message: string, duration?: any): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Show a warning toast
|
|
37
|
+
*/
|
|
38
|
+
export declare function showWarningToast(message: string, duration?: any): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Show an error toast
|
|
41
|
+
*/
|
|
42
|
+
export declare function showErrorToast(message: string, duration?: any): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Show a notification with title
|
|
45
|
+
*/
|
|
46
|
+
export declare function notify(title: string, message: string, type?: AlertOptions['type']): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Dismiss a specific alert by ID
|
|
49
|
+
*/
|
|
50
|
+
export declare function dismissAlertById(id: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Dismiss all active alerts
|
|
53
|
+
*/
|
|
54
|
+
export declare function dismissAllAlerts(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Get count of active alerts
|
|
57
|
+
*/
|
|
58
|
+
export declare function getActiveAlertCount(): number;
|
|
59
|
+
/**
|
|
60
|
+
* CSS styles for web-based toasts
|
|
61
|
+
*/
|
|
62
|
+
export declare const TOAST_STYLES: `
|
|
63
|
+
.stx-toast-container {
|
|
64
|
+
position: fixed;
|
|
65
|
+
z-index: 10001;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 8px;
|
|
69
|
+
max-width: 400px;
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.stx-toast-container.top-left { top: 16px; left: 16px; }
|
|
74
|
+
.stx-toast-container.top-center { top: 16px; left: 50%; transform: translateX(-50%); }
|
|
75
|
+
.stx-toast-container.top-right { top: 16px; right: 16px; }
|
|
76
|
+
.stx-toast-container.bottom-left { bottom: 16px; left: 16px; }
|
|
77
|
+
.stx-toast-container.bottom-center { bottom: 16px; left: 50%; transform: translateX(-50%); }
|
|
78
|
+
.stx-toast-container.bottom-right { bottom: 16px; right: 16px; }
|
|
79
|
+
|
|
80
|
+
.stx-toast {
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: flex-start;
|
|
83
|
+
gap: 12px;
|
|
84
|
+
padding: 12px 16px;
|
|
85
|
+
background: #fff;
|
|
86
|
+
border-radius: 8px;
|
|
87
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
88
|
+
pointer-events: auto;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
opacity: 0;
|
|
91
|
+
transform: translateY(-10px);
|
|
92
|
+
transition: opacity 0.2s, transform 0.2s;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.stx-toast.visible {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
transform: translateY(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.stx-toast.dismissing {
|
|
101
|
+
opacity: 0;
|
|
102
|
+
transform: translateX(100%);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@media (prefers-color-scheme: dark) {
|
|
106
|
+
.stx-toast {
|
|
107
|
+
background: #2d2d2d;
|
|
108
|
+
color: #fff;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.stx-toast-icon {
|
|
113
|
+
font-size: 20px;
|
|
114
|
+
flex-shrink: 0;
|
|
115
|
+
margin-top: 2px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.stx-toast.info .stx-toast-icon { color: #3498db; }
|
|
119
|
+
.stx-toast.success .stx-toast-icon { color: #27ae60; }
|
|
120
|
+
.stx-toast.warning .stx-toast-icon { color: #f39c12; }
|
|
121
|
+
.stx-toast.error .stx-toast-icon { color: #e74c3c; }
|
|
122
|
+
|
|
123
|
+
.stx-toast-content {
|
|
124
|
+
flex: 1;
|
|
125
|
+
min-width: 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.stx-toast-title {
|
|
129
|
+
font-weight: 600;
|
|
130
|
+
margin-bottom: 4px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.stx-toast-message {
|
|
134
|
+
color: #666;
|
|
135
|
+
font-size: 14px;
|
|
136
|
+
line-height: 1.4;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (prefers-color-scheme: dark) {
|
|
140
|
+
.stx-toast-message { color: #aaa; }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.stx-toast-close {
|
|
144
|
+
background: none;
|
|
145
|
+
border: none;
|
|
146
|
+
font-size: 20px;
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
opacity: 0.5;
|
|
149
|
+
padding: 0;
|
|
150
|
+
line-height: 1;
|
|
151
|
+
color: inherit;
|
|
152
|
+
transition: opacity 0.15s;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.stx-toast-close:hover {
|
|
156
|
+
opacity: 1;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Border accent for different types */
|
|
160
|
+
.stx-toast.info { border-left: 4px solid #3498db; }
|
|
161
|
+
.stx-toast.success { border-left: 4px solid #27ae60; }
|
|
162
|
+
.stx-toast.warning { border-left: 4px solid #f39c12; }
|
|
163
|
+
.stx-toast.error { border-left: 4px solid #e74c3c; }
|
|
164
|
+
`;
|