ywana-core8 0.2.5 → 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 +1134 -54
- package/dist/index.js +293 -90
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +293 -90
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +293 -90
- 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 +256 -11
- package/src/desktop/WindowContext.js +4 -0
- package/src/desktop/WindowManager.js +54 -9
- package/src/desktop/desktop-linux.css +287 -0
- package/src/desktop/desktop-macos.css +317 -0
- package/src/desktop/desktop-windows.css +244 -0
- package/src/desktop/desktop.css +30 -0
- package/src/desktop/desktop.js +107 -67
- package/src/desktop/window.css +98 -0
- package/src/desktop/window.js +172 -4
- package/src/html/button.css +5 -0
- package/src/html/button.js +2 -1
@@ -0,0 +1,244 @@
|
|
1
|
+
/* Windows Desktop Theme */
|
2
|
+
|
3
|
+
.desktop--windows {
|
4
|
+
background: linear-gradient(135deg, #0078d4 0%, #106ebe 100%);
|
5
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
6
|
+
}
|
7
|
+
|
8
|
+
.desktop--windows .desktop__background {
|
9
|
+
background-image:
|
10
|
+
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
11
|
+
radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.15) 0%, transparent 50%),
|
12
|
+
radial-gradient(circle at 40% 40%, rgba(120, 119, 198, 0.15) 0%, transparent 50%);
|
13
|
+
}
|
14
|
+
|
15
|
+
/* Windows-style taskbar */
|
16
|
+
.desktop--windows .window {
|
17
|
+
border: 1px solid #cccccc;
|
18
|
+
border-radius: 8px;
|
19
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
20
|
+
background: #ffffff;
|
21
|
+
}
|
22
|
+
|
23
|
+
.desktop--windows .window__header {
|
24
|
+
background: linear-gradient(180deg, #f0f0f0 0%, #e5e5e5 100%);
|
25
|
+
border-bottom: 1px solid #d0d0d0;
|
26
|
+
border-radius: 8px 8px 0 0;
|
27
|
+
height: 32px;
|
28
|
+
padding: 0 12px;
|
29
|
+
}
|
30
|
+
|
31
|
+
.desktop--windows .window__title {
|
32
|
+
font-size: 13px;
|
33
|
+
font-weight: 400;
|
34
|
+
color: #333333;
|
35
|
+
}
|
36
|
+
|
37
|
+
.desktop--windows .window__control {
|
38
|
+
width: 46px;
|
39
|
+
height: 32px;
|
40
|
+
border: none;
|
41
|
+
background: transparent;
|
42
|
+
font-size: 10px;
|
43
|
+
font-family: 'Segoe MDL2 Assets', 'Segoe UI Symbol', sans-serif;
|
44
|
+
color: #333333;
|
45
|
+
display: flex;
|
46
|
+
align-items: center;
|
47
|
+
justify-content: center;
|
48
|
+
transition: background-color 0.1s ease;
|
49
|
+
}
|
50
|
+
|
51
|
+
.desktop--windows .window__control:hover {
|
52
|
+
background: rgba(0, 0, 0, 0.1);
|
53
|
+
}
|
54
|
+
|
55
|
+
.desktop--windows .window__control--minimize:hover {
|
56
|
+
background: #e5e5e5;
|
57
|
+
}
|
58
|
+
|
59
|
+
.desktop--windows .window__control--maximize:hover {
|
60
|
+
background: #e5e5e5;
|
61
|
+
}
|
62
|
+
|
63
|
+
.desktop--windows .window__control--close:hover {
|
64
|
+
background: #e81123;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
.desktop--windows .window__control--minimize::before {
|
69
|
+
content: '🗕';
|
70
|
+
}
|
71
|
+
|
72
|
+
.desktop--windows .window__control--maximize::before {
|
73
|
+
content: '🗖';
|
74
|
+
}
|
75
|
+
|
76
|
+
.desktop--windows .window__control--close::before {
|
77
|
+
content: '🗙';
|
78
|
+
}
|
79
|
+
|
80
|
+
/* Windows taskbar styling */
|
81
|
+
.desktop--windows .desktop-taskbar {
|
82
|
+
background: rgba(0, 0, 0, 0.8);
|
83
|
+
backdrop-filter: blur(20px);
|
84
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
85
|
+
}
|
86
|
+
|
87
|
+
.desktop--windows .taskbar-button {
|
88
|
+
background: rgba(255, 255, 255, 0.1);
|
89
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
90
|
+
border-radius: 4px;
|
91
|
+
color: white;
|
92
|
+
font-family: 'Segoe UI', sans-serif;
|
93
|
+
font-size: 14px;
|
94
|
+
transition: all 0.2s ease;
|
95
|
+
}
|
96
|
+
|
97
|
+
.desktop--windows .taskbar-button:hover {
|
98
|
+
background: rgba(255, 255, 255, 0.2);
|
99
|
+
border-color: rgba(255, 255, 255, 0.3);
|
100
|
+
}
|
101
|
+
|
102
|
+
.desktop--windows .taskbar-button--active {
|
103
|
+
background: rgba(255, 255, 255, 0.25);
|
104
|
+
border-color: rgba(255, 255, 255, 0.4);
|
105
|
+
}
|
106
|
+
|
107
|
+
/* Windows Start Button Styling */
|
108
|
+
.desktop--windows .toggle-button {
|
109
|
+
/* Reset selector styles and apply Windows button styling */
|
110
|
+
position: relative;
|
111
|
+
padding: 8px 16px;
|
112
|
+
display: flex;
|
113
|
+
align-items: center;
|
114
|
+
justify-content: center;
|
115
|
+
gap: 8px;
|
116
|
+
overflow: hidden;
|
117
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
118
|
+
outline: none;
|
119
|
+
transition: all 0.2s ease;
|
120
|
+
color: white;
|
121
|
+
background: linear-gradient(180deg, #0078d4 0%, #106ebe 100%);
|
122
|
+
min-height: 40px;
|
123
|
+
border-radius: 4px;
|
124
|
+
cursor: pointer;
|
125
|
+
font-family: 'Segoe UI', sans-serif;
|
126
|
+
font-weight: 500;
|
127
|
+
text-decoration: none;
|
128
|
+
white-space: nowrap;
|
129
|
+
list-style: none;
|
130
|
+
margin: 0;
|
131
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
132
|
+
}
|
133
|
+
|
134
|
+
.desktop--windows .toggle-button:hover:not(.toggle-button--disabled) {
|
135
|
+
background: linear-gradient(180deg, #106ebe 0%, #005a9e 100%);
|
136
|
+
border-color: rgba(255, 255, 255, 0.3);
|
137
|
+
transform: none;
|
138
|
+
}
|
139
|
+
|
140
|
+
.desktop--windows .toggle-button.selected {
|
141
|
+
background: linear-gradient(180deg, #005a9e 0%, #004578 100%);
|
142
|
+
color: white;
|
143
|
+
border-color: rgba(255, 255, 255, 0.4);
|
144
|
+
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
|
145
|
+
}
|
146
|
+
|
147
|
+
.desktop--windows .toggle-button:focus {
|
148
|
+
outline: 2px solid rgba(255, 255, 255, 0.5);
|
149
|
+
outline-offset: 2px;
|
150
|
+
}
|
151
|
+
|
152
|
+
.desktop--windows .toggle-button--disabled {
|
153
|
+
background: rgba(200, 200, 200, 0.3) !important;
|
154
|
+
color: rgba(100, 100, 100, 0.5) !important;
|
155
|
+
border-color: rgba(255, 255, 255, 0.1) !important;
|
156
|
+
cursor: not-allowed;
|
157
|
+
opacity: 1;
|
158
|
+
box-shadow: none;
|
159
|
+
}
|
160
|
+
|
161
|
+
/* Windows Application Menu */
|
162
|
+
.desktop--windows .application-menu {
|
163
|
+
background: rgba(248, 248, 248, 0.95);
|
164
|
+
backdrop-filter: blur(20px);
|
165
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
166
|
+
border-radius: 8px;
|
167
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
168
|
+
}
|
169
|
+
|
170
|
+
.desktop--windows .application-menu__header {
|
171
|
+
background: linear-gradient(180deg, #f8f8f8 0%, #e8e8e8 100%);
|
172
|
+
border-bottom: 1px solid #d0d0d0;
|
173
|
+
}
|
174
|
+
|
175
|
+
.desktop--windows .application-menu__search-input {
|
176
|
+
border: 2px solid #e0e0e0;
|
177
|
+
border-radius: 4px;
|
178
|
+
font-family: 'Segoe UI', sans-serif;
|
179
|
+
}
|
180
|
+
|
181
|
+
.desktop--windows .application-menu__search-input:focus {
|
182
|
+
border-color: #0078d4;
|
183
|
+
outline: none;
|
184
|
+
}
|
185
|
+
|
186
|
+
.desktop--windows .application-menu__category {
|
187
|
+
background: #ffffff;
|
188
|
+
border: 1px solid #e0e0e0;
|
189
|
+
border-radius: 16px;
|
190
|
+
font-family: 'Segoe UI', sans-serif;
|
191
|
+
font-size: 13px;
|
192
|
+
}
|
193
|
+
|
194
|
+
.desktop--windows .application-menu__category:hover {
|
195
|
+
background: #f5f5f5;
|
196
|
+
border-color: #d0d0d0;
|
197
|
+
}
|
198
|
+
|
199
|
+
.desktop--windows .application-menu__category.active {
|
200
|
+
background: #0078d4;
|
201
|
+
border-color: #0078d4;
|
202
|
+
color: white;
|
203
|
+
}
|
204
|
+
|
205
|
+
.desktop--windows .application-menu__app {
|
206
|
+
background: #ffffff;
|
207
|
+
border: 1px solid transparent;
|
208
|
+
border-radius: 8px;
|
209
|
+
transition: all 0.15s ease;
|
210
|
+
}
|
211
|
+
|
212
|
+
.desktop--windows .application-menu__app:hover {
|
213
|
+
background: #f5f5f5;
|
214
|
+
border-color: #e0e0e0;
|
215
|
+
transform: translateY(-1px);
|
216
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
217
|
+
}
|
218
|
+
|
219
|
+
.desktop--windows .app-name {
|
220
|
+
font-family: 'Segoe UI', sans-serif;
|
221
|
+
font-size: 13px;
|
222
|
+
font-weight: 400;
|
223
|
+
color: #333333;
|
224
|
+
}
|
225
|
+
|
226
|
+
/* Windows scrollbar */
|
227
|
+
.desktop--windows .application-menu__content::-webkit-scrollbar {
|
228
|
+
width: 12px;
|
229
|
+
}
|
230
|
+
|
231
|
+
.desktop--windows .application-menu__content::-webkit-scrollbar-track {
|
232
|
+
background: #f1f1f1;
|
233
|
+
border-radius: 6px;
|
234
|
+
}
|
235
|
+
|
236
|
+
.desktop--windows .application-menu__content::-webkit-scrollbar-thumb {
|
237
|
+
background: #c1c1c1;
|
238
|
+
border-radius: 6px;
|
239
|
+
border: 2px solid #f1f1f1;
|
240
|
+
}
|
241
|
+
|
242
|
+
.desktop--windows .application-menu__content::-webkit-scrollbar-thumb:hover {
|
243
|
+
background: #a8a8a8;
|
244
|
+
}
|
package/src/desktop/desktop.css
CHANGED
@@ -24,8 +24,38 @@
|
|
24
24
|
width: 100%;
|
25
25
|
height: 100%;
|
26
26
|
z-index: 1;
|
27
|
+
display: flex;
|
28
|
+
flex-direction: column;
|
27
29
|
}
|
28
30
|
|
31
|
+
/* Workspace container - takes available space above taskbar */
|
32
|
+
.desktop__workspace-container {
|
33
|
+
position: relative;
|
34
|
+
flex: 1;
|
35
|
+
overflow: hidden;
|
36
|
+
z-index: 1;
|
37
|
+
}
|
38
|
+
|
39
|
+
/* Workspace - container for windows with boundaries */
|
40
|
+
.workspace {
|
41
|
+
position: relative;
|
42
|
+
width: 100%;
|
43
|
+
height: 100%;
|
44
|
+
overflow: hidden;
|
45
|
+
}
|
46
|
+
|
47
|
+
.desktop-taskbar {
|
48
|
+
|
49
|
+
& .icon {
|
50
|
+
color: white;
|
51
|
+
& :hover {
|
52
|
+
color: #fff;
|
53
|
+
background-color: rgba(255, 255, 255, 0.1);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
|
29
59
|
/* Desktop variants */
|
30
60
|
.desktop--dark {
|
31
61
|
color: white;
|
package/src/desktop/desktop.js
CHANGED
@@ -3,7 +3,12 @@ import { WindowProvider, useWindows } from './WindowContext'
|
|
3
3
|
import { Window } from './window'
|
4
4
|
import { ApplicationMenu } from './ApplicationMenu'
|
5
5
|
import { defaultAppManager } from './AppManager'
|
6
|
+
import { ToggleButton } from '../html/selector'
|
7
|
+
import { Icon } from '../html/icon'
|
6
8
|
import './desktop.css'
|
9
|
+
import './desktop-windows.css'
|
10
|
+
import './desktop-linux.css'
|
11
|
+
import './desktop-macos.css'
|
7
12
|
|
8
13
|
/**
|
9
14
|
* Context for Application state
|
@@ -54,17 +59,17 @@ export const AppProvider = ({ children, appManager = defaultAppManager }) => {
|
|
54
59
|
/**
|
55
60
|
* Desktop layout component - manages overall desktop structure and sizing
|
56
61
|
*/
|
57
|
-
const DesktopLayout = ({ children, className = '', ...props }) => {
|
62
|
+
const DesktopLayout = ({ children, className = '', theme = 'windows', workspaceRef, ...props }) => {
|
58
63
|
const desktopRef = useRef(null)
|
59
64
|
const { windowManager } = useWindows()
|
60
65
|
|
61
|
-
// Measure
|
66
|
+
// Measure workspace size on mount and resize
|
62
67
|
useEffect(() => {
|
63
|
-
let currentSize = { width: 1200, height:
|
68
|
+
let currentSize = { width: 1200, height: 750 } // Default workspace size (desktop - taskbar)
|
64
69
|
|
65
|
-
const
|
66
|
-
if (
|
67
|
-
const rect =
|
70
|
+
const measureWorkspace = () => {
|
71
|
+
if (workspaceRef.current) {
|
72
|
+
const rect = workspaceRef.current.getBoundingClientRect()
|
68
73
|
const newSize = {
|
69
74
|
width: rect.width,
|
70
75
|
height: rect.height
|
@@ -79,12 +84,12 @@ const DesktopLayout = ({ children, className = '', ...props }) => {
|
|
79
84
|
}
|
80
85
|
|
81
86
|
// Initial measurement
|
82
|
-
|
87
|
+
measureWorkspace()
|
83
88
|
|
84
89
|
// Listen for resize
|
85
|
-
const resizeObserver = new ResizeObserver(
|
86
|
-
if (
|
87
|
-
resizeObserver.observe(
|
90
|
+
const resizeObserver = new ResizeObserver(measureWorkspace)
|
91
|
+
if (workspaceRef.current) {
|
92
|
+
resizeObserver.observe(workspaceRef.current)
|
88
93
|
}
|
89
94
|
|
90
95
|
return () => {
|
@@ -99,10 +104,13 @@ const DesktopLayout = ({ children, className = '', ...props }) => {
|
|
99
104
|
console.log('Desktop context menu at:', e.clientX, e.clientY)
|
100
105
|
}
|
101
106
|
|
107
|
+
// Generate theme class name
|
108
|
+
const themeClass = `desktop--${theme}`
|
109
|
+
|
102
110
|
return (
|
103
111
|
<div
|
104
112
|
ref={desktopRef}
|
105
|
-
className={`desktop ${className}`}
|
113
|
+
className={`desktop ${themeClass} ${className}`}
|
106
114
|
onContextMenu={handleContextMenu}
|
107
115
|
{...props}
|
108
116
|
>
|
@@ -118,13 +126,13 @@ const DesktopLayout = ({ children, className = '', ...props }) => {
|
|
118
126
|
}
|
119
127
|
|
120
128
|
/**
|
121
|
-
* Workspace -
|
129
|
+
* Workspace - container for windows with proper boundaries
|
122
130
|
*/
|
123
131
|
export const Workspace = ({ children }) => {
|
124
132
|
const { windows } = useWindows()
|
125
133
|
|
126
134
|
return (
|
127
|
-
|
135
|
+
<div className="workspace">
|
128
136
|
{children}
|
129
137
|
|
130
138
|
{/* Render windows using Window component */}
|
@@ -142,7 +150,7 @@ export const Workspace = ({ children }) => {
|
|
142
150
|
</div>
|
143
151
|
</Window>
|
144
152
|
))}
|
145
|
-
|
153
|
+
</div>
|
146
154
|
)
|
147
155
|
}
|
148
156
|
|
@@ -150,6 +158,11 @@ export const Workspace = ({ children }) => {
|
|
150
158
|
* DesktopTaskbar - handles window creation and management
|
151
159
|
*/
|
152
160
|
export const DesktopTaskbar = () => {
|
161
|
+
console.log('DesktopTaskbar render')
|
162
|
+
|
163
|
+
const windowsContext = useWindows()
|
164
|
+
console.log('useWindows result:', windowsContext)
|
165
|
+
|
153
166
|
const {
|
154
167
|
createWindow,
|
155
168
|
windows,
|
@@ -157,12 +170,20 @@ export const DesktopTaskbar = () => {
|
|
157
170
|
activeWindowId,
|
158
171
|
focusWindow,
|
159
172
|
minimizeWindow,
|
160
|
-
closeWindow
|
161
|
-
|
173
|
+
closeWindow,
|
174
|
+
cascadeWindows,
|
175
|
+
tileWindows,
|
176
|
+
centerAllWindows,
|
177
|
+
clearAllWindows
|
178
|
+
} = windowsContext
|
162
179
|
|
163
|
-
const {
|
180
|
+
const { isOpen, toggle } = useApplicationMenu()
|
181
|
+
console.log('DesktopTaskbar - isOpen:', isOpen, 'toggle:', toggle)
|
164
182
|
|
165
183
|
const handleCreateWindow = () => {
|
184
|
+
console.log('handleCreateWindow called!')
|
185
|
+
console.log('createWindow function:', createWindow)
|
186
|
+
|
166
187
|
const windowTypes = [
|
167
188
|
{ title: 'File Explorer', icon: '📁', size: { width: 600, height: 400 } },
|
168
189
|
{ title: 'Text Editor', icon: '📝', size: { width: 500, height: 350 } },
|
@@ -172,6 +193,7 @@ export const DesktopTaskbar = () => {
|
|
172
193
|
]
|
173
194
|
|
174
195
|
const randomType = windowTypes[Math.floor(Math.random() * windowTypes.length)]
|
196
|
+
console.log('Creating window:', randomType)
|
175
197
|
|
176
198
|
createWindow({
|
177
199
|
title: randomType.title,
|
@@ -220,11 +242,7 @@ export const DesktopTaskbar = () => {
|
|
220
242
|
}
|
221
243
|
|
222
244
|
return (
|
223
|
-
<div style={{
|
224
|
-
position: 'absolute',
|
225
|
-
bottom: 0,
|
226
|
-
left: 0,
|
227
|
-
right: 0,
|
245
|
+
<div className='desktop-taskbar' style={{
|
228
246
|
height: '50px',
|
229
247
|
background: 'rgba(0,0,0,0.8)',
|
230
248
|
display: 'flex',
|
@@ -233,45 +251,16 @@ export const DesktopTaskbar = () => {
|
|
233
251
|
gap: '8px'
|
234
252
|
}}>
|
235
253
|
{/* Start button */}
|
236
|
-
<
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
color: 'white',
|
242
|
-
border: 'none',
|
243
|
-
borderRadius: '4px',
|
244
|
-
cursor: 'pointer',
|
245
|
-
fontSize: '14px',
|
246
|
-
fontWeight: 'bold',
|
247
|
-
flexShrink: 0,
|
248
|
-
display: 'flex',
|
249
|
-
alignItems: 'center',
|
250
|
-
gap: '6px'
|
251
|
-
}}
|
252
|
-
title="Open application menu"
|
253
|
-
>
|
254
|
-
<span style={{ fontSize: '16px' }}>🚀</span>
|
255
|
-
Start
|
256
|
-
</button>
|
257
|
-
|
258
|
-
{/* Create window button (for testing) */}
|
259
|
-
<button
|
260
|
-
onClick={handleCreateWindow}
|
261
|
-
style={{
|
262
|
-
padding: '8px 12px',
|
263
|
-
background: '#666',
|
264
|
-
color: 'white',
|
265
|
-
border: 'none',
|
266
|
-
borderRadius: '4px',
|
267
|
-
cursor: 'pointer',
|
268
|
-
fontSize: '12px',
|
269
|
-
flexShrink: 0
|
254
|
+
<ToggleButton
|
255
|
+
checked={isOpen}
|
256
|
+
onToggle={() => {
|
257
|
+
console.log('Start button toggled, current state:', isOpen)
|
258
|
+
toggle()
|
270
259
|
}}
|
271
|
-
|
260
|
+
icon="start"
|
261
|
+
label="Start"
|
272
262
|
>
|
273
|
-
|
274
|
-
</button>
|
263
|
+
</ToggleButton>
|
275
264
|
|
276
265
|
{/* Separator */}
|
277
266
|
<div style={{
|
@@ -350,6 +339,49 @@ export const DesktopTaskbar = () => {
|
|
350
339
|
))}
|
351
340
|
</div>
|
352
341
|
|
342
|
+
{/* Window Layout Controls */}
|
343
|
+
<div style={{
|
344
|
+
display: 'flex',
|
345
|
+
gap: '4px',
|
346
|
+
alignItems: 'center',
|
347
|
+
marginLeft: 'auto',
|
348
|
+
marginRight: '8px'
|
349
|
+
}}>
|
350
|
+
|
351
|
+
<Icon clickable size="small"
|
352
|
+
action={() => {
|
353
|
+
console.log('Cascade windows clicked!')
|
354
|
+
cascadeWindows()
|
355
|
+
}}
|
356
|
+
icon="view_stream"
|
357
|
+
label="Cascade"
|
358
|
+
/>
|
359
|
+
<Icon clickable size="small"
|
360
|
+
action={() => {
|
361
|
+
console.log('Tile windows clicked!')
|
362
|
+
tileWindows()
|
363
|
+
}}
|
364
|
+
icon="view_module"
|
365
|
+
label="Tile"
|
366
|
+
/>
|
367
|
+
<Icon clickable size="small"
|
368
|
+
action={() => {
|
369
|
+
console.log('Center all windows clicked!')
|
370
|
+
centerAllWindows()
|
371
|
+
}}
|
372
|
+
icon="center_focus_strong"
|
373
|
+
label="Center"
|
374
|
+
/>
|
375
|
+
<Icon clickable size="small"
|
376
|
+
action={() => {
|
377
|
+
console.log('Clear all windows clicked!')
|
378
|
+
clearAllWindows()
|
379
|
+
}}
|
380
|
+
icon="clear_all"
|
381
|
+
label="Clear"
|
382
|
+
/>
|
383
|
+
</div>
|
384
|
+
|
353
385
|
{/* Debug info */}
|
354
386
|
<div style={{
|
355
387
|
color: 'rgba(255,255,255,0.7)',
|
@@ -369,18 +401,26 @@ export const DesktopTaskbar = () => {
|
|
369
401
|
*/
|
370
402
|
const DesktopInternal = ({ desktopSize, children, ...props }) => {
|
371
403
|
const { isOpen, close } = useApplicationMenu()
|
404
|
+
const workspaceRef = useRef(null)
|
372
405
|
|
373
406
|
return (
|
374
407
|
<WindowProvider desktopSize={desktopSize}>
|
375
|
-
<DesktopLayout {...props}>
|
376
|
-
|
377
|
-
|
378
|
-
|
408
|
+
<DesktopLayout workspaceRef={workspaceRef} {...props}>
|
409
|
+
{/* Workspace container - has its own boundaries */}
|
410
|
+
<div ref={workspaceRef} className="desktop__workspace-container">
|
411
|
+
<Workspace>
|
412
|
+
{children}
|
413
|
+
</Workspace>
|
414
|
+
|
415
|
+
{/* ApplicationMenu positioned over workspace */}
|
416
|
+
<ApplicationMenu
|
417
|
+
isOpen={isOpen}
|
418
|
+
onClose={close}
|
419
|
+
/>
|
420
|
+
</div>
|
421
|
+
|
422
|
+
{/* Taskbar at bottom - separate from workspace */}
|
379
423
|
<DesktopTaskbar />
|
380
|
-
<ApplicationMenu
|
381
|
-
isOpen={isOpen}
|
382
|
-
onClose={close}
|
383
|
-
/>
|
384
424
|
</DesktopLayout>
|
385
425
|
</WindowProvider>
|
386
426
|
)
|
package/src/desktop/window.css
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
11
11
|
overflow: hidden;
|
12
12
|
user-select: none;
|
13
|
+
pointer-events: auto; /* Ensure windows are clickable */
|
13
14
|
}
|
14
15
|
|
15
16
|
.window:focus-within {
|
@@ -249,3 +250,100 @@
|
|
249
250
|
.window--dragging * {
|
250
251
|
user-select: none !important;
|
251
252
|
}
|
253
|
+
|
254
|
+
/* Window Resize Handles */
|
255
|
+
.window__resize-handle {
|
256
|
+
position: absolute;
|
257
|
+
background: transparent;
|
258
|
+
z-index: 10;
|
259
|
+
}
|
260
|
+
|
261
|
+
/* Edge handles */
|
262
|
+
.window__resize-handle--n {
|
263
|
+
top: -3px;
|
264
|
+
left: 8px;
|
265
|
+
right: 8px;
|
266
|
+
height: 6px;
|
267
|
+
cursor: n-resize;
|
268
|
+
}
|
269
|
+
|
270
|
+
.window__resize-handle--s {
|
271
|
+
bottom: -3px;
|
272
|
+
left: 8px;
|
273
|
+
right: 8px;
|
274
|
+
height: 6px;
|
275
|
+
cursor: s-resize;
|
276
|
+
}
|
277
|
+
|
278
|
+
.window__resize-handle--e {
|
279
|
+
top: 8px;
|
280
|
+
bottom: 8px;
|
281
|
+
right: -3px;
|
282
|
+
width: 6px;
|
283
|
+
cursor: e-resize;
|
284
|
+
}
|
285
|
+
|
286
|
+
.window__resize-handle--w {
|
287
|
+
top: 8px;
|
288
|
+
bottom: 8px;
|
289
|
+
left: -3px;
|
290
|
+
width: 6px;
|
291
|
+
cursor: w-resize;
|
292
|
+
}
|
293
|
+
|
294
|
+
/* Corner handles */
|
295
|
+
.window__resize-handle--ne {
|
296
|
+
top: -3px;
|
297
|
+
right: -3px;
|
298
|
+
width: 12px;
|
299
|
+
height: 12px;
|
300
|
+
cursor: ne-resize;
|
301
|
+
}
|
302
|
+
|
303
|
+
.window__resize-handle--nw {
|
304
|
+
top: -3px;
|
305
|
+
left: -3px;
|
306
|
+
width: 12px;
|
307
|
+
height: 12px;
|
308
|
+
cursor: nw-resize;
|
309
|
+
}
|
310
|
+
|
311
|
+
.window__resize-handle--se {
|
312
|
+
bottom: -3px;
|
313
|
+
right: -3px;
|
314
|
+
width: 12px;
|
315
|
+
height: 12px;
|
316
|
+
cursor: se-resize;
|
317
|
+
}
|
318
|
+
|
319
|
+
.window__resize-handle--sw {
|
320
|
+
bottom: -3px;
|
321
|
+
left: -3px;
|
322
|
+
width: 12px;
|
323
|
+
height: 12px;
|
324
|
+
cursor: sw-resize;
|
325
|
+
}
|
326
|
+
|
327
|
+
/* Resize handle hover effects */
|
328
|
+
.window__resize-handle:hover {
|
329
|
+
background: rgba(25, 118, 210, 0.2);
|
330
|
+
}
|
331
|
+
|
332
|
+
/* Window resizing state */
|
333
|
+
.window--resizing {
|
334
|
+
pointer-events: none;
|
335
|
+
}
|
336
|
+
|
337
|
+
.window--resizing * {
|
338
|
+
pointer-events: none !important;
|
339
|
+
}
|
340
|
+
|
341
|
+
/* Allow resize handles to work during resize */
|
342
|
+
.window--resizing .window__resize-handle {
|
343
|
+
pointer-events: auto !important;
|
344
|
+
}
|
345
|
+
|
346
|
+
/* Disable text selection during resize */
|
347
|
+
.window--resizing * {
|
348
|
+
user-select: none !important;
|
349
|
+
}
|