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/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
|
+
}
|
package/src/desktop/window.js
CHANGED
@@ -130,14 +130,119 @@ export const Window = ({
|
|
130
130
|
updateWindowPosition(id, finalPosition)
|
131
131
|
}
|
132
132
|
|
133
|
-
//
|
133
|
+
// Handle resize start
|
134
|
+
const handleResizeStart = (e, direction) => {
|
135
|
+
if (!resizable || maximized) return
|
136
|
+
|
137
|
+
e.preventDefault()
|
138
|
+
e.stopPropagation()
|
139
|
+
|
140
|
+
setIsResizing(true)
|
141
|
+
setResizeDirection(direction)
|
142
|
+
setResizeStartSize(size)
|
143
|
+
setResizeStartPosition(position)
|
144
|
+
setResizeStartMouse({ x: e.clientX, y: e.clientY })
|
145
|
+
|
146
|
+
// Focus window
|
147
|
+
focusWindow(id)
|
148
|
+
}
|
149
|
+
|
150
|
+
// Handle resize move
|
151
|
+
const handleResizeMove = (e) => {
|
152
|
+
if (!isResizing) return
|
153
|
+
|
154
|
+
e.preventDefault()
|
155
|
+
|
156
|
+
const deltaX = e.clientX - resizeStartMouse.x
|
157
|
+
const deltaY = e.clientY - resizeStartMouse.y
|
158
|
+
|
159
|
+
let newSize = { ...resizeStartSize }
|
160
|
+
let newPosition = { ...resizeStartPosition }
|
161
|
+
|
162
|
+
// Calculate new size and position based on resize direction
|
163
|
+
switch (resizeDirection) {
|
164
|
+
case 'n': // North
|
165
|
+
newSize.height = Math.max(150, resizeStartSize.height - deltaY)
|
166
|
+
newPosition.y = resizeStartPosition.y + (resizeStartSize.height - newSize.height)
|
167
|
+
break
|
168
|
+
case 's': // South
|
169
|
+
newSize.height = Math.max(150, resizeStartSize.height + deltaY)
|
170
|
+
break
|
171
|
+
case 'e': // East
|
172
|
+
newSize.width = Math.max(200, resizeStartSize.width + deltaX)
|
173
|
+
break
|
174
|
+
case 'w': // West
|
175
|
+
newSize.width = Math.max(200, resizeStartSize.width - deltaX)
|
176
|
+
newPosition.x = resizeStartPosition.x + (resizeStartSize.width - newSize.width)
|
177
|
+
break
|
178
|
+
case 'ne': // Northeast
|
179
|
+
newSize.width = Math.max(200, resizeStartSize.width + deltaX)
|
180
|
+
newSize.height = Math.max(150, resizeStartSize.height - deltaY)
|
181
|
+
newPosition.y = resizeStartPosition.y + (resizeStartSize.height - newSize.height)
|
182
|
+
break
|
183
|
+
case 'nw': // Northwest
|
184
|
+
newSize.width = Math.max(200, resizeStartSize.width - deltaX)
|
185
|
+
newSize.height = Math.max(150, resizeStartSize.height - deltaY)
|
186
|
+
newPosition.x = resizeStartPosition.x + (resizeStartSize.width - newSize.width)
|
187
|
+
newPosition.y = resizeStartPosition.y + (resizeStartSize.height - newSize.height)
|
188
|
+
break
|
189
|
+
case 'se': // Southeast
|
190
|
+
newSize.width = Math.max(200, resizeStartSize.width + deltaX)
|
191
|
+
newSize.height = Math.max(150, resizeStartSize.height + deltaY)
|
192
|
+
break
|
193
|
+
case 'sw': // Southwest
|
194
|
+
newSize.width = Math.max(200, resizeStartSize.width - deltaX)
|
195
|
+
newSize.height = Math.max(150, resizeStartSize.height + deltaY)
|
196
|
+
newPosition.x = resizeStartPosition.x + (resizeStartSize.width - newSize.width)
|
197
|
+
break
|
198
|
+
}
|
199
|
+
|
200
|
+
// Apply changes visually
|
201
|
+
if (windowRef.current) {
|
202
|
+
windowRef.current.style.width = `${newSize.width}px`
|
203
|
+
windowRef.current.style.height = `${newSize.height}px`
|
204
|
+
windowRef.current.style.left = `${newPosition.x}px`
|
205
|
+
windowRef.current.style.top = `${newPosition.y}px`
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
// Handle resize end
|
210
|
+
const handleResizeEnd = () => {
|
211
|
+
if (!isResizing) return
|
212
|
+
|
213
|
+
setIsResizing(false)
|
214
|
+
setResizeDirection('')
|
215
|
+
|
216
|
+
// Get final size and position
|
217
|
+
const desktopContainer = windowRef.current?.parentElement
|
218
|
+
if (!desktopContainer) return
|
219
|
+
|
220
|
+
const windowRect = windowRef.current.getBoundingClientRect()
|
221
|
+
const desktopRect = desktopContainer.getBoundingClientRect()
|
222
|
+
|
223
|
+
const finalSize = {
|
224
|
+
width: windowRect.width,
|
225
|
+
height: windowRect.height
|
226
|
+
}
|
227
|
+
|
228
|
+
const finalPosition = {
|
229
|
+
x: windowRect.left - desktopRect.left,
|
230
|
+
y: windowRect.top - desktopRect.top
|
231
|
+
}
|
232
|
+
|
233
|
+
// Update WindowManager
|
234
|
+
updateWindowSize(id, finalSize)
|
235
|
+
updateWindowPosition(id, finalPosition)
|
236
|
+
}
|
237
|
+
|
238
|
+
// Setup drag and resize event listeners
|
134
239
|
useEffect(() => {
|
135
240
|
if (isDragging) {
|
136
241
|
document.addEventListener('mousemove', handleMouseMove)
|
137
242
|
document.addEventListener('mouseup', handleMouseUp)
|
138
243
|
document.body.style.userSelect = 'none'
|
139
244
|
document.body.style.cursor = 'move'
|
140
|
-
|
245
|
+
|
141
246
|
return () => {
|
142
247
|
document.removeEventListener('mousemove', handleMouseMove)
|
143
248
|
document.removeEventListener('mouseup', handleMouseUp)
|
@@ -147,6 +252,20 @@ export const Window = ({
|
|
147
252
|
}
|
148
253
|
}, [isDragging])
|
149
254
|
|
255
|
+
useEffect(() => {
|
256
|
+
if (isResizing) {
|
257
|
+
document.addEventListener('mousemove', handleResizeMove)
|
258
|
+
document.addEventListener('mouseup', handleResizeEnd)
|
259
|
+
document.body.style.userSelect = 'none'
|
260
|
+
|
261
|
+
return () => {
|
262
|
+
document.removeEventListener('mousemove', handleResizeMove)
|
263
|
+
document.removeEventListener('mouseup', handleResizeEnd)
|
264
|
+
document.body.style.userSelect = ''
|
265
|
+
}
|
266
|
+
}
|
267
|
+
}, [isResizing])
|
268
|
+
|
150
269
|
// Window control handlers
|
151
270
|
const handleMinimize = (e) => {
|
152
271
|
e.stopPropagation()
|
@@ -189,6 +308,7 @@ export const Window = ({
|
|
189
308
|
'window',
|
190
309
|
maximized && 'window--maximized',
|
191
310
|
isDragging && 'window--dragging',
|
311
|
+
isResizing && 'window--resizing',
|
192
312
|
className
|
193
313
|
].filter(Boolean).join(' ')
|
194
314
|
|
@@ -264,6 +384,47 @@ export const Window = ({
|
|
264
384
|
{statusBar}
|
265
385
|
</div>
|
266
386
|
)}
|
387
|
+
|
388
|
+
{/* Resize Handles */}
|
389
|
+
{resizable && !maximized && (
|
390
|
+
<>
|
391
|
+
{/* Edge handles */}
|
392
|
+
<div
|
393
|
+
className="window__resize-handle window__resize-handle--n"
|
394
|
+
onMouseDown={(e) => handleResizeStart(e, 'n')}
|
395
|
+
/>
|
396
|
+
<div
|
397
|
+
className="window__resize-handle window__resize-handle--s"
|
398
|
+
onMouseDown={(e) => handleResizeStart(e, 's')}
|
399
|
+
/>
|
400
|
+
<div
|
401
|
+
className="window__resize-handle window__resize-handle--e"
|
402
|
+
onMouseDown={(e) => handleResizeStart(e, 'e')}
|
403
|
+
/>
|
404
|
+
<div
|
405
|
+
className="window__resize-handle window__resize-handle--w"
|
406
|
+
onMouseDown={(e) => handleResizeStart(e, 'w')}
|
407
|
+
/>
|
408
|
+
|
409
|
+
{/* Corner handles */}
|
410
|
+
<div
|
411
|
+
className="window__resize-handle window__resize-handle--ne"
|
412
|
+
onMouseDown={(e) => handleResizeStart(e, 'ne')}
|
413
|
+
/>
|
414
|
+
<div
|
415
|
+
className="window__resize-handle window__resize-handle--nw"
|
416
|
+
onMouseDown={(e) => handleResizeStart(e, 'nw')}
|
417
|
+
/>
|
418
|
+
<div
|
419
|
+
className="window__resize-handle window__resize-handle--se"
|
420
|
+
onMouseDown={(e) => handleResizeStart(e, 'se')}
|
421
|
+
/>
|
422
|
+
<div
|
423
|
+
className="window__resize-handle window__resize-handle--sw"
|
424
|
+
onMouseDown={(e) => handleResizeStart(e, 'sw')}
|
425
|
+
/>
|
426
|
+
</>
|
427
|
+
)}
|
267
428
|
</div>
|
268
429
|
)
|
269
430
|
}
|
package/src/html/button.css
CHANGED
package/src/html/button.js
CHANGED
@@ -111,7 +111,8 @@ export const Button = (props) => {
|
|
111
111
|
icon: loading ? 'hourglass_empty' : icon,
|
112
112
|
size: size === 'small' ? 'small' : size === 'large' ? 'normal' : 'small',
|
113
113
|
disabled: disabled || loading,
|
114
|
-
className: loading ? 'loading-icon' : ''
|
114
|
+
className: loading ? 'loading-icon' : '',
|
115
|
+
eventPropagation: true, // Allow click events to bubble up to button
|
115
116
|
}
|
116
117
|
|
117
118
|
return (
|