ywana-core8 0.2.4 → 0.2.6
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/dist/index.css +961 -0
- package/dist/index.js +450 -6
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +450 -6
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +450 -6
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/desktop/AppManager.js +270 -0
- package/src/desktop/ApplicationMenu.css +279 -0
- package/src/desktop/ApplicationMenu.js +214 -0
- package/src/desktop/Desktop.stories.jsx +432 -5
- package/src/desktop/WindowContext.js +1 -0
- package/src/desktop/WindowManager.js +23 -0
- package/src/desktop/desktop-linux.css +232 -0
- package/src/desktop/desktop-macos.css +260 -0
- package/src/desktop/desktop-windows.css +190 -0
- package/src/desktop/desktop.js +131 -33
- package/src/desktop/index.js +5 -1
- package/src/desktop/window.js +9 -2
- package/src/examples/ApplicationMenuExample.js +361 -0
package/package.json
CHANGED
@@ -0,0 +1,270 @@
|
|
1
|
+
/**
|
2
|
+
* AppManager - Manages available applications for the desktop
|
3
|
+
*/
|
4
|
+
export class AppManager {
|
5
|
+
constructor() {
|
6
|
+
this.applications = new Map()
|
7
|
+
this.categories = new Map()
|
8
|
+
this.listeners = new Set()
|
9
|
+
|
10
|
+
// Initialize with default applications
|
11
|
+
this.initializeDefaultApps()
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Initialize default applications
|
16
|
+
*/
|
17
|
+
initializeDefaultApps() {
|
18
|
+
// System applications
|
19
|
+
this.registerApp({
|
20
|
+
id: 'file-explorer',
|
21
|
+
name: 'File Explorer',
|
22
|
+
description: 'Browse and manage files',
|
23
|
+
icon: '📁',
|
24
|
+
category: 'System',
|
25
|
+
component: null, // Will be set when registering actual components
|
26
|
+
size: { width: 600, height: 400 },
|
27
|
+
toolbar: null,
|
28
|
+
statusBar: null
|
29
|
+
})
|
30
|
+
|
31
|
+
this.registerApp({
|
32
|
+
id: 'text-editor',
|
33
|
+
name: 'Text Editor',
|
34
|
+
description: 'Edit text files',
|
35
|
+
icon: '📝',
|
36
|
+
category: 'Productivity',
|
37
|
+
component: null,
|
38
|
+
size: { width: 500, height: 350 },
|
39
|
+
toolbar: null,
|
40
|
+
statusBar: null,
|
41
|
+
})
|
42
|
+
|
43
|
+
this.registerApp({
|
44
|
+
id: 'calculator',
|
45
|
+
name: 'Calculator',
|
46
|
+
description: 'Perform calculations',
|
47
|
+
icon: '🧮',
|
48
|
+
category: 'Utilities',
|
49
|
+
component: null,
|
50
|
+
size: { width: 300, height: 400 }
|
51
|
+
})
|
52
|
+
|
53
|
+
this.registerApp({
|
54
|
+
id: 'settings',
|
55
|
+
name: 'Settings',
|
56
|
+
description: 'System configuration',
|
57
|
+
icon: '⚙️',
|
58
|
+
category: 'System',
|
59
|
+
component: null,
|
60
|
+
size: { width: 450, height: 300 }
|
61
|
+
})
|
62
|
+
|
63
|
+
this.registerApp({
|
64
|
+
id: 'browser',
|
65
|
+
name: 'Web Browser',
|
66
|
+
description: 'Browse the internet',
|
67
|
+
icon: '🌐',
|
68
|
+
category: 'Internet',
|
69
|
+
component: null,
|
70
|
+
size: { width: 800, height: 500 }
|
71
|
+
})
|
72
|
+
|
73
|
+
this.registerApp({
|
74
|
+
id: 'terminal',
|
75
|
+
name: 'Terminal',
|
76
|
+
description: 'Command line interface',
|
77
|
+
icon: '💻',
|
78
|
+
category: 'Development',
|
79
|
+
component: null,
|
80
|
+
size: { width: 700, height: 400 }
|
81
|
+
})
|
82
|
+
|
83
|
+
this.registerApp({
|
84
|
+
id: 'image-viewer',
|
85
|
+
name: 'Image Viewer',
|
86
|
+
description: 'View and edit images',
|
87
|
+
icon: '🖼️',
|
88
|
+
category: 'Media',
|
89
|
+
component: null,
|
90
|
+
size: { width: 600, height: 500 }
|
91
|
+
})
|
92
|
+
|
93
|
+
this.registerApp({
|
94
|
+
id: 'music-player',
|
95
|
+
name: 'Music Player',
|
96
|
+
description: 'Play audio files',
|
97
|
+
icon: '🎵',
|
98
|
+
category: 'Media',
|
99
|
+
component: null,
|
100
|
+
size: { width: 400, height: 300 }
|
101
|
+
})
|
102
|
+
|
103
|
+
// Initialize categories
|
104
|
+
this.initializeCategories()
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
* Initialize application categories
|
109
|
+
*/
|
110
|
+
initializeCategories() {
|
111
|
+
const categoryData = [
|
112
|
+
{ id: 'system', name: 'System', icon: '⚙️', color: '#607d8b' },
|
113
|
+
{ id: 'productivity', name: 'Productivity', icon: '📊', color: '#2196f3' },
|
114
|
+
{ id: 'utilities', name: 'Utilities', icon: '🔧', color: '#ff9800' },
|
115
|
+
{ id: 'internet', name: 'Internet', icon: '🌐', color: '#4caf50' },
|
116
|
+
{ id: 'development', name: 'Development', icon: '💻', color: '#9c27b0' },
|
117
|
+
{ id: 'media', name: 'Media', icon: '🎬', color: '#e91e63' },
|
118
|
+
{ id: 'games', name: 'Games', icon: '🎮', color: '#f44336' }
|
119
|
+
]
|
120
|
+
|
121
|
+
categoryData.forEach(category => {
|
122
|
+
this.categories.set(category.id, category)
|
123
|
+
})
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Register a new application
|
128
|
+
*/
|
129
|
+
registerApp(appConfig) {
|
130
|
+
const app = {
|
131
|
+
id: appConfig.id,
|
132
|
+
name: appConfig.name,
|
133
|
+
description: appConfig.description || '',
|
134
|
+
icon: appConfig.icon || '📄',
|
135
|
+
category: appConfig.category || 'Utilities',
|
136
|
+
component: appConfig.component || null,
|
137
|
+
size: appConfig.size || { width: 600, height: 400 },
|
138
|
+
toolbar: appConfig.toolbar || null,
|
139
|
+
statusBar: appConfig.statusBar || null,
|
140
|
+
...appConfig
|
141
|
+
}
|
142
|
+
|
143
|
+
this.applications.set(app.id, app)
|
144
|
+
this.notifyListeners()
|
145
|
+
return app.id
|
146
|
+
}
|
147
|
+
|
148
|
+
/**
|
149
|
+
* Unregister an application
|
150
|
+
*/
|
151
|
+
unregisterApp(appId) {
|
152
|
+
const removed = this.applications.delete(appId)
|
153
|
+
if (removed) {
|
154
|
+
this.notifyListeners()
|
155
|
+
}
|
156
|
+
return removed
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Get an application by ID
|
161
|
+
*/
|
162
|
+
getApp(appId) {
|
163
|
+
return this.applications.get(appId)
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Get all applications
|
168
|
+
*/
|
169
|
+
getAllApps() {
|
170
|
+
return Array.from(this.applications.values())
|
171
|
+
}
|
172
|
+
|
173
|
+
/**
|
174
|
+
* Get applications by category
|
175
|
+
*/
|
176
|
+
getAppsByCategory(categoryId) {
|
177
|
+
return Array.from(this.applications.values())
|
178
|
+
.filter(app => app.category.toLowerCase() === categoryId.toLowerCase())
|
179
|
+
}
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Get all categories
|
183
|
+
*/
|
184
|
+
getAllCategories() {
|
185
|
+
return Array.from(this.categories.values())
|
186
|
+
}
|
187
|
+
|
188
|
+
/**
|
189
|
+
* Get category by ID
|
190
|
+
*/
|
191
|
+
getCategory(categoryId) {
|
192
|
+
return this.categories.get(categoryId.toLowerCase())
|
193
|
+
}
|
194
|
+
|
195
|
+
/**
|
196
|
+
* Search applications
|
197
|
+
*/
|
198
|
+
searchApps(query) {
|
199
|
+
const searchTerm = query.toLowerCase()
|
200
|
+
return Array.from(this.applications.values())
|
201
|
+
.filter(app =>
|
202
|
+
app.name.toLowerCase().includes(searchTerm) ||
|
203
|
+
app.description.toLowerCase().includes(searchTerm) ||
|
204
|
+
app.category.toLowerCase().includes(searchTerm)
|
205
|
+
)
|
206
|
+
}
|
207
|
+
|
208
|
+
/**
|
209
|
+
* Add listener for changes
|
210
|
+
*/
|
211
|
+
addListener(listener) {
|
212
|
+
this.listeners.add(listener)
|
213
|
+
}
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Remove listener
|
217
|
+
*/
|
218
|
+
removeListener(listener) {
|
219
|
+
this.listeners.delete(listener)
|
220
|
+
}
|
221
|
+
|
222
|
+
/**
|
223
|
+
* Notify all listeners about changes
|
224
|
+
*/
|
225
|
+
notifyListeners() {
|
226
|
+
this.listeners.forEach(listener => listener(this.getAllApps()))
|
227
|
+
}
|
228
|
+
|
229
|
+
/**
|
230
|
+
* Get applications grouped by category
|
231
|
+
*/
|
232
|
+
getAppsGroupedByCategory() {
|
233
|
+
const grouped = {}
|
234
|
+
const categories = this.getAllCategories()
|
235
|
+
|
236
|
+
// Initialize categories
|
237
|
+
categories.forEach(category => {
|
238
|
+
grouped[category.id] = {
|
239
|
+
category: category,
|
240
|
+
apps: []
|
241
|
+
}
|
242
|
+
})
|
243
|
+
|
244
|
+
// Group applications
|
245
|
+
this.getAllApps().forEach(app => {
|
246
|
+
const categoryId = app.category.toLowerCase()
|
247
|
+
if (grouped[categoryId]) {
|
248
|
+
grouped[categoryId].apps.push(app)
|
249
|
+
} else {
|
250
|
+
// Create category if it doesn't exist
|
251
|
+
grouped[categoryId] = {
|
252
|
+
category: { id: categoryId, name: app.category, icon: '📁', color: '#757575' },
|
253
|
+
apps: [app]
|
254
|
+
}
|
255
|
+
}
|
256
|
+
})
|
257
|
+
|
258
|
+
// Remove empty categories
|
259
|
+
Object.keys(grouped).forEach(key => {
|
260
|
+
if (grouped[key].apps.length === 0) {
|
261
|
+
delete grouped[key]
|
262
|
+
}
|
263
|
+
})
|
264
|
+
|
265
|
+
return grouped
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
// Create default instance
|
270
|
+
export const defaultAppManager = new AppManager()
|
@@ -0,0 +1,279 @@
|
|
1
|
+
/* ApplicationMenu - Full-screen overlay styles */
|
2
|
+
|
3
|
+
.application-menu-overlay {
|
4
|
+
position: fixed;
|
5
|
+
top: 0;
|
6
|
+
left: 0;
|
7
|
+
right: 0;
|
8
|
+
bottom: 0;
|
9
|
+
background: rgba(0, 0, 0, 0.8);
|
10
|
+
backdrop-filter: blur(8px);
|
11
|
+
z-index: 10000;
|
12
|
+
display: flex;
|
13
|
+
align-items: center;
|
14
|
+
justify-content: center;
|
15
|
+
animation: fadeIn 0.2s ease-out;
|
16
|
+
}
|
17
|
+
|
18
|
+
@keyframes fadeIn {
|
19
|
+
from {
|
20
|
+
opacity: 0;
|
21
|
+
}
|
22
|
+
to {
|
23
|
+
opacity: 1;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
.application-menu {
|
28
|
+
background: #ffffff;
|
29
|
+
border-radius: 12px;
|
30
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
31
|
+
width: 90%;
|
32
|
+
max-width: 900px;
|
33
|
+
height: 80%;
|
34
|
+
max-height: 700px;
|
35
|
+
display: flex;
|
36
|
+
flex-direction: column;
|
37
|
+
overflow: hidden;
|
38
|
+
animation: slideIn 0.3s ease-out;
|
39
|
+
}
|
40
|
+
|
41
|
+
@keyframes slideIn {
|
42
|
+
from {
|
43
|
+
transform: scale(0.9) translateY(20px);
|
44
|
+
opacity: 0;
|
45
|
+
}
|
46
|
+
to {
|
47
|
+
transform: scale(1) translateY(0);
|
48
|
+
opacity: 1;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
/* Header */
|
53
|
+
.application-menu__header {
|
54
|
+
display: flex;
|
55
|
+
align-items: center;
|
56
|
+
justify-content: space-between;
|
57
|
+
padding: 20px 24px;
|
58
|
+
border-bottom: 1px solid #e0e0e0;
|
59
|
+
background: #f8f9fa;
|
60
|
+
}
|
61
|
+
|
62
|
+
.application-menu__header h2 {
|
63
|
+
margin: 0;
|
64
|
+
color: #333;
|
65
|
+
font-size: 24px;
|
66
|
+
font-weight: 600;
|
67
|
+
}
|
68
|
+
|
69
|
+
.application-menu__close {
|
70
|
+
background: none;
|
71
|
+
border: none;
|
72
|
+
font-size: 24px;
|
73
|
+
color: #666;
|
74
|
+
cursor: pointer;
|
75
|
+
padding: 4px 8px;
|
76
|
+
border-radius: 4px;
|
77
|
+
transition: all 0.2s ease;
|
78
|
+
}
|
79
|
+
|
80
|
+
.application-menu__close:hover {
|
81
|
+
background: #e0e0e0;
|
82
|
+
color: #333;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* Search */
|
86
|
+
.application-menu__search {
|
87
|
+
padding: 16px 24px;
|
88
|
+
border-bottom: 1px solid #e0e0e0;
|
89
|
+
}
|
90
|
+
|
91
|
+
.application-menu__search-input {
|
92
|
+
width: 100%;
|
93
|
+
padding: 12px 16px;
|
94
|
+
border: 2px solid #e0e0e0;
|
95
|
+
border-radius: 8px;
|
96
|
+
font-size: 16px;
|
97
|
+
outline: none;
|
98
|
+
transition: border-color 0.2s ease;
|
99
|
+
}
|
100
|
+
|
101
|
+
.application-menu__search-input:focus {
|
102
|
+
border-color: #1976d2;
|
103
|
+
}
|
104
|
+
|
105
|
+
/* Categories */
|
106
|
+
.application-menu__categories {
|
107
|
+
display: flex;
|
108
|
+
gap: 8px;
|
109
|
+
padding: 16px 24px;
|
110
|
+
border-bottom: 1px solid #e0e0e0;
|
111
|
+
background: #f8f9fa;
|
112
|
+
overflow-x: auto;
|
113
|
+
}
|
114
|
+
|
115
|
+
.application-menu__category {
|
116
|
+
display: flex;
|
117
|
+
align-items: center;
|
118
|
+
gap: 8px;
|
119
|
+
padding: 8px 16px;
|
120
|
+
background: #ffffff;
|
121
|
+
border: 1px solid #e0e0e0;
|
122
|
+
border-radius: 20px;
|
123
|
+
cursor: pointer;
|
124
|
+
font-size: 14px;
|
125
|
+
white-space: nowrap;
|
126
|
+
transition: all 0.2s ease;
|
127
|
+
color: #666;
|
128
|
+
}
|
129
|
+
|
130
|
+
.application-menu__category:hover {
|
131
|
+
background: #f0f0f0;
|
132
|
+
border-color: #ccc;
|
133
|
+
}
|
134
|
+
|
135
|
+
.application-menu__category.active {
|
136
|
+
background: #1976d2;
|
137
|
+
border-color: #1976d2;
|
138
|
+
color: white;
|
139
|
+
}
|
140
|
+
|
141
|
+
.category-icon {
|
142
|
+
font-size: 16px;
|
143
|
+
}
|
144
|
+
|
145
|
+
/* Content */
|
146
|
+
.application-menu__content {
|
147
|
+
flex: 1;
|
148
|
+
overflow-y: auto;
|
149
|
+
padding: 24px;
|
150
|
+
}
|
151
|
+
|
152
|
+
.application-menu__search-results h3,
|
153
|
+
.category-title {
|
154
|
+
margin: 0 0 16px 0;
|
155
|
+
color: #333;
|
156
|
+
font-size: 18px;
|
157
|
+
font-weight: 600;
|
158
|
+
}
|
159
|
+
|
160
|
+
.application-menu__category-section {
|
161
|
+
margin-bottom: 32px;
|
162
|
+
}
|
163
|
+
|
164
|
+
.application-menu__category-section:last-child {
|
165
|
+
margin-bottom: 0;
|
166
|
+
}
|
167
|
+
|
168
|
+
/* Apps Grid */
|
169
|
+
.application-menu__apps-grid {
|
170
|
+
display: grid;
|
171
|
+
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
172
|
+
gap: 16px;
|
173
|
+
}
|
174
|
+
|
175
|
+
.application-menu__app {
|
176
|
+
display: flex;
|
177
|
+
flex-direction: column;
|
178
|
+
align-items: center;
|
179
|
+
padding: 16px 12px;
|
180
|
+
border-radius: 12px;
|
181
|
+
cursor: pointer;
|
182
|
+
transition: all 0.2s ease;
|
183
|
+
text-align: center;
|
184
|
+
background: #ffffff;
|
185
|
+
border: 1px solid transparent;
|
186
|
+
}
|
187
|
+
|
188
|
+
.application-menu__app:hover {
|
189
|
+
background: #f8f9fa;
|
190
|
+
border-color: #e0e0e0;
|
191
|
+
transform: translateY(-2px);
|
192
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
193
|
+
}
|
194
|
+
|
195
|
+
.app-icon {
|
196
|
+
font-size: 48px;
|
197
|
+
margin-bottom: 8px;
|
198
|
+
line-height: 1;
|
199
|
+
}
|
200
|
+
|
201
|
+
.app-name {
|
202
|
+
font-size: 14px;
|
203
|
+
font-weight: 500;
|
204
|
+
color: #333;
|
205
|
+
line-height: 1.2;
|
206
|
+
word-break: break-word;
|
207
|
+
}
|
208
|
+
|
209
|
+
/* No Results */
|
210
|
+
.application-menu__no-results {
|
211
|
+
text-align: center;
|
212
|
+
padding: 60px 20px;
|
213
|
+
color: #666;
|
214
|
+
}
|
215
|
+
|
216
|
+
.application-menu__no-results h3 {
|
217
|
+
margin: 0 0 8px 0;
|
218
|
+
color: #333;
|
219
|
+
font-size: 20px;
|
220
|
+
}
|
221
|
+
|
222
|
+
.application-menu__no-results p {
|
223
|
+
margin: 0;
|
224
|
+
font-size: 16px;
|
225
|
+
}
|
226
|
+
|
227
|
+
/* Responsive */
|
228
|
+
@media (max-width: 768px) {
|
229
|
+
.application-menu {
|
230
|
+
width: 95%;
|
231
|
+
height: 90%;
|
232
|
+
margin: 20px;
|
233
|
+
}
|
234
|
+
|
235
|
+
.application-menu__apps-grid {
|
236
|
+
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
237
|
+
gap: 12px;
|
238
|
+
}
|
239
|
+
|
240
|
+
.application-menu__app {
|
241
|
+
padding: 12px 8px;
|
242
|
+
}
|
243
|
+
|
244
|
+
.app-icon {
|
245
|
+
font-size: 40px;
|
246
|
+
}
|
247
|
+
|
248
|
+
.app-name {
|
249
|
+
font-size: 12px;
|
250
|
+
}
|
251
|
+
|
252
|
+
.application-menu__categories {
|
253
|
+
padding: 12px 16px;
|
254
|
+
}
|
255
|
+
|
256
|
+
.application-menu__search,
|
257
|
+
.application-menu__content {
|
258
|
+
padding: 16px;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
|
262
|
+
/* Scrollbar styling */
|
263
|
+
.application-menu__content::-webkit-scrollbar {
|
264
|
+
width: 8px;
|
265
|
+
}
|
266
|
+
|
267
|
+
.application-menu__content::-webkit-scrollbar-track {
|
268
|
+
background: #f1f1f1;
|
269
|
+
border-radius: 4px;
|
270
|
+
}
|
271
|
+
|
272
|
+
.application-menu__content::-webkit-scrollbar-thumb {
|
273
|
+
background: #c1c1c1;
|
274
|
+
border-radius: 4px;
|
275
|
+
}
|
276
|
+
|
277
|
+
.application-menu__content::-webkit-scrollbar-thumb:hover {
|
278
|
+
background: #a8a8a8;
|
279
|
+
}
|