ywana-core8 0.2.6 → 0.2.8
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 +452 -54
- package/dist/index.js +267 -89
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +267 -89
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +267 -89
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/desktop/ApplicationMenu.css +153 -54
- package/src/desktop/ApplicationMenu.js +75 -69
- package/src/desktop/Desktop.stories.jsx +87 -12
- package/src/desktop/WindowContext.js +3 -0
- package/src/desktop/WindowManager.js +32 -10
- package/src/desktop/desktop-linux.css +55 -0
- package/src/desktop/desktop-macos.css +57 -0
- package/src/desktop/desktop-windows.css +54 -0
- package/src/desktop/desktop.css +30 -0
- package/src/desktop/desktop.js +100 -66
- package/src/desktop/window.css +98 -0
- package/src/desktop/window.js +163 -2
- package/src/html/button.css +5 -0
- package/src/html/button.js +2 -1
package/package.json
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
-
/* ApplicationMenu -
|
1
|
+
/* ApplicationMenu - Positioned over workspace only */
|
2
2
|
|
3
3
|
.application-menu-overlay {
|
4
|
-
position:
|
4
|
+
position: absolute;
|
5
5
|
top: 0;
|
6
6
|
left: 0;
|
7
7
|
right: 0;
|
8
|
-
bottom: 0;
|
8
|
+
bottom: 0; /* Covers entire workspace container */
|
9
9
|
background: rgba(0, 0, 0, 0.8);
|
10
10
|
backdrop-filter: blur(8px);
|
11
|
-
z-index: 10000;
|
11
|
+
z-index: 10000; /* Always above all windows */
|
12
12
|
display: flex;
|
13
13
|
align-items: center;
|
14
14
|
justify-content: center;
|
15
15
|
animation: fadeIn 0.2s ease-out;
|
16
|
+
pointer-events: auto; /* Ensure menu is clickable */
|
16
17
|
}
|
17
18
|
|
18
19
|
@keyframes fadeIn {
|
@@ -29,11 +30,15 @@
|
|
29
30
|
border-radius: 12px;
|
30
31
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
31
32
|
width: 90%;
|
32
|
-
max-width:
|
33
|
-
height:
|
34
|
-
max-height:
|
35
|
-
display:
|
36
|
-
|
33
|
+
max-width: 1000px;
|
34
|
+
height: 90%; /* Use most of workspace height */
|
35
|
+
max-height: 100%; /* Constrained by workspace container */
|
36
|
+
display: grid;
|
37
|
+
grid-template-rows: auto auto 1fr;
|
38
|
+
grid-template-areas:
|
39
|
+
"header"
|
40
|
+
"search"
|
41
|
+
"main";
|
37
42
|
overflow: hidden;
|
38
43
|
animation: slideIn 0.3s ease-out;
|
39
44
|
}
|
@@ -51,6 +56,7 @@
|
|
51
56
|
|
52
57
|
/* Header */
|
53
58
|
.application-menu__header {
|
59
|
+
grid-area: header;
|
54
60
|
display: flex;
|
55
61
|
align-items: center;
|
56
62
|
justify-content: space-between;
|
@@ -84,6 +90,7 @@
|
|
84
90
|
|
85
91
|
/* Search */
|
86
92
|
.application-menu__search {
|
93
|
+
grid-area: search;
|
87
94
|
padding: 16px 24px;
|
88
95
|
border-bottom: 1px solid #e0e0e0;
|
89
96
|
}
|
@@ -102,51 +109,116 @@
|
|
102
109
|
border-color: #1976d2;
|
103
110
|
}
|
104
111
|
|
112
|
+
/* Main Grid Layout */
|
113
|
+
.application-menu__main {
|
114
|
+
grid-area: main;
|
115
|
+
display: grid;
|
116
|
+
grid-template-columns: 200px 1fr;
|
117
|
+
grid-template-areas: "sidebar content";
|
118
|
+
height: 100%;
|
119
|
+
overflow: hidden;
|
120
|
+
}
|
121
|
+
|
122
|
+
/* Sidebar */
|
123
|
+
.application-menu__sidebar {
|
124
|
+
grid-area: sidebar;
|
125
|
+
background: #f8f9fa;
|
126
|
+
border-right: 1px solid #e0e0e0;
|
127
|
+
overflow: hidden;
|
128
|
+
display: flex;
|
129
|
+
flex-direction: column;
|
130
|
+
}
|
131
|
+
|
105
132
|
/* Categories */
|
106
133
|
.application-menu__categories {
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
134
|
+
flex: 1;
|
135
|
+
padding: 16px 0;
|
136
|
+
overflow-y: auto;
|
137
|
+
scrollbar-width: thin;
|
138
|
+
scrollbar-color: #ccc transparent;
|
139
|
+
}
|
140
|
+
|
141
|
+
.application-menu__categories::-webkit-scrollbar {
|
142
|
+
width: 6px;
|
143
|
+
}
|
144
|
+
|
145
|
+
.application-menu__categories::-webkit-scrollbar-track {
|
146
|
+
background: transparent;
|
147
|
+
}
|
148
|
+
|
149
|
+
.application-menu__categories::-webkit-scrollbar-thumb {
|
150
|
+
background: #ccc;
|
151
|
+
border-radius: 3px;
|
152
|
+
}
|
153
|
+
|
154
|
+
.application-menu__categories::-webkit-scrollbar-thumb:hover {
|
155
|
+
background: #999;
|
113
156
|
}
|
114
157
|
|
115
158
|
.application-menu__category {
|
116
159
|
display: flex;
|
117
160
|
align-items: center;
|
118
|
-
gap:
|
119
|
-
padding:
|
120
|
-
|
121
|
-
|
122
|
-
border
|
161
|
+
gap: 12px;
|
162
|
+
padding: 12px 20px;
|
163
|
+
margin: 2px 8px;
|
164
|
+
background: transparent;
|
165
|
+
border: none;
|
166
|
+
border-radius: 8px;
|
123
167
|
cursor: pointer;
|
124
168
|
font-size: 14px;
|
125
|
-
|
169
|
+
text-align: left;
|
126
170
|
transition: all 0.2s ease;
|
127
171
|
color: #666;
|
172
|
+
width: calc(100% - 16px);
|
128
173
|
}
|
129
174
|
|
130
175
|
.application-menu__category:hover {
|
131
|
-
background: #
|
132
|
-
|
176
|
+
background: #e9ecef;
|
177
|
+
color: #333;
|
133
178
|
}
|
134
179
|
|
135
180
|
.application-menu__category.active {
|
136
181
|
background: #1976d2;
|
137
|
-
border-color: #1976d2;
|
138
182
|
color: white;
|
139
183
|
}
|
140
184
|
|
141
185
|
.category-icon {
|
142
|
-
font-size:
|
186
|
+
font-size: 18px;
|
187
|
+
min-width: 18px;
|
188
|
+
}
|
189
|
+
|
190
|
+
.category-name {
|
191
|
+
flex: 1;
|
192
|
+
white-space: nowrap;
|
193
|
+
overflow: hidden;
|
194
|
+
text-overflow: ellipsis;
|
143
195
|
}
|
144
196
|
|
145
197
|
/* Content */
|
146
198
|
.application-menu__content {
|
147
|
-
|
199
|
+
grid-area: content;
|
148
200
|
overflow-y: auto;
|
149
201
|
padding: 24px;
|
202
|
+
scrollbar-width: thin;
|
203
|
+
scrollbar-color: #ccc transparent;
|
204
|
+
}
|
205
|
+
|
206
|
+
.application-menu__content::-webkit-scrollbar {
|
207
|
+
width: 8px;
|
208
|
+
}
|
209
|
+
|
210
|
+
.application-menu__content::-webkit-scrollbar-track {
|
211
|
+
background: #f1f1f1;
|
212
|
+
border-radius: 4px;
|
213
|
+
}
|
214
|
+
|
215
|
+
.application-menu__content::-webkit-scrollbar-thumb {
|
216
|
+
background: #ccc;
|
217
|
+
border-radius: 4px;
|
218
|
+
}
|
219
|
+
|
220
|
+
.application-menu__content::-webkit-scrollbar-thumb:hover {
|
221
|
+
background: #999;
|
150
222
|
}
|
151
223
|
|
152
224
|
.application-menu__search-results h3,
|
@@ -168,8 +240,9 @@
|
|
168
240
|
/* Apps Grid */
|
169
241
|
.application-menu__apps-grid {
|
170
242
|
display: grid;
|
171
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
243
|
+
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
172
244
|
gap: 16px;
|
245
|
+
max-width: 100%;
|
173
246
|
}
|
174
247
|
|
175
248
|
.application-menu__app {
|
@@ -228,52 +301,78 @@
|
|
228
301
|
@media (max-width: 768px) {
|
229
302
|
.application-menu {
|
230
303
|
width: 95%;
|
231
|
-
height:
|
232
|
-
|
304
|
+
height: 95%;
|
305
|
+
max-height: 100%; /* Constrained by workspace container */
|
306
|
+
margin: 5px;
|
233
307
|
}
|
234
|
-
|
308
|
+
|
309
|
+
.application-menu__main {
|
310
|
+
grid-template-columns: 160px 1fr;
|
311
|
+
}
|
312
|
+
|
313
|
+
.application-menu__category {
|
314
|
+
padding: 10px 16px;
|
315
|
+
font-size: 13px;
|
316
|
+
}
|
317
|
+
|
318
|
+
.category-icon {
|
319
|
+
font-size: 16px;
|
320
|
+
}
|
321
|
+
|
235
322
|
.application-menu__apps-grid {
|
236
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
323
|
+
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
237
324
|
gap: 12px;
|
238
325
|
}
|
239
|
-
|
326
|
+
|
240
327
|
.application-menu__app {
|
241
328
|
padding: 12px 8px;
|
242
329
|
}
|
243
|
-
|
330
|
+
|
244
331
|
.app-icon {
|
245
|
-
font-size:
|
332
|
+
font-size: 36px;
|
246
333
|
}
|
247
|
-
|
334
|
+
|
248
335
|
.app-name {
|
249
336
|
font-size: 12px;
|
250
337
|
}
|
251
|
-
|
252
|
-
.application-menu__categories {
|
253
|
-
padding: 12px 16px;
|
254
|
-
}
|
255
|
-
|
338
|
+
|
256
339
|
.application-menu__search,
|
257
340
|
.application-menu__content {
|
258
341
|
padding: 16px;
|
259
342
|
}
|
260
343
|
}
|
261
344
|
|
262
|
-
|
263
|
-
|
264
|
-
width: 8px;
|
265
|
-
}
|
345
|
+
@media (max-width: 480px) {
|
346
|
+
/* ApplicationMenu overlay covers entire workspace on mobile */
|
266
347
|
|
267
|
-
.application-
|
268
|
-
|
269
|
-
|
270
|
-
|
348
|
+
.application-menu__main {
|
349
|
+
grid-template-columns: 1fr;
|
350
|
+
grid-template-rows: auto 1fr;
|
351
|
+
grid-template-areas:
|
352
|
+
"sidebar"
|
353
|
+
"content";
|
354
|
+
}
|
271
355
|
|
272
|
-
.application-
|
273
|
-
|
274
|
-
|
275
|
-
}
|
356
|
+
.application-menu__sidebar {
|
357
|
+
border-right: none;
|
358
|
+
border-bottom: 1px solid #e0e0e0;
|
359
|
+
}
|
276
360
|
|
277
|
-
.application-
|
278
|
-
|
361
|
+
.application-menu__categories {
|
362
|
+
display: flex;
|
363
|
+
flex-direction: row;
|
364
|
+
overflow-x: auto;
|
365
|
+
overflow-y: hidden;
|
366
|
+
padding: 12px 16px;
|
367
|
+
gap: 8px;
|
368
|
+
}
|
369
|
+
|
370
|
+
.application-menu__category {
|
371
|
+
flex-shrink: 0;
|
372
|
+
white-space: nowrap;
|
373
|
+
margin: 0;
|
374
|
+
width: auto;
|
375
|
+
}
|
279
376
|
}
|
377
|
+
|
378
|
+
|
@@ -7,6 +7,7 @@ import './ApplicationMenu.css'
|
|
7
7
|
* ApplicationMenu - Full-screen overlay menu for launching applications
|
8
8
|
*/
|
9
9
|
export const ApplicationMenu = ({ isOpen, onClose }) => {
|
10
|
+
console.log('ApplicationMenu render - isOpen:', isOpen, 'onClose:', onClose)
|
10
11
|
const appManager = useAppManager()
|
11
12
|
const [searchTerm, setSearchTerm] = useState('')
|
12
13
|
const [selectedCategory, setSelectedCategory] = useState('all')
|
@@ -112,7 +113,7 @@ export const ApplicationMenu = ({ isOpen, onClose }) => {
|
|
112
113
|
{/* Header */}
|
113
114
|
<div className="application-menu__header">
|
114
115
|
<h2>Applications</h2>
|
115
|
-
<button
|
116
|
+
<button
|
116
117
|
className="application-menu__close"
|
117
118
|
onClick={onClose}
|
118
119
|
title="Close menu"
|
@@ -133,78 +134,83 @@ export const ApplicationMenu = ({ isOpen, onClose }) => {
|
|
133
134
|
/>
|
134
135
|
</div>
|
135
136
|
|
136
|
-
{/*
|
137
|
-
<div className="application-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
137
|
+
{/* Main Grid Layout */}
|
138
|
+
<div className="application-menu__main">
|
139
|
+
{/* Categories Sidebar */}
|
140
|
+
<div className="application-menu__sidebar">
|
141
|
+
<div className="application-menu__categories">
|
142
|
+
<button
|
143
|
+
className={`application-menu__category ${selectedCategory === 'all' ? 'active' : ''}`}
|
144
|
+
onClick={() => handleCategorySelect('all')}
|
145
|
+
>
|
146
|
+
<span className="category-icon">📱</span>
|
147
|
+
<span className="category-name">All Apps</span>
|
148
|
+
</button>
|
149
|
+
{categories.map(category => (
|
150
|
+
<button
|
151
|
+
key={category.id}
|
152
|
+
className={`application-menu__category ${selectedCategory === category.id ? 'active' : ''}`}
|
153
|
+
onClick={() => handleCategorySelect(category.id)}
|
154
|
+
>
|
155
|
+
<span className="category-icon">{category.icon}</span>
|
156
|
+
<span className="category-name">{category.name}</span>
|
157
|
+
</button>
|
158
|
+
))}
|
159
|
+
</div>
|
160
|
+
</div>
|
161
|
+
|
162
|
+
{/* Applications Content */}
|
163
|
+
<div className="application-menu__content">
|
164
|
+
{searchTerm && (
|
165
|
+
<div className="application-menu__search-results">
|
166
|
+
<h3>Search Results ({filteredApps.length})</h3>
|
167
|
+
<div className="application-menu__apps-grid">
|
168
|
+
{filteredApps.map(app => (
|
169
|
+
<div
|
170
|
+
key={app.id}
|
171
|
+
className="application-menu__app"
|
172
|
+
onClick={() => handleLaunchApp(app)}
|
173
|
+
title={app.description}
|
174
|
+
>
|
175
|
+
<div className="app-icon">{app.icon}</div>
|
176
|
+
<div className="app-name">{app.name}</div>
|
177
|
+
</div>
|
178
|
+
))}
|
179
|
+
</div>
|
180
|
+
</div>
|
181
|
+
)}
|
182
|
+
|
183
|
+
{!searchTerm && (
|
184
|
+
<div className="application-menu__categories-content">
|
185
|
+
{Object.entries(groupedApps).map(([categoryName, categoryApps]) => (
|
186
|
+
<div key={categoryName} className="application-menu__category-section">
|
187
|
+
<h3 className="category-title">{categoryName}</h3>
|
188
|
+
<div className="application-menu__apps-grid">
|
189
|
+
{categoryApps.map(app => (
|
190
|
+
<div
|
191
|
+
key={app.id}
|
192
|
+
className="application-menu__app"
|
193
|
+
onClick={() => handleLaunchApp(app)}
|
194
|
+
title={app.description}
|
195
|
+
>
|
196
|
+
<div className="app-icon">{app.icon}</div>
|
197
|
+
<div className="app-name">{app.name}</div>
|
198
|
+
</div>
|
199
|
+
))}
|
200
|
+
</div>
|
172
201
|
</div>
|
173
202
|
))}
|
174
203
|
</div>
|
175
|
-
|
176
|
-
)}
|
177
|
-
|
178
|
-
{!searchTerm && (
|
179
|
-
<div className="application-menu__categories-content">
|
180
|
-
{Object.entries(groupedApps).map(([categoryName, categoryApps]) => (
|
181
|
-
<div key={categoryName} className="application-menu__category-section">
|
182
|
-
<h3 className="category-title">{categoryName}</h3>
|
183
|
-
<div className="application-menu__apps-grid">
|
184
|
-
{categoryApps.map(app => (
|
185
|
-
<div
|
186
|
-
key={app.id}
|
187
|
-
className="application-menu__app"
|
188
|
-
onClick={() => handleLaunchApp(app)}
|
189
|
-
title={app.description}
|
190
|
-
>
|
191
|
-
<div className="app-icon">{app.icon}</div>
|
192
|
-
<div className="app-name">{app.name}</div>
|
193
|
-
</div>
|
194
|
-
))}
|
195
|
-
</div>
|
196
|
-
</div>
|
197
|
-
))}
|
198
|
-
</div>
|
199
|
-
)}
|
204
|
+
)}
|
200
205
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
206
|
+
{filteredApps.length === 0 && (
|
207
|
+
<div className="application-menu__no-results">
|
208
|
+
<div style={{ fontSize: '48px', marginBottom: '16px' }}>🔍</div>
|
209
|
+
<h3>No applications found</h3>
|
210
|
+
<p>Try adjusting your search or category filter.</p>
|
211
|
+
</div>
|
212
|
+
)}
|
213
|
+
</div>
|
208
214
|
</div>
|
209
215
|
</div>
|
210
216
|
</div>
|
@@ -7,7 +7,7 @@ import { defaultAppManager } from './AppManager.js'
|
|
7
7
|
*/
|
8
8
|
export const BasicDesktop = () => (
|
9
9
|
<div style={{ height: '600px', width: '100%', position: 'relative', overflow: 'hidden' }}>
|
10
|
-
<Desktop>
|
10
|
+
<Desktop desktopSize={{ width: 1200, height: 600 }}>
|
11
11
|
<div style={{
|
12
12
|
position: 'absolute',
|
13
13
|
top: '50%',
|
@@ -61,7 +61,7 @@ export const CustomSizeDesktop = () => (
|
|
61
61
|
*/
|
62
62
|
export const DarkDesktop = () => (
|
63
63
|
<div style={{ height: '600px', width: '100%', position: 'relative', overflow: 'hidden' }}>
|
64
|
-
<Desktop className="desktop--dark">
|
64
|
+
<Desktop className="desktop--dark" desktopSize={{ width: 1200, height: 600 }}>
|
65
65
|
<div style={{
|
66
66
|
position: 'absolute',
|
67
67
|
top: '50%',
|
@@ -88,7 +88,7 @@ export const DarkDesktop = () => (
|
|
88
88
|
*/
|
89
89
|
export const LightDesktop = () => (
|
90
90
|
<div style={{ height: '600px', width: '100%', position: 'relative', overflow: 'hidden' }}>
|
91
|
-
<Desktop className="desktop--light">
|
91
|
+
<Desktop className="desktop--light" desktopSize={{ width: 1200, height: 600 }}>
|
92
92
|
<div style={{
|
93
93
|
position: 'absolute',
|
94
94
|
top: '50%',
|
@@ -238,18 +238,21 @@ export const ApplicationMenuBasic = () => (
|
|
238
238
|
boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
|
239
239
|
maxWidth: '400px'
|
240
240
|
}}>
|
241
|
-
<h3 style={{ margin: '0 0 15px 0' }}>🚀
|
241
|
+
<h3 style={{ margin: '0 0 15px 0' }}>🚀 New Layout: Workspace + Menu</h3>
|
242
242
|
<p style={{ margin: '0 0 15px 0', lineHeight: '1.5' }}>
|
243
|
-
Click
|
244
|
-
|
243
|
+
Click <strong>"Start"</strong> to open the Application Menu.
|
244
|
+
The new architecture has a <strong>dedicated Workspace</strong> that contains windows,
|
245
|
+
and the <strong>ApplicationMenu overlays only the workspace</strong> (never the taskbar).
|
245
246
|
</p>
|
246
247
|
<div style={{ fontSize: '14px', color: '#666' }}>
|
247
|
-
<p><strong>
|
248
|
+
<p><strong>New Architecture:</strong></p>
|
248
249
|
<ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
|
249
|
-
<li>
|
250
|
-
<li>
|
251
|
-
<li>
|
252
|
-
<li>
|
250
|
+
<li>✅ <strong>Workspace container</strong> with proper boundaries</li>
|
251
|
+
<li>✅ <strong>Windows constrained</strong> to workspace area</li>
|
252
|
+
<li>✅ <strong>ApplicationMenu over workspace</strong> only</li>
|
253
|
+
<li>✅ <strong>Taskbar always accessible</strong> and separate</li>
|
254
|
+
<li>✅ Categories sidebar with independent scrolling</li>
|
255
|
+
<li>✅ Responsive grid layout</li>
|
253
256
|
</ul>
|
254
257
|
</div>
|
255
258
|
</div>
|
@@ -428,7 +431,79 @@ export const ThemeComparison = () => (
|
|
428
431
|
)
|
429
432
|
|
430
433
|
/**
|
431
|
-
*
|
434
|
+
* Resizable Windows Demo
|
435
|
+
*/
|
436
|
+
export const ResizableWindows = () => (
|
437
|
+
<div style={{ height: '600px', width: '100%', position: 'relative', overflow: 'hidden' }}>
|
438
|
+
<Desktop desktopSize={{ width: 1200, height: 600 }}>
|
439
|
+
<div style={{
|
440
|
+
position: 'absolute',
|
441
|
+
top: '20px',
|
442
|
+
left: '20px',
|
443
|
+
background: 'rgba(255,255,255,0.9)',
|
444
|
+
padding: '20px',
|
445
|
+
borderRadius: '8px',
|
446
|
+
boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
|
447
|
+
maxWidth: '400px'
|
448
|
+
}}>
|
449
|
+
<h3 style={{ margin: '0 0 15px 0' }}>🔄 Resizable Windows</h3>
|
450
|
+
<p style={{ margin: '0 0 15px 0', lineHeight: '1.5' }}>
|
451
|
+
Create windows and try resizing them by dragging the edges and corners.
|
452
|
+
The WindowManager gets notified of size changes when you finish resizing.
|
453
|
+
</p>
|
454
|
+
<div style={{ fontSize: '14px', color: '#666' }}>
|
455
|
+
<p><strong>Resize Features:</strong></p>
|
456
|
+
<ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
|
457
|
+
<li>Drag edges to resize horizontally/vertically</li>
|
458
|
+
<li>Drag corners to resize diagonally</li>
|
459
|
+
<li>Minimum size constraints (200x150)</li>
|
460
|
+
<li>WindowManager updates on resize end</li>
|
461
|
+
<li>Visual feedback with hover effects</li>
|
462
|
+
</ul>
|
463
|
+
</div>
|
464
|
+
</div>
|
465
|
+
</Desktop>
|
466
|
+
</div>
|
467
|
+
)
|
468
|
+
|
469
|
+
/**
|
470
|
+
* Resizable Windows with macOS Theme
|
471
|
+
*/
|
472
|
+
export const ResizableWindowsMacOS = () => (
|
473
|
+
<div style={{ height: '600px', width: '100%', position: 'relative', overflow: 'hidden' }}>
|
474
|
+
<Desktop theme="macos" desktopSize={{ width: 1200, height: 600 }}>
|
475
|
+
<div style={{
|
476
|
+
position: 'absolute',
|
477
|
+
top: '20px',
|
478
|
+
left: '20px',
|
479
|
+
background: 'rgba(255,255,255,0.9)',
|
480
|
+
padding: '20px',
|
481
|
+
borderRadius: '16px',
|
482
|
+
boxShadow: '0 8px 25px rgba(0,0,0,0.15)',
|
483
|
+
maxWidth: '400px',
|
484
|
+
backdropFilter: 'blur(20px)'
|
485
|
+
}}>
|
486
|
+
<h3 style={{ margin: '0 0 15px 0' }}>🍎 macOS Resizable Windows</h3>
|
487
|
+
<p style={{ margin: '0 0 15px 0', lineHeight: '1.5' }}>
|
488
|
+
Experience window resizing with the beautiful macOS theme.
|
489
|
+
Notice the traffic light controls and smooth animations.
|
490
|
+
</p>
|
491
|
+
<div style={{ fontSize: '14px', color: '#666' }}>
|
492
|
+
<p><strong>macOS Features:</strong></p>
|
493
|
+
<ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
|
494
|
+
<li>Traffic light window controls</li>
|
495
|
+
<li>Smooth resize animations</li>
|
496
|
+
<li>macOS-style blur effects</li>
|
497
|
+
<li>SF Pro Display typography</li>
|
498
|
+
</ul>
|
499
|
+
</div>
|
500
|
+
</div>
|
501
|
+
</Desktop>
|
502
|
+
</div>
|
503
|
+
)
|
504
|
+
|
505
|
+
/**
|
506
|
+
* Desktop with ApplicationMenu - Workspace Boundaries Demo
|
432
507
|
*/
|
433
508
|
export const ApplicationMenuAdvanced = () => {
|
434
509
|
// Setup custom apps
|
@@ -44,9 +44,12 @@ export const WindowProvider = ({ children, desktopSize }) => {
|
|
44
44
|
|
45
45
|
// Don't render until WindowManager is initialized
|
46
46
|
if (!state || !windowManagerRef.current) {
|
47
|
+
console.log('WindowProvider not ready - state:', state, 'windowManager:', windowManagerRef.current)
|
47
48
|
return null
|
48
49
|
}
|
49
50
|
|
51
|
+
console.log('WindowProvider ready - providing context')
|
52
|
+
|
50
53
|
const value = {
|
51
54
|
// Current state
|
52
55
|
windows: state.windows,
|