@jsenv/plugin-toolbar 0.1.0 → 0.1.2
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/css/document_execution_indicator.css +87 -0
- package/dist/css/globals.css +75 -0
- package/dist/css/server_indicator.css +83 -0
- package/dist/css/theme_light.css +110 -0
- package/dist/css/toolbar.css +7 -683
- package/dist/css/toolbar_menu_overflow.css +59 -0
- package/dist/css/toolbar_settings.css +202 -0
- package/dist/css/tooltips.css +67 -0
- package/dist/js/animation.js +282 -0
- package/dist/js/animation_actions.js +7 -0
- package/dist/js/animation_effects.js +10 -0
- package/dist/js/animation_signals.js +4 -0
- package/dist/js/changes_actions.js +7 -0
- package/dist/js/changes_indicator.js +57 -0
- package/dist/js/changes_signals.js +2 -0
- package/dist/js/document_execution_indicator.js +62 -0
- package/dist/js/document_index_link.js +4 -0
- package/dist/js/dom.js +48 -0
- package/dist/js/execution_actions.js +46 -0
- package/dist/js/execution_effects.js +16 -0
- package/dist/js/execution_signals.js +17 -0
- package/dist/js/hooks.mjs +185 -0
- package/dist/js/iframe_to_parent_href.js +10 -0
- package/dist/js/notification_actions.js +60 -0
- package/dist/js/notification_context.js +1 -0
- package/dist/js/notification_effects.js +9 -0
- package/dist/js/notification_signals.js +5 -0
- package/dist/js/parent_window_actions.js +39 -0
- package/dist/js/parent_window_context.js +6 -0
- package/dist/js/parent_window_effects.js +15 -0
- package/dist/js/parent_window_signals.js +25 -0
- package/dist/js/preact.mjs +316 -0
- package/dist/js/responsive.js +104 -0
- package/dist/js/server_actions.js +7 -0
- package/dist/js/server_effects.js +9 -0
- package/dist/js/server_indicator.js +52 -0
- package/dist/js/server_signals.js +10 -0
- package/dist/js/settings_actions.js +7 -0
- package/dist/js/settings_signals.js +2 -0
- package/dist/js/signals-core.mjs +339 -0
- package/dist/js/signals.mjs +202 -0
- package/dist/js/theme_actions.js +7 -0
- package/dist/js/theme_effects.js +6 -0
- package/dist/js/theme_signals.js +4 -0
- package/dist/js/toolbar_animation_setting.js +21 -0
- package/dist/js/toolbar_autoreload_setting.js +67 -0
- package/dist/js/toolbar_close_button.js +14 -0
- package/dist/js/toolbar_core.js +8 -1792
- package/dist/js/toolbar_injector.js +2 -4
- package/dist/js/toolbar_menu_overflow.js +81 -0
- package/dist/js/toolbar_notification_setting.js +72 -0
- package/dist/js/toolbar_open_actions.js +7 -0
- package/dist/js/toolbar_open_effects.js +4 -0
- package/dist/js/toolbar_open_signals.js +4 -0
- package/dist/js/toolbar_opening.js +65 -0
- package/dist/js/toolbar_overlay.js +69 -0
- package/dist/js/toolbar_settings.js +44 -0
- package/dist/js/toolbar_state_context.js +1 -0
- package/dist/js/toolbar_state_effects.js +8 -0
- package/dist/js/toolbar_state_signals.js +17 -0
- package/dist/js/toolbar_theme_setting.js +13 -0
- package/dist/js/toolbar_ui.js +20 -0
- package/dist/js/tooltip_actions.js +6 -0
- package/dist/js/variant.js +53 -0
- package/dist/jsenv_plugin_toolbar.js +3 -6
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const jsenvLogoSvgUrl = new URL("../other/jsenv_logo.svg", import.meta.url);
|
|
2
|
-
const injectToolbar = async ({
|
|
2
|
+
export const injectToolbar = async ({
|
|
3
3
|
toolbarUrl,
|
|
4
4
|
logLevel,
|
|
5
5
|
theme,
|
|
@@ -234,6 +234,4 @@ const iframeToLoadedPromise = iframe => {
|
|
|
234
234
|
};
|
|
235
235
|
iframe.addEventListener("load", onload, true);
|
|
236
236
|
});
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
export { injectToolbar };
|
|
237
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { closeAllTooltips } from "./tooltip_actions.js";
|
|
2
|
+
import { forceHideElement, removeForceHideElement, deactivateToolbarSection } from "./dom.js";
|
|
3
|
+
import { createHorizontalBreakpoint } from "./responsive.js";
|
|
4
|
+
const WINDOW_SMALL_WIDTH = 420;
|
|
5
|
+
export const initToolbarMenuOverflow = () => {
|
|
6
|
+
// apply responsive design on toolbar icons if needed + add listener on resize screen
|
|
7
|
+
// ideally we should listen breakpoint once, for now restore toolbar
|
|
8
|
+
const overflowMenuBreakpoint = createHorizontalBreakpoint(WINDOW_SMALL_WIDTH);
|
|
9
|
+
const handleOverflowMenuBreakpoint = () => {
|
|
10
|
+
responsiveToolbar(overflowMenuBreakpoint);
|
|
11
|
+
};
|
|
12
|
+
handleOverflowMenuBreakpoint();
|
|
13
|
+
overflowMenuBreakpoint.changed.listen(handleOverflowMenuBreakpoint);
|
|
14
|
+
document.querySelector("#menu_overflow_button").onclick = () => {
|
|
15
|
+
if (overflowMenuIsOpened()) {
|
|
16
|
+
closeOverflowMenu();
|
|
17
|
+
} else {
|
|
18
|
+
openOverflowMenu();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
const responsiveToolbar = overflowMenuBreakpoint => {
|
|
23
|
+
// close all tooltips in case opened
|
|
24
|
+
closeAllTooltips();
|
|
25
|
+
// close settings box in case opened
|
|
26
|
+
deactivateToolbarSection(document.querySelector("#settings"));
|
|
27
|
+
if (overflowMenuBreakpoint.isBelow()) {
|
|
28
|
+
enableOverflow();
|
|
29
|
+
} else {
|
|
30
|
+
disableOverflow();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
let moves = [];
|
|
34
|
+
const enableOverflow = () => {
|
|
35
|
+
// move elements from toolbar to overflow menu
|
|
36
|
+
const responsiveToolbarElements = document.querySelectorAll("[data-responsive-toolbar-element]");
|
|
37
|
+
const overflowMenu = document.querySelector("#menu_overflow");
|
|
38
|
+
|
|
39
|
+
// keep a placeholder element to know where to move them back
|
|
40
|
+
moves = Array.from(responsiveToolbarElements).map(element => {
|
|
41
|
+
const placeholder = document.createElement("div");
|
|
42
|
+
placeholder.style.display = "none";
|
|
43
|
+
placeholder.setAttribute("data-placeholder", "");
|
|
44
|
+
element.parentNode.replaceChild(placeholder, element);
|
|
45
|
+
overflowMenu.appendChild(element);
|
|
46
|
+
return {
|
|
47
|
+
element,
|
|
48
|
+
placeholder
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
document.querySelector("#toolbar").setAttribute("data-menu-overflow-enabled", "");
|
|
52
|
+
removeForceHideElement(document.querySelector("#menu_overflow_button"));
|
|
53
|
+
};
|
|
54
|
+
const disableOverflow = () => {
|
|
55
|
+
// close overflow menu in case it's open & unselect toggleOverflowMenu button in case it's selected
|
|
56
|
+
closeOverflowMenu();
|
|
57
|
+
deactivateToolbarSection(document.querySelector("#menu_overflow"));
|
|
58
|
+
moves.forEach(({
|
|
59
|
+
element,
|
|
60
|
+
placeholder
|
|
61
|
+
}) => {
|
|
62
|
+
placeholder.parentNode.replaceChild(element, placeholder);
|
|
63
|
+
});
|
|
64
|
+
moves = [];
|
|
65
|
+
document.querySelector("#toolbar").removeAttribute("data-menu-overflow-enabled");
|
|
66
|
+
forceHideElement(document.querySelector("#menu_overflow_button"));
|
|
67
|
+
};
|
|
68
|
+
const overflowMenuIsOpened = () => {
|
|
69
|
+
const toolbar = document.querySelector("#toolbar");
|
|
70
|
+
return toolbar.hasAttribute("data-menu-overflow-opened");
|
|
71
|
+
};
|
|
72
|
+
const openOverflowMenu = () => {
|
|
73
|
+
const toolbar = document.querySelector("#toolbar");
|
|
74
|
+
document.querySelector("#menu_overflow").setAttribute("data-animate", "");
|
|
75
|
+
toolbar.setAttribute("data-menu-overflow-opened", "");
|
|
76
|
+
};
|
|
77
|
+
const closeOverflowMenu = () => {
|
|
78
|
+
const toolbar = document.querySelector("#toolbar");
|
|
79
|
+
toolbar.removeAttribute("data-menu-overflow-opened");
|
|
80
|
+
document.querySelector("#menu_overflow").removeAttribute("data-animate");
|
|
81
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { notificationsEnabledSignal, notificationPermissionSignal } from "./notification_signals.js";
|
|
3
|
+
import { notificationAPIDetected } from "./notification_context.js";
|
|
4
|
+
import { enableNotifications, disableNotifications, requestPermission } from "./notification_actions.js";
|
|
5
|
+
import { enableVariant } from "./variant.js";
|
|
6
|
+
const notifCheckbox = document.querySelector("#toggle_notifs");
|
|
7
|
+
export const renderToolbarNotificationSetting = () => {
|
|
8
|
+
effect(() => {
|
|
9
|
+
const notificationsEnabled = notificationsEnabledSignal.value;
|
|
10
|
+
notifCheckbox.checked = notificationsEnabled;
|
|
11
|
+
});
|
|
12
|
+
effect(() => {
|
|
13
|
+
const notificationPermission = notificationPermissionSignal.value;
|
|
14
|
+
if (!notificationAPIDetected) {
|
|
15
|
+
applyNotificationNotAvailableEffects();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (notificationPermission === "default") {
|
|
19
|
+
applyNotificationDefaultEffects();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (notificationPermission === "denied") {
|
|
23
|
+
applyNotificationDeniedEffects();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (notificationPermission === "granted") {
|
|
27
|
+
applyNotificationGrantedEffects();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const applyNotificationNotAvailableEffects = () => {
|
|
33
|
+
const notifSetting = document.querySelector(".settings_notification");
|
|
34
|
+
notifSetting.setAttribute("data-disabled", "true");
|
|
35
|
+
notifSetting.setAttribute("title", `Notification not available in the browser`);
|
|
36
|
+
notifCheckbox.disabled = true;
|
|
37
|
+
};
|
|
38
|
+
const applyNotificationDefaultEffects = () => {
|
|
39
|
+
applyNotificationNOTGrantedEffects();
|
|
40
|
+
const notifSetting = document.querySelector(".settings_notification");
|
|
41
|
+
notifSetting.removeAttribute("data-disabled");
|
|
42
|
+
notifSetting.removeAttribute("title");
|
|
43
|
+
};
|
|
44
|
+
const applyNotificationDeniedEffects = () => {
|
|
45
|
+
applyNotificationNOTGrantedEffects();
|
|
46
|
+
const notifSetting = document.querySelector(".settings_notification");
|
|
47
|
+
notifSetting.setAttribute("data-disabled", "true");
|
|
48
|
+
notifSetting.setAttribute("title", `Notification denied`);
|
|
49
|
+
};
|
|
50
|
+
const applyNotificationGrantedEffects = () => {
|
|
51
|
+
enableVariant(document.querySelector(".notification_text"), {
|
|
52
|
+
notif_granted: "yes"
|
|
53
|
+
});
|
|
54
|
+
notifCheckbox.disabled = false;
|
|
55
|
+
notifCheckbox.onchange = () => {
|
|
56
|
+
if (notifCheckbox.checked) {
|
|
57
|
+
enableNotifications();
|
|
58
|
+
} else {
|
|
59
|
+
disableNotifications();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const applyNotificationNOTGrantedEffects = () => {
|
|
64
|
+
enableVariant(document.querySelector(".notification_text"), {
|
|
65
|
+
notif_granted: "no"
|
|
66
|
+
});
|
|
67
|
+
notifCheckbox.disabled = true;
|
|
68
|
+
notifCheckbox.checked = false;
|
|
69
|
+
document.querySelector("a.request_notification_permission").onclick = () => {
|
|
70
|
+
requestPermission();
|
|
71
|
+
};
|
|
72
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { signal } from "./signals.mjs";
|
|
2
|
+
import { paramsFromParentWindow } from "./parent_window_context.js";
|
|
3
|
+
import { stateFromLocalStorage } from "./toolbar_state_context.js";
|
|
4
|
+
export const openedSignal = signal(typeof stateFromLocalStorage.opened === "boolean" ? stateFromLocalStorage.opened : typeof paramsFromParentWindow.opened === "boolean" ? paramsFromParentWindow.opened : false);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { closeAllTooltips } from "./tooltip_actions.js";
|
|
3
|
+
import { animationsEnabledSignal } from "./animation_signals.js";
|
|
4
|
+
import { openedSignal } from "./toolbar_open_signals.js";
|
|
5
|
+
import { getToolbarIframe, setStyles } from "./dom.js";
|
|
6
|
+
import { startJavaScriptAnimation } from "./animation.js";
|
|
7
|
+
export const initToolbarOpening = () => {
|
|
8
|
+
effect(() => {
|
|
9
|
+
const opened = openedSignal.value;
|
|
10
|
+
if (opened) {
|
|
11
|
+
showToolbar();
|
|
12
|
+
} else {
|
|
13
|
+
hideToolbar();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
let restoreToolbarIframeParentStyles = () => {};
|
|
18
|
+
let restoreToolbarIframeStyles = () => {};
|
|
19
|
+
const hideToolbar = () => {
|
|
20
|
+
closeAllTooltips();
|
|
21
|
+
restoreToolbarIframeParentStyles();
|
|
22
|
+
restoreToolbarIframeStyles();
|
|
23
|
+
document.documentElement.removeAttribute("data-toolbar-visible");
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// (by the way it might be cool to have the toolbar auto show when)
|
|
27
|
+
// it has something to say (being disconnected from server)
|
|
28
|
+
const showToolbar = () => {
|
|
29
|
+
const animationsEnabled = animationsEnabledSignal.peek();
|
|
30
|
+
document.documentElement.setAttribute("data-toolbar-visible", "");
|
|
31
|
+
const toolbarIframe = getToolbarIframe();
|
|
32
|
+
const toolbarIframeParent = toolbarIframe.parentNode;
|
|
33
|
+
const parentWindow = window.parent;
|
|
34
|
+
const parentDocumentElement = parentWindow.document.compatMode === "CSS1Compat" ? parentWindow.document.documentElement : parentWindow.document.body;
|
|
35
|
+
const scrollYMax = parentDocumentElement.scrollHeight - parentWindow.innerHeight;
|
|
36
|
+
const scrollY = parentDocumentElement.scrollTop;
|
|
37
|
+
const scrollYRemaining = scrollYMax - scrollY;
|
|
38
|
+
setStyles(toolbarIframeParent, {
|
|
39
|
+
"transition-property": "padding-bottom",
|
|
40
|
+
"transition-duration": animationsEnabled ? "300ms" : "0s"
|
|
41
|
+
});
|
|
42
|
+
// maybe we should use js animation here because we would not conflict with css
|
|
43
|
+
restoreToolbarIframeParentStyles = setStyles(toolbarIframeParent, {
|
|
44
|
+
"scroll-padding-bottom": "40px",
|
|
45
|
+
// same here we should add 40px
|
|
46
|
+
"padding-bottom": "40px" // if there is already one we should add 40px
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
restoreToolbarIframeStyles = setStyles(toolbarIframe, {
|
|
50
|
+
height: "40px",
|
|
51
|
+
visibility: "visible"
|
|
52
|
+
});
|
|
53
|
+
if (scrollYRemaining < 40 && scrollYMax > 0) {
|
|
54
|
+
const scrollEnd = scrollY + 40;
|
|
55
|
+
startJavaScriptAnimation({
|
|
56
|
+
duration: 300,
|
|
57
|
+
onProgress: ({
|
|
58
|
+
progress
|
|
59
|
+
}) => {
|
|
60
|
+
const value = scrollY + (scrollEnd - scrollY) * progress;
|
|
61
|
+
parentDocumentElement.scrollTop = value;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { openedSignal } from "./toolbar_open_signals.js";
|
|
3
|
+
import { settingsOpenedSignal } from "./settings_signals.js";
|
|
4
|
+
import { closeSettings } from "./settings_actions.js";
|
|
5
|
+
import { closeAllTooltips } from "./tooltip_actions.js";
|
|
6
|
+
import { executionTooltipOpenedSignal } from "./execution_signals.js";
|
|
7
|
+
import { changesTooltipOpenedSignal } from "./changes_signals.js";
|
|
8
|
+
import { serverTooltipOpenedSignal } from "./server_signals.js";
|
|
9
|
+
import { getToolbarIframe, setStyles } from "./dom.js";
|
|
10
|
+
export const renderToolbarOverlay = () => {
|
|
11
|
+
const toolbarOverlay = document.querySelector("#toolbar_overlay");
|
|
12
|
+
toolbarOverlay.onclick = () => {
|
|
13
|
+
closeAllTooltips();
|
|
14
|
+
closeSettings();
|
|
15
|
+
};
|
|
16
|
+
effect(() => {
|
|
17
|
+
if (!window.parent) {
|
|
18
|
+
// can happen while parent iframe reloads
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const opened = openedSignal.value;
|
|
22
|
+
const settingsOpened = settingsOpenedSignal.value;
|
|
23
|
+
const executionTooltipOpened = executionTooltipOpenedSignal.value;
|
|
24
|
+
const changesTooltipOpened = changesTooltipOpenedSignal.value;
|
|
25
|
+
const serverTooltipOpened = serverTooltipOpenedSignal.value;
|
|
26
|
+
if (!opened) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (settingsOpened || executionTooltipOpened || changesTooltipOpened || serverTooltipOpened) {
|
|
30
|
+
enableIframeOverflowOnParentWindow();
|
|
31
|
+
} else {
|
|
32
|
+
disableIframeOverflowOnParentWindow();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
const enableIframeOverflowOnParentWindow = () => {
|
|
37
|
+
const iframe = getToolbarIframe();
|
|
38
|
+
const transitionDuration = iframe.style.transitionDuration;
|
|
39
|
+
setStyles(iframe, {
|
|
40
|
+
"height": "100%",
|
|
41
|
+
// we don't want to animate height transition
|
|
42
|
+
// but if it was enabled, we'll restore it afterwards
|
|
43
|
+
"transition-duration": "0ms"
|
|
44
|
+
});
|
|
45
|
+
if (transitionDuration) {
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
setStyles(iframe, {
|
|
48
|
+
"transition-duration": transitionDuration
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const disableIframeOverflowOnParentWindow = () => {
|
|
54
|
+
const iframe = getToolbarIframe();
|
|
55
|
+
const transitionDuration = iframe.style.transitionDuration;
|
|
56
|
+
setStyles(iframe, {
|
|
57
|
+
"height": "40px",
|
|
58
|
+
// we don't want to animate height transition
|
|
59
|
+
// but if it was enabled, we'll restore it afterwards
|
|
60
|
+
"transition-duration": "0ms"
|
|
61
|
+
});
|
|
62
|
+
if (transitionDuration) {
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
setStyles(iframe, {
|
|
65
|
+
"transition-duration": transitionDuration
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { settingsOpenedSignal } from "./settings_signals.js";
|
|
3
|
+
import { openSettings, closeSettings } from "./settings_actions.js";
|
|
4
|
+
import { enableVariant } from "./variant.js";
|
|
5
|
+
import { activateToolbarSection, deactivateToolbarSection } from "./dom.js";
|
|
6
|
+
import { renderToolbarAutoreloadSetting } from "./toolbar_autoreload_setting.js";
|
|
7
|
+
import { renderToolbarAnimationSetting } from "./toolbar_animation_setting.js";
|
|
8
|
+
import { renderToolbarNotificationSetting } from "./toolbar_notification_setting.js";
|
|
9
|
+
import { renderToolbarThemeSetting } from "./toolbar_theme_setting.js";
|
|
10
|
+
export const renderToolbarSettings = () => {
|
|
11
|
+
document.querySelector("#settings_open_button").onclick = toggleSettings;
|
|
12
|
+
document.querySelector("#settings_close_button").onclick = toggleSettings;
|
|
13
|
+
disableWarningStyle();
|
|
14
|
+
renderToolbarAutoreloadSetting();
|
|
15
|
+
renderToolbarAnimationSetting();
|
|
16
|
+
renderToolbarNotificationSetting();
|
|
17
|
+
renderToolbarThemeSetting();
|
|
18
|
+
effect(() => {
|
|
19
|
+
const settingsOpened = settingsOpenedSignal.value;
|
|
20
|
+
if (settingsOpened) {
|
|
21
|
+
activateToolbarSection(document.querySelector("#settings"));
|
|
22
|
+
} else {
|
|
23
|
+
deactivateToolbarSection(document.querySelector("#settings"));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const toggleSettings = () => {
|
|
28
|
+
const settingsOpened = settingsOpenedSignal.value;
|
|
29
|
+
if (settingsOpened) {
|
|
30
|
+
closeSettings();
|
|
31
|
+
} else {
|
|
32
|
+
openSettings();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
export const enableWarningStyle = () => {
|
|
36
|
+
enableVariant(document.querySelector("#settings_open_button"), {
|
|
37
|
+
has_warning: "yes"
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
export const disableWarningStyle = () => {
|
|
41
|
+
enableVariant(document.querySelector("#settings_open_button"), {
|
|
42
|
+
has_warning: "no"
|
|
43
|
+
});
|
|
44
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const stateFromLocalStorage = localStorage.hasOwnProperty("jsenv_toolbar") ? JSON.parse(localStorage.getItem("jsenv_toolbar")) : {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { toolbarStateSignal } from "./toolbar_state_signals.js";
|
|
3
|
+
import { sendEventToParent } from "./parent_window_actions.js";
|
|
4
|
+
effect(() => {
|
|
5
|
+
const toolbarState = toolbarStateSignal.value;
|
|
6
|
+
localStorage.setItem("jsenv_toolbar", JSON.stringify(toolbarState));
|
|
7
|
+
sendEventToParent("toolbar_state_change", toolbarState);
|
|
8
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { computed } from "./signals.mjs";
|
|
2
|
+
import { openedSignal } from "./toolbar_open_signals.js";
|
|
3
|
+
import { themeSignal } from "./theme_signals.js";
|
|
4
|
+
import { animationsEnabledSignal } from "./animation_signals.js";
|
|
5
|
+
import { notificationsEnabledSignal } from "./notification_signals.js";
|
|
6
|
+
export const toolbarStateSignal = computed(() => {
|
|
7
|
+
const opened = openedSignal.value;
|
|
8
|
+
const theme = themeSignal.value;
|
|
9
|
+
const animationsEnabled = animationsEnabledSignal.value;
|
|
10
|
+
const notificationsEnabled = notificationsEnabledSignal.value;
|
|
11
|
+
return {
|
|
12
|
+
opened,
|
|
13
|
+
theme,
|
|
14
|
+
animationsEnabled,
|
|
15
|
+
notificationsEnabled
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { themeSignal } from "./theme_signals.js";
|
|
2
|
+
import { switchToDefaultTheme, switchToLightTheme } from "./theme_actions.js";
|
|
3
|
+
export const renderToolbarThemeSetting = () => {
|
|
4
|
+
const checkbox = document.querySelector("#checkbox_dark_theme");
|
|
5
|
+
checkbox.checked = themeSignal.value === "dark";
|
|
6
|
+
checkbox.onchange = () => {
|
|
7
|
+
if (checkbox.checked) {
|
|
8
|
+
switchToDefaultTheme();
|
|
9
|
+
} else {
|
|
10
|
+
switchToLightTheme();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { initToolbarOpening } from "./toolbar_opening.js";
|
|
2
|
+
import { initToolbarMenuOverflow } from "./toolbar_menu_overflow.js";
|
|
3
|
+
import { renderToolbarOverlay } from "./toolbar_overlay.js";
|
|
4
|
+
import { renderDocumentIndexLink } from "./document_index_link.js";
|
|
5
|
+
import { renderDocumentExecutionIndicator } from "./document_execution_indicator.js";
|
|
6
|
+
import { renderChangesIndicator } from "./changes_indicator.js";
|
|
7
|
+
import { renderServerIndicator } from "./server_indicator.js";
|
|
8
|
+
import { renderToolbarSettings } from "./toolbar_settings.js";
|
|
9
|
+
import { renderToolbarCloseButton } from "./toolbar_close_button.js";
|
|
10
|
+
export const initToolbarUI = () => {
|
|
11
|
+
initToolbarOpening();
|
|
12
|
+
initToolbarMenuOverflow();
|
|
13
|
+
renderToolbarOverlay();
|
|
14
|
+
renderDocumentIndexLink();
|
|
15
|
+
renderDocumentExecutionIndicator();
|
|
16
|
+
renderChangesIndicator();
|
|
17
|
+
renderServerIndicator();
|
|
18
|
+
renderToolbarSettings();
|
|
19
|
+
renderToolbarCloseButton();
|
|
20
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const enableVariant = (rootNode, variables) => {
|
|
2
|
+
const nodesNotMatching = Array.from(rootNode.querySelectorAll(`[${attributeIndicatingACondition}]`));
|
|
3
|
+
nodesNotMatching.forEach(nodeNotMatching => {
|
|
4
|
+
const conditionAttributeValue = nodeNotMatching.getAttribute(attributeIndicatingACondition);
|
|
5
|
+
const matches = testCondition(conditionAttributeValue, variables);
|
|
6
|
+
if (matches) {
|
|
7
|
+
renameAttribute(nodeNotMatching, attributeIndicatingACondition, attributeIndicatingAMatch);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
const nodesMatching = Array.from(rootNode.querySelectorAll(`[${attributeIndicatingAMatch}]`));
|
|
11
|
+
nodesMatching.forEach(nodeMatching => {
|
|
12
|
+
const conditionAttributeValue = nodeMatching.getAttribute(attributeIndicatingAMatch);
|
|
13
|
+
const matches = testCondition(conditionAttributeValue, variables);
|
|
14
|
+
if (!matches) {
|
|
15
|
+
renameAttribute(nodeMatching, attributeIndicatingAMatch, attributeIndicatingACondition);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const testCondition = (conditionAttributeValue, variables) => {
|
|
20
|
+
const condition = parseCondition(conditionAttributeValue);
|
|
21
|
+
return Object.keys(variables).some(key => {
|
|
22
|
+
if (condition.key !== key) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// the condition do not specify a value, any value is ok
|
|
26
|
+
if (condition.value === undefined) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (condition.value === variables[key]) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const parseCondition = conditionAttributeValue => {
|
|
36
|
+
const colonIndex = conditionAttributeValue.indexOf(":");
|
|
37
|
+
if (colonIndex === -1) {
|
|
38
|
+
return {
|
|
39
|
+
key: conditionAttributeValue,
|
|
40
|
+
value: undefined
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
key: conditionAttributeValue.slice(0, colonIndex),
|
|
45
|
+
value: conditionAttributeValue.slice(colonIndex + 1)
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const attributeIndicatingACondition = `data-when`;
|
|
49
|
+
const attributeIndicatingAMatch = `data-when-active`;
|
|
50
|
+
const renameAttribute = (node, name, newName) => {
|
|
51
|
+
node.setAttribute(newName, node.getAttribute(name));
|
|
52
|
+
node.removeAttribute(name);
|
|
53
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { parseHtmlString, injectScriptNodeAsEarlyAsPossible, createHtmlNode
|
|
2
|
-
|
|
3
|
-
const jsenvPluginToolbar = ({
|
|
1
|
+
import { parseHtmlString, stringifyHtmlAst, injectScriptNodeAsEarlyAsPossible, createHtmlNode } from "@jsenv/ast";
|
|
2
|
+
export const jsenvPluginToolbar = ({
|
|
4
3
|
logLevel = "warn",
|
|
5
4
|
theme = "dark",
|
|
6
5
|
opened = false,
|
|
@@ -52,6 +51,4 @@ injectToolbar(${JSON.stringify({
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
};
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export { jsenvPluginToolbar };
|
|
54
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/plugin-toolbar",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"/src/"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@jsenv/ast": "1.4.
|
|
29
|
+
"@jsenv/ast": "1.4.9",
|
|
30
30
|
"@preact/signals": "1.1.2"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|