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.
@@ -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
+ }
@@ -130,14 +130,119 @@ export const Window = ({
130
130
  updateWindowPosition(id, finalPosition)
131
131
  }
132
132
 
133
- // Setup drag event listeners
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
  }
@@ -20,6 +20,11 @@
20
20
  white-space: nowrap;
21
21
  }
22
22
 
23
+ /* Ensure icons inside buttons don't block clicks */
24
+ .btn .icon {
25
+ pointer-events: none;
26
+ }
27
+
23
28
  .btn.outlined {
24
29
  color: var(--primary-color);
25
30
  border: solid 1px var(--primary-color);
@@ -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 (