@react95/core 9.5.2 → 9.6.0
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/cjs/GlobalStyle/GlobalStyle.css.cjs +0 -1
- package/cjs/Modal/Modal.cjs +44 -31
- package/cjs/TaskBar/TaskBar.cjs +29 -17
- package/cjs/index.cjs +4 -0
- package/cjs/shared/emitter.cjs +35 -0
- package/cjs/shared/modal-controller.cjs +5 -0
- package/cjs/shared/modal-types.cjs +12 -0
- package/cjs/shared/use-modal.cjs +39 -0
- package/cjs/themes/azureOrange.css.cjs +1 -0
- package/esm/GlobalStyle/GlobalStyle.css.mjs +0 -1
- package/esm/Modal/Modal.mjs +44 -31
- package/esm/TaskBar/TaskBar.mjs +29 -17
- package/esm/index.mjs +5 -1
- package/esm/shared/emitter.mjs +35 -0
- package/esm/shared/modal-controller.mjs +5 -0
- package/esm/shared/modal-types.mjs +12 -0
- package/esm/shared/use-modal.mjs +39 -0
- package/esm/themes/azureOrange.css.mjs +1 -0
- package/package.json +2 -2
- package/types/Modal/Modal.d.ts +2 -1
- package/types/index.d.ts +2 -1
- package/types/shared/emitter.d.ts +6 -0
- package/types/shared/events.d.ts +4 -21
- package/types/shared/modal-controller.d.ts +11 -0
- package/types/shared/modal-types.d.ts +15 -0
- package/types/shared/use-modal.d.ts +14 -0
- package/cjs/shared/events.cjs +0 -37
- package/esm/shared/events.mjs +0 -37
package/cjs/Modal/Modal.cjs
CHANGED
|
@@ -9,30 +9,34 @@ const TitleBar = require("../TitleBar/TitleBar.cjs");
|
|
|
9
9
|
const Modal_css = require("./Modal.css.cjs");
|
|
10
10
|
const cn = require("classnames");
|
|
11
11
|
const usehooksTs = require("usehooks-ts");
|
|
12
|
-
const
|
|
12
|
+
const useModal = require("../shared/use-modal.cjs");
|
|
13
|
+
const modalTypes = require("../shared/modal-types.cjs");
|
|
13
14
|
const ModalContent = Frame.fixedForwardRef(
|
|
14
15
|
(rest, ref) => /* @__PURE__ */ React.createElement(Frame.Frame, { ...rest, ref, className: cn(Modal_css.content, rest.className) })
|
|
15
16
|
);
|
|
16
17
|
const ModalMinimize = Frame.fixedForwardRef(
|
|
17
18
|
(props, ref) => {
|
|
18
19
|
const [id, setId] = React.useState("");
|
|
20
|
+
const { minimize, focus, subscribe } = useModal.useModal();
|
|
19
21
|
React.useEffect(() => {
|
|
20
22
|
const handleVisibilityChange = ({ id: activeId }) => {
|
|
21
23
|
setId(activeId);
|
|
22
24
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const unsubscribe = subscribe(
|
|
26
|
+
modalTypes.ModalEvents.ModalVisibilityChanged,
|
|
27
|
+
handleVisibilityChange
|
|
28
|
+
);
|
|
29
|
+
return unsubscribe;
|
|
30
|
+
}, [subscribe]);
|
|
28
31
|
const handleMinimize = () => {
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
minimize(id);
|
|
33
|
+
focus("no-id");
|
|
31
34
|
};
|
|
32
35
|
return /* @__PURE__ */ React.createElement(TitleBar.TitleBar.Minimize, { ...props, ref, onClick: handleMinimize });
|
|
33
36
|
}
|
|
34
37
|
);
|
|
35
38
|
const ModalRenderer = ({
|
|
39
|
+
id: providedId,
|
|
36
40
|
hasWindowButton: hasButton = true,
|
|
37
41
|
buttons = [],
|
|
38
42
|
buttonsAlignment = "flex-end",
|
|
@@ -45,10 +49,11 @@ const ModalRenderer = ({
|
|
|
45
49
|
className,
|
|
46
50
|
...rest
|
|
47
51
|
}, ref) => {
|
|
48
|
-
const [id] = React.useState(nanoid.nanoid());
|
|
52
|
+
const [id] = React.useState(providedId || nanoid.nanoid());
|
|
49
53
|
const [menuOpened, setMenuOpened] = React.useState("");
|
|
50
54
|
const [isActive, setIsActive] = React.useState(false);
|
|
51
55
|
const [isModalMinimized, setIsModalMinimized] = React.useState(false);
|
|
56
|
+
const { add, remove, focus, subscribe } = useModal.useModal();
|
|
52
57
|
const draggableRef = React.useRef(null);
|
|
53
58
|
react.useDraggable(draggableRef, {
|
|
54
59
|
...dragOptions,
|
|
@@ -59,38 +64,46 @@ const ModalRenderer = ({
|
|
|
59
64
|
setMenuOpened("");
|
|
60
65
|
});
|
|
61
66
|
React.useEffect(() => {
|
|
62
|
-
|
|
67
|
+
add({
|
|
63
68
|
icon,
|
|
64
|
-
title,
|
|
69
|
+
title: title || "",
|
|
65
70
|
id,
|
|
66
71
|
hasButton
|
|
67
72
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
const unsubscribeVisibility = subscribe(
|
|
74
|
+
modalTypes.ModalEvents.ModalVisibilityChanged,
|
|
75
|
+
({ id: activeId }) => {
|
|
76
|
+
setIsActive(activeId === id);
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
focus(id);
|
|
72
80
|
return () => {
|
|
73
|
-
|
|
81
|
+
remove(id);
|
|
82
|
+
unsubscribeVisibility();
|
|
74
83
|
};
|
|
75
|
-
}, []);
|
|
84
|
+
}, [id, icon, title, hasButton, providedId, add, remove, focus, subscribe]);
|
|
76
85
|
React.useEffect(() => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
const unsubscribeMinimize = subscribe(
|
|
87
|
+
modalTypes.ModalEvents.MinimizeModal,
|
|
88
|
+
({ id: activeId }) => {
|
|
89
|
+
if (activeId === id) {
|
|
90
|
+
setIsModalMinimized(true);
|
|
91
|
+
}
|
|
80
92
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
);
|
|
94
|
+
const unsubscribeRestore = subscribe(
|
|
95
|
+
modalTypes.ModalEvents.RestoreModal,
|
|
96
|
+
({ id: activeId }) => {
|
|
97
|
+
if (activeId === id) {
|
|
98
|
+
setIsModalMinimized(false);
|
|
99
|
+
}
|
|
85
100
|
}
|
|
86
|
-
|
|
101
|
+
);
|
|
87
102
|
return () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
events.modals.off(events.ModalEvents.RestoreModal, () => {
|
|
91
|
-
});
|
|
103
|
+
unsubscribeMinimize();
|
|
104
|
+
unsubscribeRestore();
|
|
92
105
|
};
|
|
93
|
-
}, [id]);
|
|
106
|
+
}, [id, subscribe]);
|
|
94
107
|
React.useImperativeHandle(ref, () => {
|
|
95
108
|
return draggableRef.current;
|
|
96
109
|
});
|
|
@@ -106,7 +119,7 @@ const ModalRenderer = ({
|
|
|
106
119
|
"aria-hidden": isModalMinimized,
|
|
107
120
|
ref: draggableRef,
|
|
108
121
|
onMouseDown: () => {
|
|
109
|
-
|
|
122
|
+
focus(id);
|
|
110
123
|
}
|
|
111
124
|
},
|
|
112
125
|
/* @__PURE__ */ React.createElement(
|
package/cjs/TaskBar/TaskBar.cjs
CHANGED
|
@@ -6,16 +6,27 @@ const Clock = require("./Clock.cjs");
|
|
|
6
6
|
const WindowButton = require("./WindowButton.cjs");
|
|
7
7
|
const icons = require("@react95/icons");
|
|
8
8
|
const TaskBar_css = require("./TaskBar.css.cjs");
|
|
9
|
-
const
|
|
9
|
+
const useModal = require("../shared/use-modal.cjs");
|
|
10
|
+
const modalTypes = require("../shared/modal-types.cjs");
|
|
10
11
|
const TaskBar = React.forwardRef(
|
|
11
12
|
({ list, className }, ref) => {
|
|
12
13
|
const [showList, toggleShowList] = React.useState(false);
|
|
13
14
|
const [activeStart, toggleActiveStart] = React.useState(false);
|
|
14
15
|
const [modalWindows, setModalWindows] = React.useState([]);
|
|
15
16
|
const [activeWindow, setActiveWindow] = React.useState();
|
|
17
|
+
const { minimize, restore, focus, subscribe } = useModal.useModal();
|
|
16
18
|
React.useEffect(() => {
|
|
17
19
|
const addModal = (window) => {
|
|
18
|
-
|
|
20
|
+
if (!window.id) {
|
|
21
|
+
console.warn("Modal added without ID");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setModalWindows((prevModals) => {
|
|
25
|
+
if (prevModals.some((modal) => modal.id === window.id)) {
|
|
26
|
+
return prevModals;
|
|
27
|
+
}
|
|
28
|
+
return [...prevModals, window];
|
|
29
|
+
});
|
|
19
30
|
};
|
|
20
31
|
const removeModal = (data) => {
|
|
21
32
|
setModalWindows((prevModals) => {
|
|
@@ -23,10 +34,8 @@ const TaskBar = React.forwardRef(
|
|
|
23
34
|
(modal) => modal.id !== data.id
|
|
24
35
|
);
|
|
25
36
|
const lastModal = filteredModals.at(-1);
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
id: lastModal == null ? void 0 : lastModal.id
|
|
29
|
-
});
|
|
37
|
+
if (activeWindow === data.id && lastModal) {
|
|
38
|
+
focus(lastModal.id);
|
|
30
39
|
}
|
|
31
40
|
return filteredModals;
|
|
32
41
|
});
|
|
@@ -34,15 +43,18 @@ const TaskBar = React.forwardRef(
|
|
|
34
43
|
const updateVisibleModal = ({ id }) => {
|
|
35
44
|
setActiveWindow(id);
|
|
36
45
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
const unsubscribeAdd = subscribe(modalTypes.ModalEvents.AddModal, addModal);
|
|
47
|
+
const unsubscribeRemove = subscribe(modalTypes.ModalEvents.RemoveModal, removeModal);
|
|
48
|
+
const unsubscribeVisibility = subscribe(
|
|
49
|
+
modalTypes.ModalEvents.ModalVisibilityChanged,
|
|
50
|
+
updateVisibleModal
|
|
51
|
+
);
|
|
40
52
|
return () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
unsubscribeAdd();
|
|
54
|
+
unsubscribeRemove();
|
|
55
|
+
unsubscribeVisibility();
|
|
44
56
|
};
|
|
45
|
-
}, []);
|
|
57
|
+
}, [activeWindow, subscribe, focus]);
|
|
46
58
|
return /* @__PURE__ */ React.createElement(
|
|
47
59
|
Frame.Frame,
|
|
48
60
|
{
|
|
@@ -95,11 +107,11 @@ const TaskBar = React.forwardRef(
|
|
|
95
107
|
active: id === activeWindow,
|
|
96
108
|
onClick: () => {
|
|
97
109
|
if (id === activeWindow) {
|
|
98
|
-
|
|
99
|
-
setActiveWindow(
|
|
110
|
+
minimize(id);
|
|
111
|
+
setActiveWindow(void 0);
|
|
100
112
|
} else {
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
restore(id);
|
|
114
|
+
focus(id);
|
|
103
115
|
}
|
|
104
116
|
},
|
|
105
117
|
small: false
|
package/cjs/index.cjs
CHANGED
|
@@ -24,6 +24,8 @@ const TitleBar = require("./TitleBar/TitleBar.cjs");
|
|
|
24
24
|
const Video = require("./Video/Video.cjs");
|
|
25
25
|
const contract_css = require("./themes/contract.css.cjs");
|
|
26
26
|
const index = require("./themes/tokens/index.cjs");
|
|
27
|
+
const modalTypes = require("./shared/modal-types.cjs");
|
|
28
|
+
const useModal = require("./shared/use-modal.cjs");
|
|
27
29
|
exports.Modal = Modal.Modal;
|
|
28
30
|
exports.Tabs = Tabs.Tabs;
|
|
29
31
|
exports.Tab = Tab.Tab;
|
|
@@ -48,3 +50,5 @@ exports.TitleBar = TitleBar.TitleBar;
|
|
|
48
50
|
exports.Video = Video.Video;
|
|
49
51
|
exports.contract = contract_css.contract;
|
|
50
52
|
exports.tokens = index;
|
|
53
|
+
exports.ModalEvents = modalTypes.ModalEvents;
|
|
54
|
+
exports.useModal = useModal.useModal;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
class Emitter {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.listeners = {};
|
|
6
|
+
}
|
|
7
|
+
on(eventName, callback) {
|
|
8
|
+
var _a;
|
|
9
|
+
if (!this.listeners[eventName]) {
|
|
10
|
+
this.listeners[eventName] = [];
|
|
11
|
+
}
|
|
12
|
+
(_a = this.listeners[eventName]) == null ? void 0 : _a.push(callback);
|
|
13
|
+
}
|
|
14
|
+
off(eventName, callback) {
|
|
15
|
+
var _a;
|
|
16
|
+
if (this.listeners[eventName]) {
|
|
17
|
+
this.listeners[eventName] = (_a = this.listeners[eventName]) == null ? void 0 : _a.filter(
|
|
18
|
+
(cb) => cb !== callback
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
emit(eventName, data) {
|
|
23
|
+
var _a;
|
|
24
|
+
if (this.listeners[eventName]) {
|
|
25
|
+
(_a = this.listeners[eventName]) == null ? void 0 : _a.forEach((callback) => {
|
|
26
|
+
try {
|
|
27
|
+
callback(data);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Error in event listener for ${eventName}:`, error);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.Emitter = Emitter;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
var ModalEvents = /* @__PURE__ */ ((ModalEvents2) => {
|
|
4
|
+
ModalEvents2["AddModal"] = "add-modal";
|
|
5
|
+
ModalEvents2["RemoveModal"] = "remove-modal";
|
|
6
|
+
ModalEvents2["ModalVisibilityChanged"] = "modal-visibility-changed";
|
|
7
|
+
ModalEvents2["MinimizeModal"] = "minimize-modal";
|
|
8
|
+
ModalEvents2["RestoreModal"] = "restore-modal";
|
|
9
|
+
ModalEvents2["FocusModal"] = "focus-modal";
|
|
10
|
+
return ModalEvents2;
|
|
11
|
+
})(ModalEvents || {});
|
|
12
|
+
exports.ModalEvents = ModalEvents;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const modalController = require("./modal-controller.cjs");
|
|
5
|
+
const modalTypes = require("./modal-types.cjs");
|
|
6
|
+
const useModal = () => {
|
|
7
|
+
const add = React.useCallback((modal) => {
|
|
8
|
+
modalController.modals.emit(modalTypes.ModalEvents.AddModal, modal);
|
|
9
|
+
}, []);
|
|
10
|
+
const remove = React.useCallback((id) => {
|
|
11
|
+
modalController.modals.emit(modalTypes.ModalEvents.RemoveModal, { id });
|
|
12
|
+
}, []);
|
|
13
|
+
const minimize = React.useCallback((id) => {
|
|
14
|
+
modalController.modals.emit(modalTypes.ModalEvents.MinimizeModal, { id });
|
|
15
|
+
}, []);
|
|
16
|
+
const restore = React.useCallback((id) => {
|
|
17
|
+
modalController.modals.emit(modalTypes.ModalEvents.RestoreModal, { id });
|
|
18
|
+
}, []);
|
|
19
|
+
const focus = React.useCallback((id) => {
|
|
20
|
+
modalController.modals.emit(modalTypes.ModalEvents.ModalVisibilityChanged, { id });
|
|
21
|
+
}, []);
|
|
22
|
+
const toggle = React.useCallback((id, isActive) => {
|
|
23
|
+
if (isActive) {
|
|
24
|
+
modalController.modals.emit(modalTypes.ModalEvents.MinimizeModal, { id });
|
|
25
|
+
} else {
|
|
26
|
+
modalController.modals.emit(modalTypes.ModalEvents.RestoreModal, { id });
|
|
27
|
+
modalController.modals.emit(modalTypes.ModalEvents.ModalVisibilityChanged, { id });
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
const subscribe = React.useCallback(
|
|
31
|
+
(event, callback) => {
|
|
32
|
+
modalController.modals.on(event, callback);
|
|
33
|
+
return () => modalController.modals.off(event, callback);
|
|
34
|
+
},
|
|
35
|
+
[]
|
|
36
|
+
);
|
|
37
|
+
return { add, remove, minimize, restore, focus, toggle, subscribe };
|
|
38
|
+
};
|
|
39
|
+
exports.useModal = useModal;
|
package/esm/Modal/Modal.mjs
CHANGED
|
@@ -7,30 +7,34 @@ import { TitleBar } from "../TitleBar/TitleBar.mjs";
|
|
|
7
7
|
import { content, modalWrapper, menuWrapper, menuItem, buttonWrapper } from "./Modal.css.mjs";
|
|
8
8
|
import cn from "classnames";
|
|
9
9
|
import { useOnClickOutside } from "usehooks-ts";
|
|
10
|
-
import {
|
|
10
|
+
import { useModal } from "../shared/use-modal.mjs";
|
|
11
|
+
import { ModalEvents } from "../shared/modal-types.mjs";
|
|
11
12
|
const ModalContent = fixedForwardRef(
|
|
12
13
|
(rest, ref) => /* @__PURE__ */ React.createElement(Frame, { ...rest, ref, className: cn(content, rest.className) })
|
|
13
14
|
);
|
|
14
15
|
const ModalMinimize = fixedForwardRef(
|
|
15
16
|
(props, ref) => {
|
|
16
17
|
const [id, setId] = useState("");
|
|
18
|
+
const { minimize, focus, subscribe } = useModal();
|
|
17
19
|
useEffect(() => {
|
|
18
20
|
const handleVisibilityChange = ({ id: activeId }) => {
|
|
19
21
|
setId(activeId);
|
|
20
22
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const unsubscribe = subscribe(
|
|
24
|
+
ModalEvents.ModalVisibilityChanged,
|
|
25
|
+
handleVisibilityChange
|
|
26
|
+
);
|
|
27
|
+
return unsubscribe;
|
|
28
|
+
}, [subscribe]);
|
|
26
29
|
const handleMinimize = () => {
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
minimize(id);
|
|
31
|
+
focus("no-id");
|
|
29
32
|
};
|
|
30
33
|
return /* @__PURE__ */ React.createElement(TitleBar.Minimize, { ...props, ref, onClick: handleMinimize });
|
|
31
34
|
}
|
|
32
35
|
);
|
|
33
36
|
const ModalRenderer = ({
|
|
37
|
+
id: providedId,
|
|
34
38
|
hasWindowButton: hasButton = true,
|
|
35
39
|
buttons = [],
|
|
36
40
|
buttonsAlignment = "flex-end",
|
|
@@ -43,10 +47,11 @@ const ModalRenderer = ({
|
|
|
43
47
|
className,
|
|
44
48
|
...rest
|
|
45
49
|
}, ref) => {
|
|
46
|
-
const [id] = useState(nanoid());
|
|
50
|
+
const [id] = useState(providedId || nanoid());
|
|
47
51
|
const [menuOpened, setMenuOpened] = useState("");
|
|
48
52
|
const [isActive, setIsActive] = useState(false);
|
|
49
53
|
const [isModalMinimized, setIsModalMinimized] = useState(false);
|
|
54
|
+
const { add, remove, focus, subscribe } = useModal();
|
|
50
55
|
const draggableRef = useRef(null);
|
|
51
56
|
useDraggable(draggableRef, {
|
|
52
57
|
...dragOptions,
|
|
@@ -57,38 +62,46 @@ const ModalRenderer = ({
|
|
|
57
62
|
setMenuOpened("");
|
|
58
63
|
});
|
|
59
64
|
useEffect(() => {
|
|
60
|
-
|
|
65
|
+
add({
|
|
61
66
|
icon,
|
|
62
|
-
title,
|
|
67
|
+
title: title || "",
|
|
63
68
|
id,
|
|
64
69
|
hasButton
|
|
65
70
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
const unsubscribeVisibility = subscribe(
|
|
72
|
+
ModalEvents.ModalVisibilityChanged,
|
|
73
|
+
({ id: activeId }) => {
|
|
74
|
+
setIsActive(activeId === id);
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
focus(id);
|
|
70
78
|
return () => {
|
|
71
|
-
|
|
79
|
+
remove(id);
|
|
80
|
+
unsubscribeVisibility();
|
|
72
81
|
};
|
|
73
|
-
}, []);
|
|
82
|
+
}, [id, icon, title, hasButton, providedId, add, remove, focus, subscribe]);
|
|
74
83
|
useEffect(() => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
const unsubscribeMinimize = subscribe(
|
|
85
|
+
ModalEvents.MinimizeModal,
|
|
86
|
+
({ id: activeId }) => {
|
|
87
|
+
if (activeId === id) {
|
|
88
|
+
setIsModalMinimized(true);
|
|
89
|
+
}
|
|
78
90
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
);
|
|
92
|
+
const unsubscribeRestore = subscribe(
|
|
93
|
+
ModalEvents.RestoreModal,
|
|
94
|
+
({ id: activeId }) => {
|
|
95
|
+
if (activeId === id) {
|
|
96
|
+
setIsModalMinimized(false);
|
|
97
|
+
}
|
|
83
98
|
}
|
|
84
|
-
|
|
99
|
+
);
|
|
85
100
|
return () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
modals.off(ModalEvents.RestoreModal, () => {
|
|
89
|
-
});
|
|
101
|
+
unsubscribeMinimize();
|
|
102
|
+
unsubscribeRestore();
|
|
90
103
|
};
|
|
91
|
-
}, [id]);
|
|
104
|
+
}, [id, subscribe]);
|
|
92
105
|
useImperativeHandle(ref, () => {
|
|
93
106
|
return draggableRef.current;
|
|
94
107
|
});
|
|
@@ -104,7 +117,7 @@ const ModalRenderer = ({
|
|
|
104
117
|
"aria-hidden": isModalMinimized,
|
|
105
118
|
ref: draggableRef,
|
|
106
119
|
onMouseDown: () => {
|
|
107
|
-
|
|
120
|
+
focus(id);
|
|
108
121
|
}
|
|
109
122
|
},
|
|
110
123
|
/* @__PURE__ */ React.createElement(
|
package/esm/TaskBar/TaskBar.mjs
CHANGED
|
@@ -4,16 +4,27 @@ import { Clock } from "./Clock.mjs";
|
|
|
4
4
|
import { WindowButton } from "./WindowButton.mjs";
|
|
5
5
|
import { Logo } from "@react95/icons";
|
|
6
6
|
import { truncate } from "./TaskBar.css.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { useModal } from "../shared/use-modal.mjs";
|
|
8
|
+
import { ModalEvents } from "../shared/modal-types.mjs";
|
|
8
9
|
const TaskBar = forwardRef(
|
|
9
10
|
({ list, className }, ref) => {
|
|
10
11
|
const [showList, toggleShowList] = useState(false);
|
|
11
12
|
const [activeStart, toggleActiveStart] = useState(false);
|
|
12
13
|
const [modalWindows, setModalWindows] = React.useState([]);
|
|
13
14
|
const [activeWindow, setActiveWindow] = useState();
|
|
15
|
+
const { minimize, restore, focus, subscribe } = useModal();
|
|
14
16
|
useEffect(() => {
|
|
15
17
|
const addModal = (window) => {
|
|
16
|
-
|
|
18
|
+
if (!window.id) {
|
|
19
|
+
console.warn("Modal added without ID");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
setModalWindows((prevModals) => {
|
|
23
|
+
if (prevModals.some((modal) => modal.id === window.id)) {
|
|
24
|
+
return prevModals;
|
|
25
|
+
}
|
|
26
|
+
return [...prevModals, window];
|
|
27
|
+
});
|
|
17
28
|
};
|
|
18
29
|
const removeModal = (data) => {
|
|
19
30
|
setModalWindows((prevModals) => {
|
|
@@ -21,10 +32,8 @@ const TaskBar = forwardRef(
|
|
|
21
32
|
(modal) => modal.id !== data.id
|
|
22
33
|
);
|
|
23
34
|
const lastModal = filteredModals.at(-1);
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
id: lastModal == null ? void 0 : lastModal.id
|
|
27
|
-
});
|
|
35
|
+
if (activeWindow === data.id && lastModal) {
|
|
36
|
+
focus(lastModal.id);
|
|
28
37
|
}
|
|
29
38
|
return filteredModals;
|
|
30
39
|
});
|
|
@@ -32,15 +41,18 @@ const TaskBar = forwardRef(
|
|
|
32
41
|
const updateVisibleModal = ({ id }) => {
|
|
33
42
|
setActiveWindow(id);
|
|
34
43
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
const unsubscribeAdd = subscribe(ModalEvents.AddModal, addModal);
|
|
45
|
+
const unsubscribeRemove = subscribe(ModalEvents.RemoveModal, removeModal);
|
|
46
|
+
const unsubscribeVisibility = subscribe(
|
|
47
|
+
ModalEvents.ModalVisibilityChanged,
|
|
48
|
+
updateVisibleModal
|
|
49
|
+
);
|
|
38
50
|
return () => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
unsubscribeAdd();
|
|
52
|
+
unsubscribeRemove();
|
|
53
|
+
unsubscribeVisibility();
|
|
42
54
|
};
|
|
43
|
-
}, []);
|
|
55
|
+
}, [activeWindow, subscribe, focus]);
|
|
44
56
|
return /* @__PURE__ */ React.createElement(
|
|
45
57
|
Frame,
|
|
46
58
|
{
|
|
@@ -93,11 +105,11 @@ const TaskBar = forwardRef(
|
|
|
93
105
|
active: id === activeWindow,
|
|
94
106
|
onClick: () => {
|
|
95
107
|
if (id === activeWindow) {
|
|
96
|
-
|
|
97
|
-
setActiveWindow(
|
|
108
|
+
minimize(id);
|
|
109
|
+
setActiveWindow(void 0);
|
|
98
110
|
} else {
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
restore(id);
|
|
112
|
+
focus(id);
|
|
101
113
|
}
|
|
102
114
|
},
|
|
103
115
|
small: false
|
package/esm/index.mjs
CHANGED
|
@@ -22,6 +22,8 @@ import { TitleBar } from "./TitleBar/TitleBar.mjs";
|
|
|
22
22
|
import { Video } from "./Video/Video.mjs";
|
|
23
23
|
import { contract } from "./themes/contract.css.mjs";
|
|
24
24
|
import * as index from "./themes/tokens/index.mjs";
|
|
25
|
+
import { ModalEvents } from "./shared/modal-types.mjs";
|
|
26
|
+
import { useModal } from "./shared/use-modal.mjs";
|
|
25
27
|
export {
|
|
26
28
|
Alert,
|
|
27
29
|
Avatar,
|
|
@@ -34,6 +36,7 @@ export {
|
|
|
34
36
|
Input,
|
|
35
37
|
List,
|
|
36
38
|
Modal,
|
|
39
|
+
ModalEvents,
|
|
37
40
|
ProgressBar,
|
|
38
41
|
RadioButton,
|
|
39
42
|
Range,
|
|
@@ -46,5 +49,6 @@ export {
|
|
|
46
49
|
Tree,
|
|
47
50
|
Video,
|
|
48
51
|
contract,
|
|
49
|
-
index as tokens
|
|
52
|
+
index as tokens,
|
|
53
|
+
useModal
|
|
50
54
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class Emitter {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.listeners = {};
|
|
4
|
+
}
|
|
5
|
+
on(eventName, callback) {
|
|
6
|
+
var _a;
|
|
7
|
+
if (!this.listeners[eventName]) {
|
|
8
|
+
this.listeners[eventName] = [];
|
|
9
|
+
}
|
|
10
|
+
(_a = this.listeners[eventName]) == null ? void 0 : _a.push(callback);
|
|
11
|
+
}
|
|
12
|
+
off(eventName, callback) {
|
|
13
|
+
var _a;
|
|
14
|
+
if (this.listeners[eventName]) {
|
|
15
|
+
this.listeners[eventName] = (_a = this.listeners[eventName]) == null ? void 0 : _a.filter(
|
|
16
|
+
(cb) => cb !== callback
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
emit(eventName, data) {
|
|
21
|
+
var _a;
|
|
22
|
+
if (this.listeners[eventName]) {
|
|
23
|
+
(_a = this.listeners[eventName]) == null ? void 0 : _a.forEach((callback) => {
|
|
24
|
+
try {
|
|
25
|
+
callback(data);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(`Error in event listener for ${eventName}:`, error);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
Emitter
|
|
35
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
var ModalEvents = /* @__PURE__ */ ((ModalEvents2) => {
|
|
2
|
+
ModalEvents2["AddModal"] = "add-modal";
|
|
3
|
+
ModalEvents2["RemoveModal"] = "remove-modal";
|
|
4
|
+
ModalEvents2["ModalVisibilityChanged"] = "modal-visibility-changed";
|
|
5
|
+
ModalEvents2["MinimizeModal"] = "minimize-modal";
|
|
6
|
+
ModalEvents2["RestoreModal"] = "restore-modal";
|
|
7
|
+
ModalEvents2["FocusModal"] = "focus-modal";
|
|
8
|
+
return ModalEvents2;
|
|
9
|
+
})(ModalEvents || {});
|
|
10
|
+
export {
|
|
11
|
+
ModalEvents
|
|
12
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { modals } from "./modal-controller.mjs";
|
|
3
|
+
import { ModalEvents } from "./modal-types.mjs";
|
|
4
|
+
const useModal = () => {
|
|
5
|
+
const add = useCallback((modal) => {
|
|
6
|
+
modals.emit(ModalEvents.AddModal, modal);
|
|
7
|
+
}, []);
|
|
8
|
+
const remove = useCallback((id) => {
|
|
9
|
+
modals.emit(ModalEvents.RemoveModal, { id });
|
|
10
|
+
}, []);
|
|
11
|
+
const minimize = useCallback((id) => {
|
|
12
|
+
modals.emit(ModalEvents.MinimizeModal, { id });
|
|
13
|
+
}, []);
|
|
14
|
+
const restore = useCallback((id) => {
|
|
15
|
+
modals.emit(ModalEvents.RestoreModal, { id });
|
|
16
|
+
}, []);
|
|
17
|
+
const focus = useCallback((id) => {
|
|
18
|
+
modals.emit(ModalEvents.ModalVisibilityChanged, { id });
|
|
19
|
+
}, []);
|
|
20
|
+
const toggle = useCallback((id, isActive) => {
|
|
21
|
+
if (isActive) {
|
|
22
|
+
modals.emit(ModalEvents.MinimizeModal, { id });
|
|
23
|
+
} else {
|
|
24
|
+
modals.emit(ModalEvents.RestoreModal, { id });
|
|
25
|
+
modals.emit(ModalEvents.ModalVisibilityChanged, { id });
|
|
26
|
+
}
|
|
27
|
+
}, []);
|
|
28
|
+
const subscribe = useCallback(
|
|
29
|
+
(event, callback) => {
|
|
30
|
+
modals.on(event, callback);
|
|
31
|
+
return () => modals.off(event, callback);
|
|
32
|
+
},
|
|
33
|
+
[]
|
|
34
|
+
);
|
|
35
|
+
return { add, remove, minimize, restore, focus, toggle, subscribe };
|
|
36
|
+
};
|
|
37
|
+
export {
|
|
38
|
+
useModal
|
|
39
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react95/core",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.6.0",
|
|
4
4
|
"description": "Windows 95 styleguide",
|
|
5
5
|
"main": "cjs/index.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
"url": "https://github.com/React95/React95/issues"
|
|
196
196
|
},
|
|
197
197
|
"homepage": "https://github.com/React95/React95#readme",
|
|
198
|
-
"gitHead": "
|
|
198
|
+
"gitHead": "6cc1349c2f972524a3741900c2d284633d4d9abe",
|
|
199
199
|
"module": "esm/index.mjs",
|
|
200
200
|
"private": false,
|
|
201
201
|
"types": "types/index.d.ts"
|
package/types/Modal/Modal.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export type ModalDefaultPosition = {
|
|
|
17
17
|
};
|
|
18
18
|
type TitleBarOptions = typeof TitleBar.Close | typeof TitleBar.Help | typeof TitleBar.Maximize | typeof TitleBar.Minimize | typeof TitleBar.Restore;
|
|
19
19
|
export type ModalProps = {
|
|
20
|
+
id?: string;
|
|
20
21
|
buttons?: Array<ModalButtons>;
|
|
21
22
|
menu?: Array<ModalMenu>;
|
|
22
23
|
dragOptions?: Omit<DragOptions, 'handle'>;
|
|
@@ -2391,7 +2392,7 @@ declare const ModalContent: (props: {
|
|
|
2391
2392
|
};
|
|
2392
2393
|
}> & React.RefAttributes<HTMLDivElement>) => React.ReactNode;
|
|
2393
2394
|
declare const ModalMinimize: OptionReturnType;
|
|
2394
|
-
declare const ModalRenderer: ({ hasWindowButton: hasButton, buttons, buttonsAlignment, children, icon, menu, title, dragOptions, titleBarOptions, className, ...rest }: ModalProps, ref: Ref<HTMLDivElement | null>) => React.JSX.Element;
|
|
2395
|
+
declare const ModalRenderer: ({ id: providedId, hasWindowButton: hasButton, buttons, buttonsAlignment, children, icon, menu, title, dragOptions, titleBarOptions, className, ...rest }: ModalProps, ref: Ref<HTMLDivElement | null>) => React.JSX.Element;
|
|
2395
2396
|
export declare const Modal: ModalProps & typeof ModalRenderer & {
|
|
2396
2397
|
Content: typeof ModalContent;
|
|
2397
2398
|
Minimize: typeof ModalMinimize;
|
package/types/index.d.ts
CHANGED
|
@@ -22,4 +22,5 @@ import { TitleBar } from './TitleBar/TitleBar';
|
|
|
22
22
|
import { Video } from './Video/Video';
|
|
23
23
|
import { contract } from './themes/contract.css';
|
|
24
24
|
import * as tokens from './themes/tokens';
|
|
25
|
-
|
|
25
|
+
import { ModalEvents, useModal } from './shared/events';
|
|
26
|
+
export { Alert, Avatar, Button, Checkbox, Cursor, Dropdown, Fieldset, Frame, Input, List, Modal, ProgressBar, RadioButton, Range, Tab, Tabs, TaskBar, TextArea, Tree, Tooltip, TitleBar, Video, contract, tokens, ModalEvents, useModal, };
|
package/types/shared/events.d.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
off(eventName: U, callback: (data: T) => void): void;
|
|
6
|
-
emit(eventName: U, data: Partial<T>): void;
|
|
7
|
-
}
|
|
8
|
-
export declare enum ModalEvents {
|
|
9
|
-
AddModal = "add-modal",
|
|
10
|
-
RemoveModal = "remove-modal",
|
|
11
|
-
ModalVisibilityChanged = "modal-visibility-changed",
|
|
12
|
-
MinimizeModal = "minimize-modal",
|
|
13
|
-
RestoreModal = "restore-modal"
|
|
14
|
-
}
|
|
15
|
-
export interface ModalWindow {
|
|
16
|
-
icon?: ReactElement;
|
|
17
|
-
title: string;
|
|
18
|
-
hasButton: boolean;
|
|
19
|
-
id: string;
|
|
20
|
-
}
|
|
21
|
-
export declare const modals: Emitter<ModalEvents, ModalWindow>;
|
|
1
|
+
export { Emitter } from './emitter';
|
|
2
|
+
export { ModalEvents, type ModalWindow } from './modal-types';
|
|
3
|
+
export { modals, modalController } from './modal-controller';
|
|
4
|
+
export { useModal } from './use-modal';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Emitter } from './emitter';
|
|
2
|
+
import { ModalEvents, ModalWindow } from './modal-types';
|
|
3
|
+
export declare const modals: Emitter<ModalEvents, ModalWindow>;
|
|
4
|
+
export declare const modalController: {
|
|
5
|
+
add: (modal: ModalWindow) => void;
|
|
6
|
+
remove: (id: string) => void;
|
|
7
|
+
minimize: (id: string) => void;
|
|
8
|
+
restore: (id: string) => void;
|
|
9
|
+
focus: (id: string) => void;
|
|
10
|
+
toggle: (id: string, isActive: boolean) => void;
|
|
11
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
export declare enum ModalEvents {
|
|
3
|
+
AddModal = "add-modal",
|
|
4
|
+
RemoveModal = "remove-modal",
|
|
5
|
+
ModalVisibilityChanged = "modal-visibility-changed",
|
|
6
|
+
MinimizeModal = "minimize-modal",
|
|
7
|
+
RestoreModal = "restore-modal",
|
|
8
|
+
FocusModal = "focus-modal"
|
|
9
|
+
}
|
|
10
|
+
export interface ModalWindow {
|
|
11
|
+
icon?: ReactElement;
|
|
12
|
+
title: string;
|
|
13
|
+
hasButton: boolean;
|
|
14
|
+
id: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ModalEvents, ModalWindow } from './modal-types';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for controlling and listening to modal events
|
|
4
|
+
* @returns Object with methods to control modals and subscribe to events
|
|
5
|
+
*/
|
|
6
|
+
export declare const useModal: () => {
|
|
7
|
+
add: (modal: ModalWindow) => void;
|
|
8
|
+
remove: (id: string) => void;
|
|
9
|
+
minimize: (id: string) => void;
|
|
10
|
+
restore: (id: string) => void;
|
|
11
|
+
focus: (id: string) => void;
|
|
12
|
+
toggle: (id: string, isActive: boolean) => void;
|
|
13
|
+
subscribe: (event: ModalEvents, callback: (data: Partial<ModalWindow>) => void) => () => void;
|
|
14
|
+
};
|
package/cjs/shared/events.cjs
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
class Emitter {
|
|
4
|
-
constructor() {
|
|
5
|
-
this.listeners = {};
|
|
6
|
-
}
|
|
7
|
-
on(eventName, callback) {
|
|
8
|
-
if (!this.listeners[eventName]) {
|
|
9
|
-
this.listeners[eventName] = [];
|
|
10
|
-
}
|
|
11
|
-
this.listeners[eventName].push(callback);
|
|
12
|
-
}
|
|
13
|
-
off(eventName, callback) {
|
|
14
|
-
if (this.listeners[eventName]) {
|
|
15
|
-
this.listeners[eventName] = this.listeners[eventName].filter(
|
|
16
|
-
(cb) => cb !== callback
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
emit(eventName, data) {
|
|
21
|
-
if (this.listeners[eventName]) {
|
|
22
|
-
this.listeners[eventName].forEach((callback) => callback(data));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
var ModalEvents = /* @__PURE__ */ ((ModalEvents2) => {
|
|
27
|
-
ModalEvents2["AddModal"] = "add-modal";
|
|
28
|
-
ModalEvents2["RemoveModal"] = "remove-modal";
|
|
29
|
-
ModalEvents2["ModalVisibilityChanged"] = "modal-visibility-changed";
|
|
30
|
-
ModalEvents2["MinimizeModal"] = "minimize-modal";
|
|
31
|
-
ModalEvents2["RestoreModal"] = "restore-modal";
|
|
32
|
-
return ModalEvents2;
|
|
33
|
-
})(ModalEvents || {});
|
|
34
|
-
const modals = new Emitter();
|
|
35
|
-
exports.Emitter = Emitter;
|
|
36
|
-
exports.ModalEvents = ModalEvents;
|
|
37
|
-
exports.modals = modals;
|
package/esm/shared/events.mjs
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
class Emitter {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.listeners = {};
|
|
4
|
-
}
|
|
5
|
-
on(eventName, callback) {
|
|
6
|
-
if (!this.listeners[eventName]) {
|
|
7
|
-
this.listeners[eventName] = [];
|
|
8
|
-
}
|
|
9
|
-
this.listeners[eventName].push(callback);
|
|
10
|
-
}
|
|
11
|
-
off(eventName, callback) {
|
|
12
|
-
if (this.listeners[eventName]) {
|
|
13
|
-
this.listeners[eventName] = this.listeners[eventName].filter(
|
|
14
|
-
(cb) => cb !== callback
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
emit(eventName, data) {
|
|
19
|
-
if (this.listeners[eventName]) {
|
|
20
|
-
this.listeners[eventName].forEach((callback) => callback(data));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
var ModalEvents = /* @__PURE__ */ ((ModalEvents2) => {
|
|
25
|
-
ModalEvents2["AddModal"] = "add-modal";
|
|
26
|
-
ModalEvents2["RemoveModal"] = "remove-modal";
|
|
27
|
-
ModalEvents2["ModalVisibilityChanged"] = "modal-visibility-changed";
|
|
28
|
-
ModalEvents2["MinimizeModal"] = "minimize-modal";
|
|
29
|
-
ModalEvents2["RestoreModal"] = "restore-modal";
|
|
30
|
-
return ModalEvents2;
|
|
31
|
-
})(ModalEvents || {});
|
|
32
|
-
const modals = new Emitter();
|
|
33
|
-
export {
|
|
34
|
-
Emitter,
|
|
35
|
-
ModalEvents,
|
|
36
|
-
modals
|
|
37
|
-
};
|