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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ywana-core8",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "ywana-core8",
5
5
  "homepage": "https://ywana.github.io/workspace",
6
6
  "author": "Ernesto Roldan Garcia",
@@ -1,18 +1,19 @@
1
- /* ApplicationMenu - Full-screen overlay styles */
1
+ /* ApplicationMenu - Positioned over workspace only */
2
2
 
3
3
  .application-menu-overlay {
4
- position: fixed;
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: 900px;
33
- height: 80%;
34
- max-height: 700px;
35
- display: flex;
36
- flex-direction: column;
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
- display: flex;
108
- gap: 8px;
109
- padding: 16px 24px;
110
- border-bottom: 1px solid #e0e0e0;
111
- background: #f8f9fa;
112
- overflow-x: auto;
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: 8px;
119
- padding: 8px 16px;
120
- background: #ffffff;
121
- border: 1px solid #e0e0e0;
122
- border-radius: 20px;
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
- white-space: nowrap;
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: #f0f0f0;
132
- border-color: #ccc;
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: 16px;
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
- flex: 1;
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(120px, 1fr));
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: 90%;
232
- margin: 20px;
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(100px, 1fr));
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: 40px;
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
- /* Scrollbar styling */
263
- .application-menu__content::-webkit-scrollbar {
264
- width: 8px;
265
- }
345
+ @media (max-width: 480px) {
346
+ /* ApplicationMenu overlay covers entire workspace on mobile */
266
347
 
267
- .application-menu__content::-webkit-scrollbar-track {
268
- background: #f1f1f1;
269
- border-radius: 4px;
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-menu__content::-webkit-scrollbar-thumb {
273
- background: #c1c1c1;
274
- border-radius: 4px;
275
- }
356
+ .application-menu__sidebar {
357
+ border-right: none;
358
+ border-bottom: 1px solid #e0e0e0;
359
+ }
276
360
 
277
- .application-menu__content::-webkit-scrollbar-thumb:hover {
278
- background: #a8a8a8;
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
- {/* Categories */}
137
- <div className="application-menu__categories">
138
- <button
139
- className={`application-menu__category ${selectedCategory === 'all' ? 'active' : ''}`}
140
- onClick={() => handleCategorySelect('all')}
141
- >
142
- <span className="category-icon">📱</span>
143
- All Apps
144
- </button>
145
- {categories.map(category => (
146
- <button
147
- key={category.id}
148
- className={`application-menu__category ${selectedCategory === category.id ? 'active' : ''}`}
149
- onClick={() => handleCategorySelect(category.id)}
150
- >
151
- <span className="category-icon">{category.icon}</span>
152
- {category.name}
153
- </button>
154
- ))}
155
- </div>
156
-
157
- {/* Applications Grid */}
158
- <div className="application-menu__content">
159
- {searchTerm && (
160
- <div className="application-menu__search-results">
161
- <h3>Search Results ({filteredApps.length})</h3>
162
- <div className="application-menu__apps-grid">
163
- {filteredApps.map(app => (
164
- <div
165
- key={app.id}
166
- className="application-menu__app"
167
- onClick={() => handleLaunchApp(app)}
168
- title={app.description}
169
- >
170
- <div className="app-icon">{app.icon}</div>
171
- <div className="app-name">{app.name}</div>
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
- </div>
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
- {filteredApps.length === 0 && (
202
- <div className="application-menu__no-results">
203
- <div style={{ fontSize: '48px', marginBottom: '16px' }}>🔍</div>
204
- <h3>No applications found</h3>
205
- <p>Try adjusting your search or category filter.</p>
206
- </div>
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' }}>🚀 Application Menu Demo</h3>
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 the <strong>"Start"</strong> button in the taskbar to open the Application Menu.
244
- Browse applications by category and launch them to create windows.
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>Features:</strong></p>
248
+ <p><strong>New Architecture:</strong></p>
248
249
  <ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
249
- <li>Browse apps by category</li>
250
- <li>Search functionality</li>
251
- <li>Launch applications as windows</li>
252
- <li>Full-screen overlay menu</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
- * Desktop with ApplicationMenu - Advanced with controls
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,