ywana-core8 0.2.16 → 0.2.18
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 +231 -0
- package/dist/index.js +218 -2
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +218 -2
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +218 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/desktop/Desktop.stories.jsx +522 -14
- package/src/desktop/window.css +231 -0
- package/src/desktop/window.js +341 -8
package/dist/index.css
CHANGED
@@ -15876,6 +15876,7 @@ li.selected,
|
|
15876
15876
|
overflow: hidden;
|
15877
15877
|
user-select: none;
|
15878
15878
|
pointer-events: auto; /* Ensure windows are clickable */
|
15879
|
+
position: relative; /* For floating elements positioning */
|
15879
15880
|
}
|
15880
15881
|
|
15881
15882
|
.window:focus-within {
|
@@ -16121,6 +16122,236 @@ li.selected,
|
|
16121
16122
|
user-select: none !important;
|
16122
16123
|
}
|
16123
16124
|
|
16125
|
+
/* Window Instance Context - Floating Elements */
|
16126
|
+
.window-floating-elements {
|
16127
|
+
position: absolute;
|
16128
|
+
top: 0;
|
16129
|
+
left: 0;
|
16130
|
+
right: 0;
|
16131
|
+
bottom: 0;
|
16132
|
+
pointer-events: none;
|
16133
|
+
z-index: 1000;
|
16134
|
+
}
|
16135
|
+
|
16136
|
+
/* Dialog Styles */
|
16137
|
+
.window-dialog {
|
16138
|
+
position: absolute;
|
16139
|
+
top: 0;
|
16140
|
+
left: 0;
|
16141
|
+
right: 0;
|
16142
|
+
bottom: 0;
|
16143
|
+
background: rgba(0, 0, 0, 0.3);
|
16144
|
+
display: flex;
|
16145
|
+
align-items: center;
|
16146
|
+
justify-content: center;
|
16147
|
+
pointer-events: auto;
|
16148
|
+
z-index: 1002;
|
16149
|
+
}
|
16150
|
+
|
16151
|
+
.window-dialog__content {
|
16152
|
+
background: white;
|
16153
|
+
border-radius: 8px;
|
16154
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
16155
|
+
min-width: 300px;
|
16156
|
+
max-width: 80%;
|
16157
|
+
max-height: 80%;
|
16158
|
+
overflow: hidden;
|
16159
|
+
display: flex;
|
16160
|
+
flex-direction: column;
|
16161
|
+
}
|
16162
|
+
|
16163
|
+
.window-dialog__header {
|
16164
|
+
padding: 16px 20px;
|
16165
|
+
border-bottom: 1px solid #e0e0e0;
|
16166
|
+
display: flex;
|
16167
|
+
align-items: center;
|
16168
|
+
justify-content: space-between;
|
16169
|
+
background: #f8f9fa;
|
16170
|
+
}
|
16171
|
+
|
16172
|
+
.window-dialog__title {
|
16173
|
+
margin: 0;
|
16174
|
+
font-size: 16px;
|
16175
|
+
font-weight: 600;
|
16176
|
+
color: #333;
|
16177
|
+
}
|
16178
|
+
|
16179
|
+
.window-dialog__close {
|
16180
|
+
background: none;
|
16181
|
+
border: none;
|
16182
|
+
font-size: 18px;
|
16183
|
+
cursor: pointer;
|
16184
|
+
color: #666;
|
16185
|
+
width: 24px;
|
16186
|
+
height: 24px;
|
16187
|
+
display: flex;
|
16188
|
+
align-items: center;
|
16189
|
+
justify-content: center;
|
16190
|
+
border-radius: 4px;
|
16191
|
+
}
|
16192
|
+
|
16193
|
+
.window-dialog__close:hover {
|
16194
|
+
background: rgba(0, 0, 0, 0.1);
|
16195
|
+
color: #333;
|
16196
|
+
}
|
16197
|
+
|
16198
|
+
.window-dialog__body {
|
16199
|
+
padding: 20px;
|
16200
|
+
flex: 1;
|
16201
|
+
overflow: auto;
|
16202
|
+
}
|
16203
|
+
|
16204
|
+
.window-dialog__footer {
|
16205
|
+
padding: 16px 20px;
|
16206
|
+
border-top: 1px solid #e0e0e0;
|
16207
|
+
display: flex;
|
16208
|
+
gap: 8px;
|
16209
|
+
justify-content: flex-end;
|
16210
|
+
background: #f8f9fa;
|
16211
|
+
}
|
16212
|
+
|
16213
|
+
/* Notification Styles */
|
16214
|
+
.window-notification {
|
16215
|
+
position: absolute;
|
16216
|
+
top: 16px;
|
16217
|
+
right: 16px;
|
16218
|
+
background: white;
|
16219
|
+
border-radius: 8px;
|
16220
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
16221
|
+
padding: 12px 16px;
|
16222
|
+
display: flex;
|
16223
|
+
align-items: flex-start;
|
16224
|
+
gap: 12px;
|
16225
|
+
max-width: 300px;
|
16226
|
+
pointer-events: auto;
|
16227
|
+
z-index: 1003;
|
16228
|
+
border-left: 4px solid #007bff;
|
16229
|
+
animation: slideInRight 0.3s ease-out;
|
16230
|
+
}
|
16231
|
+
|
16232
|
+
.window-notification--success { border-left-color: #28a745; }
|
16233
|
+
.window-notification--warning { border-left-color: #ffc107; }
|
16234
|
+
.window-notification--error { border-left-color: #dc3545; }
|
16235
|
+
.window-notification--info { border-left-color: #17a2b8; }
|
16236
|
+
|
16237
|
+
.window-notification__content {
|
16238
|
+
flex: 1;
|
16239
|
+
min-width: 0;
|
16240
|
+
}
|
16241
|
+
|
16242
|
+
.window-notification__title {
|
16243
|
+
font-weight: 600;
|
16244
|
+
font-size: 14px;
|
16245
|
+
margin-bottom: 4px;
|
16246
|
+
color: #333;
|
16247
|
+
}
|
16248
|
+
|
16249
|
+
.window-notification__message {
|
16250
|
+
font-size: 13px;
|
16251
|
+
color: #666;
|
16252
|
+
line-height: 1.4;
|
16253
|
+
}
|
16254
|
+
|
16255
|
+
.window-notification__close {
|
16256
|
+
background: none;
|
16257
|
+
border: none;
|
16258
|
+
font-size: 16px;
|
16259
|
+
cursor: pointer;
|
16260
|
+
color: #999;
|
16261
|
+
width: 20px;
|
16262
|
+
height: 20px;
|
16263
|
+
display: flex;
|
16264
|
+
align-items: center;
|
16265
|
+
justify-content: center;
|
16266
|
+
border-radius: 4px;
|
16267
|
+
flex-shrink: 0;
|
16268
|
+
}
|
16269
|
+
|
16270
|
+
.window-notification__close:hover {
|
16271
|
+
background: rgba(0, 0, 0, 0.1);
|
16272
|
+
color: #666;
|
16273
|
+
}
|
16274
|
+
|
16275
|
+
/* Tooltip Styles */
|
16276
|
+
.window-tooltip {
|
16277
|
+
position: absolute;
|
16278
|
+
background: rgba(0, 0, 0, 0.8);
|
16279
|
+
color: white;
|
16280
|
+
border-radius: 6px;
|
16281
|
+
padding: 8px 12px;
|
16282
|
+
font-size: 12px;
|
16283
|
+
max-width: 200px;
|
16284
|
+
pointer-events: auto;
|
16285
|
+
z-index: 1005;
|
16286
|
+
animation: fadeIn 0.15s ease-out;
|
16287
|
+
}
|
16288
|
+
|
16289
|
+
/* Context Menu Styles */
|
16290
|
+
.window-context-menu {
|
16291
|
+
position: absolute;
|
16292
|
+
background: white;
|
16293
|
+
border-radius: 6px;
|
16294
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
16295
|
+
border: 1px solid #e0e0e0;
|
16296
|
+
padding: 4px 0;
|
16297
|
+
min-width: 150px;
|
16298
|
+
pointer-events: auto;
|
16299
|
+
z-index: 1004;
|
16300
|
+
animation: fadeIn 0.1s ease-out;
|
16301
|
+
}
|
16302
|
+
|
16303
|
+
.window-context-menu__item {
|
16304
|
+
padding: 8px 12px;
|
16305
|
+
display: flex;
|
16306
|
+
align-items: center;
|
16307
|
+
gap: 8px;
|
16308
|
+
cursor: pointer;
|
16309
|
+
font-size: 13px;
|
16310
|
+
color: #333;
|
16311
|
+
transition: background-color 0.15s ease;
|
16312
|
+
}
|
16313
|
+
|
16314
|
+
.window-context-menu__item:hover {
|
16315
|
+
background: #f8f9fa;
|
16316
|
+
}
|
16317
|
+
|
16318
|
+
/* Overlay Styles */
|
16319
|
+
.window-overlay {
|
16320
|
+
position: absolute;
|
16321
|
+
top: 0;
|
16322
|
+
left: 0;
|
16323
|
+
right: 0;
|
16324
|
+
bottom: 0;
|
16325
|
+
background: rgba(0, 0, 0, 0.5);
|
16326
|
+
display: flex;
|
16327
|
+
align-items: center;
|
16328
|
+
justify-content: center;
|
16329
|
+
pointer-events: auto;
|
16330
|
+
z-index: 1001;
|
16331
|
+
animation: fadeIn 0.2s ease-out;
|
16332
|
+
}
|
16333
|
+
|
16334
|
+
.window-overlay__content {
|
16335
|
+
background: white;
|
16336
|
+
border-radius: 8px;
|
16337
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
16338
|
+
max-width: 90%;
|
16339
|
+
max-height: 90%;
|
16340
|
+
overflow: auto;
|
16341
|
+
position: relative;
|
16342
|
+
}
|
16343
|
+
|
16344
|
+
/* Animations */
|
16345
|
+
@keyframes slideInRight {
|
16346
|
+
from { transform: translateX(100%); opacity: 0; }
|
16347
|
+
to { transform: translateX(0); opacity: 1; }
|
16348
|
+
}
|
16349
|
+
|
16350
|
+
@keyframes fadeIn {
|
16351
|
+
from { opacity: 0; }
|
16352
|
+
to { opacity: 1; }
|
16353
|
+
}
|
16354
|
+
|
16124
16355
|
/* Window Resize Handles */
|
16125
16356
|
.window__resize-handle {
|
16126
16357
|
position: absolute;
|
package/dist/index.js
CHANGED
@@ -32420,7 +32420,7 @@ const Window = ({
|
|
32420
32420
|
isResizing && "window--resizing",
|
32421
32421
|
className
|
32422
32422
|
].filter(Boolean).join(" ");
|
32423
|
-
return /* @__PURE__ */ React.createElement(
|
32423
|
+
return /* @__PURE__ */ React.createElement(WindowInstanceProvider, { windowId: id }, /* @__PURE__ */ React.createElement(
|
32424
32424
|
"div",
|
32425
32425
|
{
|
32426
32426
|
ref: windowRef,
|
@@ -32516,8 +32516,224 @@ const Window = ({
|
|
32516
32516
|
className: "window__resize-handle window__resize-handle--sw",
|
32517
32517
|
onMouseDown: (e) => handleResizeStart(e, "sw")
|
32518
32518
|
}
|
32519
|
+
)),
|
32520
|
+
/* @__PURE__ */ React.createElement(FloatingElementsRenderer, null)
|
32521
|
+
));
|
32522
|
+
};
|
32523
|
+
const WindowInstanceContext = React.createContext(null);
|
32524
|
+
const WindowInstanceProvider = ({ windowId, children }) => {
|
32525
|
+
const [dialogs, setDialogs] = React.useState([]);
|
32526
|
+
const [notifications, setNotifications] = React.useState([]);
|
32527
|
+
const [tooltips, setTooltips] = React.useState([]);
|
32528
|
+
const [contextMenus, setContextMenus] = React.useState([]);
|
32529
|
+
const [overlays, setOverlays] = React.useState([]);
|
32530
|
+
const idCounterRef = React.useRef(0);
|
32531
|
+
const generateId = React.useCallback(() => {
|
32532
|
+
return `${windowId}-element-${++idCounterRef.current}`;
|
32533
|
+
}, [windowId]);
|
32534
|
+
const showDialog = React.useCallback((config) => {
|
32535
|
+
const id = generateId();
|
32536
|
+
const dialog = {
|
32537
|
+
id,
|
32538
|
+
type: "dialog",
|
32539
|
+
...config,
|
32540
|
+
createdAt: Date.now(),
|
32541
|
+
onClose: () => hideDialog(id)
|
32542
|
+
};
|
32543
|
+
setDialogs((prev) => [...prev, dialog]);
|
32544
|
+
return id;
|
32545
|
+
}, [generateId]);
|
32546
|
+
const hideDialog = React.useCallback((id) => {
|
32547
|
+
setDialogs((prev) => prev.filter((dialog) => dialog.id !== id));
|
32548
|
+
}, []);
|
32549
|
+
const hideAllDialogs = React.useCallback(() => {
|
32550
|
+
setDialogs([]);
|
32551
|
+
}, []);
|
32552
|
+
const showNotification = React.useCallback((config) => {
|
32553
|
+
const id = generateId();
|
32554
|
+
const notification = {
|
32555
|
+
id,
|
32556
|
+
type: "notification",
|
32557
|
+
duration: 5e3,
|
32558
|
+
...config,
|
32559
|
+
createdAt: Date.now(),
|
32560
|
+
onClose: () => hideNotification(id)
|
32561
|
+
};
|
32562
|
+
setNotifications((prev) => [...prev, notification]);
|
32563
|
+
if (notification.duration > 0) {
|
32564
|
+
setTimeout(() => hideNotification(id), notification.duration);
|
32565
|
+
}
|
32566
|
+
return id;
|
32567
|
+
}, [generateId]);
|
32568
|
+
const hideNotification = React.useCallback((id) => {
|
32569
|
+
setNotifications((prev) => prev.filter((notification) => notification.id !== id));
|
32570
|
+
}, []);
|
32571
|
+
const hideAllNotifications = React.useCallback(() => {
|
32572
|
+
setNotifications([]);
|
32573
|
+
}, []);
|
32574
|
+
const showTooltip = React.useCallback((config) => {
|
32575
|
+
const id = generateId();
|
32576
|
+
const tooltip = { id, type: "tooltip", ...config, createdAt: Date.now() };
|
32577
|
+
setTooltips((prev) => [...prev, tooltip]);
|
32578
|
+
return id;
|
32579
|
+
}, [generateId]);
|
32580
|
+
const hideTooltip = React.useCallback((id) => {
|
32581
|
+
setTooltips((prev) => prev.filter((tooltip) => tooltip.id !== id));
|
32582
|
+
}, []);
|
32583
|
+
const hideAllTooltips = React.useCallback(() => {
|
32584
|
+
setTooltips([]);
|
32585
|
+
}, []);
|
32586
|
+
const showContextMenu = React.useCallback((config) => {
|
32587
|
+
setContextMenus([]);
|
32588
|
+
const id = generateId();
|
32589
|
+
const contextMenu = {
|
32590
|
+
id,
|
32591
|
+
type: "contextMenu",
|
32592
|
+
...config,
|
32593
|
+
createdAt: Date.now(),
|
32594
|
+
onClose: () => hideContextMenu(id)
|
32595
|
+
};
|
32596
|
+
setContextMenus([contextMenu]);
|
32597
|
+
return id;
|
32598
|
+
}, [generateId]);
|
32599
|
+
const hideContextMenu = React.useCallback((id) => {
|
32600
|
+
setContextMenus((prev) => prev.filter((menu) => menu.id !== id));
|
32601
|
+
}, []);
|
32602
|
+
const hideAllContextMenus = React.useCallback(() => {
|
32603
|
+
setContextMenus([]);
|
32604
|
+
}, []);
|
32605
|
+
const showOverlay = React.useCallback((config) => {
|
32606
|
+
const id = generateId();
|
32607
|
+
const overlay = {
|
32608
|
+
id,
|
32609
|
+
type: "overlay",
|
32610
|
+
...config,
|
32611
|
+
createdAt: Date.now(),
|
32612
|
+
onClose: () => hideOverlay(id)
|
32613
|
+
};
|
32614
|
+
setOverlays((prev) => [...prev, overlay]);
|
32615
|
+
return id;
|
32616
|
+
}, [generateId]);
|
32617
|
+
const hideOverlay = React.useCallback((id) => {
|
32618
|
+
setOverlays((prev) => prev.filter((overlay) => overlay.id !== id));
|
32619
|
+
}, []);
|
32620
|
+
const hideAllOverlays = React.useCallback(() => {
|
32621
|
+
setOverlays([]);
|
32622
|
+
}, []);
|
32623
|
+
const clearAll = React.useCallback(() => {
|
32624
|
+
setDialogs([]);
|
32625
|
+
setNotifications([]);
|
32626
|
+
setTooltips([]);
|
32627
|
+
setContextMenus([]);
|
32628
|
+
setOverlays([]);
|
32629
|
+
}, []);
|
32630
|
+
const value = {
|
32631
|
+
windowId,
|
32632
|
+
dialogs,
|
32633
|
+
notifications,
|
32634
|
+
tooltips,
|
32635
|
+
contextMenus,
|
32636
|
+
overlays,
|
32637
|
+
showDialog,
|
32638
|
+
hideDialog,
|
32639
|
+
hideAllDialogs,
|
32640
|
+
showNotification,
|
32641
|
+
hideNotification,
|
32642
|
+
hideAllNotifications,
|
32643
|
+
showTooltip,
|
32644
|
+
hideTooltip,
|
32645
|
+
hideAllTooltips,
|
32646
|
+
showContextMenu,
|
32647
|
+
hideContextMenu,
|
32648
|
+
hideAllContextMenus,
|
32649
|
+
showOverlay,
|
32650
|
+
hideOverlay,
|
32651
|
+
hideAllOverlays,
|
32652
|
+
clearAll,
|
32653
|
+
generateId
|
32654
|
+
};
|
32655
|
+
return /* @__PURE__ */ React.createElement(WindowInstanceContext.Provider, { value }, children);
|
32656
|
+
};
|
32657
|
+
const useWindowInstance = () => {
|
32658
|
+
const context = React.useContext(WindowInstanceContext);
|
32659
|
+
if (!context) {
|
32660
|
+
throw new Error("useWindowInstance must be used within a WindowInstanceProvider");
|
32661
|
+
}
|
32662
|
+
return context;
|
32663
|
+
};
|
32664
|
+
const FloatingElementsRenderer = () => {
|
32665
|
+
const { dialogs, notifications, tooltips, contextMenus, overlays } = useWindowInstance();
|
32666
|
+
return /* @__PURE__ */ React.createElement("div", { className: "window-floating-elements" }, overlays.map((overlay) => /* @__PURE__ */ React.createElement("div", { key: overlay.id, className: "window-overlay" }, /* @__PURE__ */ React.createElement("div", { className: "window-overlay__content" }, overlay.content, overlay.showCloseButton !== false && /* @__PURE__ */ React.createElement(
|
32667
|
+
"button",
|
32668
|
+
{
|
32669
|
+
className: "window-dialog__close",
|
32670
|
+
onClick: () => overlay.onClose && overlay.onClose(),
|
32671
|
+
style: { position: "absolute", top: "8px", right: "8px" }
|
32672
|
+
},
|
32673
|
+
"×"
|
32674
|
+
)))), dialogs.map((dialog) => /* @__PURE__ */ React.createElement("div", { key: dialog.id, className: "window-dialog" }, /* @__PURE__ */ React.createElement("div", { className: "window-dialog__content" }, dialog.title && /* @__PURE__ */ React.createElement("div", { className: "window-dialog__header" }, /* @__PURE__ */ React.createElement("h3", { className: "window-dialog__title" }, dialog.title), /* @__PURE__ */ React.createElement(
|
32675
|
+
"button",
|
32676
|
+
{
|
32677
|
+
className: "window-dialog__close",
|
32678
|
+
onClick: () => dialog.onClose && dialog.onClose()
|
32679
|
+
},
|
32680
|
+
"×"
|
32681
|
+
)), /* @__PURE__ */ React.createElement("div", { className: "window-dialog__body" }, dialog.content), dialog.actions && /* @__PURE__ */ React.createElement("div", { className: "window-dialog__footer" }, dialog.actions)))), notifications.map((notification) => /* @__PURE__ */ React.createElement(
|
32682
|
+
"div",
|
32683
|
+
{
|
32684
|
+
key: notification.id,
|
32685
|
+
className: `window-notification window-notification--${notification.type || "info"}`,
|
32686
|
+
style: {
|
32687
|
+
top: `${16 + notifications.indexOf(notification) * 80}px`
|
32688
|
+
}
|
32689
|
+
},
|
32690
|
+
notification.icon && /* @__PURE__ */ React.createElement("div", { style: { fontSize: "18px", flexShrink: 0 } }, notification.icon),
|
32691
|
+
/* @__PURE__ */ React.createElement("div", { className: "window-notification__content" }, notification.title && /* @__PURE__ */ React.createElement("div", { className: "window-notification__title" }, notification.title), /* @__PURE__ */ React.createElement("div", { className: "window-notification__message" }, notification.message)),
|
32692
|
+
/* @__PURE__ */ React.createElement(
|
32693
|
+
"button",
|
32694
|
+
{
|
32695
|
+
className: "window-notification__close",
|
32696
|
+
onClick: () => notification.onClose && notification.onClose()
|
32697
|
+
},
|
32698
|
+
"×"
|
32699
|
+
)
|
32700
|
+
)), tooltips.map((tooltip) => /* @__PURE__ */ React.createElement(
|
32701
|
+
"div",
|
32702
|
+
{
|
32703
|
+
key: tooltip.id,
|
32704
|
+
className: "window-tooltip",
|
32705
|
+
style: {
|
32706
|
+
left: tooltip.x,
|
32707
|
+
top: tooltip.y,
|
32708
|
+
transform: tooltip.position === "top" ? "translateX(-50%) translateY(-100%)" : "translateX(-50%)"
|
32709
|
+
}
|
32710
|
+
},
|
32711
|
+
tooltip.text
|
32712
|
+
)), contextMenus.map((menu) => /* @__PURE__ */ React.createElement(
|
32713
|
+
"div",
|
32714
|
+
{
|
32715
|
+
key: menu.id,
|
32716
|
+
className: "window-context-menu",
|
32717
|
+
style: {
|
32718
|
+
left: menu.x,
|
32719
|
+
top: menu.y
|
32720
|
+
}
|
32721
|
+
},
|
32722
|
+
menu.items && menu.items.map((item, index) => /* @__PURE__ */ React.createElement(
|
32723
|
+
"div",
|
32724
|
+
{
|
32725
|
+
key: index,
|
32726
|
+
className: "window-context-menu__item",
|
32727
|
+
onClick: () => {
|
32728
|
+
item.onClick && item.onClick();
|
32729
|
+
menu.onClose && menu.onClose();
|
32730
|
+
}
|
32731
|
+
},
|
32732
|
+
item.icon && /* @__PURE__ */ React.createElement("span", null, item.icon),
|
32733
|
+
/* @__PURE__ */ React.createElement("span", null, item.label),
|
32734
|
+
item.shortcut && /* @__PURE__ */ React.createElement("span", { style: { marginLeft: "auto", fontSize: "11px", color: "#999" } }, item.shortcut)
|
32519
32735
|
))
|
32520
|
-
);
|
32736
|
+
)));
|
32521
32737
|
};
|
32522
32738
|
const ApplicationMenu = ({ isOpen, onClose }) => {
|
32523
32739
|
console.log("ApplicationMenu render - isOpen:", isOpen, "onClose:", onClose);
|