@finsemble/finsemble-ui 7.1.0 → 7.2.0-beta.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/package.json +8 -8
- package/react/assets/css/core/icons.css +1 -0
- package/react/assets/css/linkerWindow.css +1 -1
- package/react/assets/css/windowTitleBar.css +8 -1
- package/react/components/common/FinsembleToggleButtonBar.js +1 -1
- package/react/components/common/FinsembleToggleButtonBar.js.map +1 -1
- package/react/components/common/TimeSelect.js +10 -3
- package/react/components/common/TimeSelect.js.map +1 -1
- package/react/components/common/helpers.js +1 -0
- package/react/components/common/helpers.js.map +1 -1
- package/react/components/linker/LinkerMenu.js +22 -6
- package/react/components/linker/LinkerMenu.js.map +1 -1
- package/react/components/menu/MenuPortal.js +1 -1
- package/react/components/menu/MenuPortal.js.map +1 -1
- package/react/components/menu/MenuToggle.js +1 -1
- package/react/components/menu/MenuToggle.js.map +1 -1
- package/react/components/notifications/components/notificationsToasts/NotificationsToasts.js +2 -1
- package/react/components/notifications/components/notificationsToasts/NotificationsToasts.js.map +1 -1
- package/react/components/notifications/utils.js +5 -5
- package/react/components/notifications/utils.js.map +1 -1
- package/react/components/sdd/Application.js +0 -1
- package/react/components/sdd/Application.js.map +1 -1
- package/react/components/sdd/Export.js +1 -1
- package/react/components/sdd/Export.js.map +1 -1
- package/react/components/sdd/css/nav.css +0 -1
- package/react/components/sdd/tests/EditPreload.spec.js +35 -24
- package/react/components/sdd/tests/EditPreload.spec.js.map +1 -1
- package/react/components/sdd/tests/Export.spec.js +6 -0
- package/react/components/sdd/tests/Export.spec.js.map +1 -1
- package/react/components/sdd/tests/OptionalSettingsView.spec.js +55 -42
- package/react/components/sdd/tests/OptionalSettingsView.spec.js.map +1 -1
- package/react/components/shared/DefaultDropdownButton.js +5 -5
- package/react/components/shared/DefaultDropdownButton.js.map +1 -1
- package/react/components/singleInputDialog/SingleInputDialog.js +2 -0
- package/react/components/singleInputDialog/SingleInputDialog.js.map +1 -1
- package/react/components/toolbar/workspaceManagementMenu/stores/workspaceManagementMenuStore.d.ts +1 -1
- package/react/components/toolbar/workspaceManagementMenu/stores/workspaceManagementMenuStore.js +52 -40
- package/react/components/toolbar/workspaceManagementMenu/stores/workspaceManagementMenuStore.js.map +1 -1
- package/react/components/userPreferences/components/content/Workspaces.d.ts +2 -2
- package/react/components/userPreferences/components/content/Workspaces.js +69 -54
- package/react/components/userPreferences/components/content/Workspaces.js.map +1 -1
- package/react/components/userPreferences/components/general/ScheduledClose.js +3 -2
- package/react/components/userPreferences/components/general/ScheduledClose.js.map +1 -1
- package/react/components/windowTitleBar/WindowTitleBarShell.js +13 -13
- package/react/components/windowTitleBar/WindowTitleBarShell.js.map +1 -1
- package/react/components/windowTitleBar/components/left/LinkerButton.js +1 -1
- package/react/components/windowTitleBar/components/left/LinkerButton.js.map +1 -1
- package/react/components/yesNoDialog/YesNoDialog.js +1 -1
- package/react/components/yesNoDialog/YesNoDialog.js.map +1 -1
- package/react/hooks/useNotifications.js +9 -2
- package/react/hooks/useNotifications.js.map +1 -1
- package/react/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finsemble/finsemble-ui",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0-beta.0",
|
|
4
4
|
"description": "Ready-made React components to give you a head-start building your SmartDesktop.",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"build-storybook": "build-storybook"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@finsemble/finsemble-api": "
|
|
31
|
+
"@finsemble/finsemble-api": "file:../api/api.tgz",
|
|
32
32
|
"@q42/floating-focus-a11y": "^1.3.3",
|
|
33
33
|
"@reduxjs/toolkit": "^1.5.0",
|
|
34
34
|
"@svgr/webpack": "^5.5.0",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@types/react-relative-portal": "^1.8.1",
|
|
43
43
|
"async": "3.2.3",
|
|
44
44
|
"date-fns": "^2.25.0",
|
|
45
|
-
"immer": "9.0.
|
|
45
|
+
"immer": "9.0.14",
|
|
46
46
|
"lodash": "4.17.21",
|
|
47
47
|
"react-circular-progressbar": "^2.0.3",
|
|
48
48
|
"react-redux": "7.2.8",
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
"@babel/preset-env": "^7.16.0",
|
|
63
63
|
"@babel/preset-react": "^7.12.10",
|
|
64
64
|
"@babel/register": "^7.16.0",
|
|
65
|
-
"@storybook/addon-actions": "6.
|
|
66
|
-
"@storybook/addon-essentials": "6.
|
|
67
|
-
"@storybook/addon-links": "6.
|
|
68
|
-
"@storybook/react": "6.
|
|
65
|
+
"@storybook/addon-actions": "6.5.5",
|
|
66
|
+
"@storybook/addon-essentials": "6.5.7",
|
|
67
|
+
"@storybook/addon-links": "6.5.5",
|
|
68
|
+
"@storybook/react": "6.5.6",
|
|
69
69
|
"@types/enzyme": "^3.10.8",
|
|
70
70
|
"@types/react-syntax-highlighter": "15.5.1",
|
|
71
71
|
"@types/react-transition-group": "4.4.4",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"canvas": "^2.9.0",
|
|
77
77
|
"chai": "4.3.6",
|
|
78
78
|
"chokidar-cli": "3.0.0",
|
|
79
|
-
"concurrently": "7.1
|
|
79
|
+
"concurrently": "7.2.1",
|
|
80
80
|
"copyfiles": "2.4.1",
|
|
81
81
|
"core-js": "^3.15.2",
|
|
82
82
|
"depcheck": "^1.4.3",
|
|
@@ -123,6 +123,11 @@ body::after {
|
|
|
123
123
|
color: var(--titleBar-inactive-font-color);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
.fsbl-header div {
|
|
127
|
+
flex-direction: row;
|
|
128
|
+
flex-shrink: unset;
|
|
129
|
+
}
|
|
130
|
+
|
|
126
131
|
html.desktop-active .title-text {
|
|
127
132
|
background: transparent;
|
|
128
133
|
color: var(--titleBar-active-font-color);
|
|
@@ -163,6 +168,7 @@ html.desktop-active .fsbl-header-title[data-hover="true"] {
|
|
|
163
168
|
align-items: center;
|
|
164
169
|
justify-content: flex-start;
|
|
165
170
|
display: flex;
|
|
171
|
+
color: aqua;
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
.fsbl-header-center {
|
|
@@ -306,6 +312,7 @@ html.desktop-active .fsbl-icon-highlighted {
|
|
|
306
312
|
padding-bottom: 4px;
|
|
307
313
|
margin-bottom: 4px;
|
|
308
314
|
color: var(--titleBar-linker-font-color);
|
|
315
|
+
display: block;
|
|
309
316
|
}
|
|
310
317
|
|
|
311
318
|
.linkerContainer {
|
|
@@ -477,7 +484,7 @@ html.desktop-active .fsbl-active-tab .fsbl-tab-title {
|
|
|
477
484
|
color: var(--titlebar-tab-active-font-color);
|
|
478
485
|
}
|
|
479
486
|
|
|
480
|
-
.fsbl-tab-close {
|
|
487
|
+
div.fsbl-tab-close {
|
|
481
488
|
font-size: 8px;
|
|
482
489
|
padding: 0 10px;
|
|
483
490
|
visibility: hidden;
|
|
@@ -21,7 +21,7 @@ export const FinsembleToggleButtonBar = ({ selected, options, onChange, enabled
|
|
|
21
21
|
(_b = buttons[fromKey + direction]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
22
22
|
};
|
|
23
23
|
return (React.createElement("span", { className: "finsembleToggle" },
|
|
24
|
-
React.createElement("span", { className: "toggle-text-label-wrapper", role: "radiogroup", ref: buttonList }, options.map((option, key) => (React.createElement("span", { key: key, className: `toggle-text-label ${enabled ? "" : "disabled"} toggle-${key}`, role: "radio", "aria-checked": selected === option.value, tabIndex: selected === option.value ? 0 : -1, onClick: () => {
|
|
24
|
+
React.createElement("span", { className: "toggle-text-label-wrapper", role: "radiogroup", ref: buttonList }, options.map((option, key) => (React.createElement("span", { key: key, className: `toggle-text-label ${enabled ? "" : "disabled"} toggle-${key}`, role: "radio", "aria-checked": selected === option.value, tabIndex: selected === option.value && enabled ? 0 : -1, onClick: () => {
|
|
25
25
|
enabled && onChange(option.value);
|
|
26
26
|
}, onKeyDown: (e) => {
|
|
27
27
|
switch (e.key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FinsembleToggleButtonBar.js","sourceRoot":"","sources":["../../../src/components/common/FinsembleToggleButtonBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,2BAA2B,CAAC;AAanC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EACxC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,GAAG,IAAI,GACiB,EAAE,EAAE;IACnC,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEhD,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,SAAiB,EAAE,EAAE;;QAC3D,MAAM,OAAO,GAAG,MAAA,UAAU,CAAC,OAAO,0CAAE,gBAAgB,CAAC,gBAAgB,CAAwC,CAAC;QAC9G,IAAI,OAAO,KAAK,SAAS,EAAE;YAC1B,OAAO;SACP;QAED,IAAI,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE;YAC/B,OAAO;SACP;QAED,IAAI,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;QACjC,IAAI,MAAM,GAAG,CAAC,EAAE;YACf,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;SAC5B;aAAM,IAAI,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE;YACpC,MAAM,GAAG,CAAC,CAAC;SACX;QAED,MAAA,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,0CAAE,KAAK,EAAE,CAAC;IACvC,CAAC,CAAC;IAEF,OAAO,CACN,8BAAM,SAAS,EAAC,iBAAiB;QAChC,8BAAM,SAAS,EAAC,2BAA2B,EAAC,IAAI,EAAC,YAAY,EAAC,GAAG,EAAE,UAAU,IAC3E,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAC7B,8BACC,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,qBAAqB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,WAAW,GAAG,EAAE,EACzE,IAAI,EAAC,OAAO,kBACE,QAAQ,KAAK,MAAM,CAAC,KAAK,EACvC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"FinsembleToggleButtonBar.js","sourceRoot":"","sources":["../../../src/components/common/FinsembleToggleButtonBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,2BAA2B,CAAC;AAanC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EACxC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,GAAG,IAAI,GACiB,EAAE,EAAE;IACnC,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEhD,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,SAAiB,EAAE,EAAE;;QAC3D,MAAM,OAAO,GAAG,MAAA,UAAU,CAAC,OAAO,0CAAE,gBAAgB,CAAC,gBAAgB,CAAwC,CAAC;QAC9G,IAAI,OAAO,KAAK,SAAS,EAAE;YAC1B,OAAO;SACP;QAED,IAAI,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE;YAC/B,OAAO;SACP;QAED,IAAI,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;QACjC,IAAI,MAAM,GAAG,CAAC,EAAE;YACf,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;SAC5B;aAAM,IAAI,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE;YACpC,MAAM,GAAG,CAAC,CAAC;SACX;QAED,MAAA,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,0CAAE,KAAK,EAAE,CAAC;IACvC,CAAC,CAAC;IAEF,OAAO,CACN,8BAAM,SAAS,EAAC,iBAAiB;QAChC,8BAAM,SAAS,EAAC,2BAA2B,EAAC,IAAI,EAAC,YAAY,EAAC,GAAG,EAAE,UAAU,IAC3E,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAC7B,8BACC,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,qBAAqB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,WAAW,GAAG,EAAE,EACzE,IAAI,EAAC,OAAO,kBACE,QAAQ,KAAK,MAAM,CAAC,KAAK,EACvC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACvD,OAAO,EAAE,GAAG,EAAE;gBACb,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC,EACD,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gBAChB,QAAQ,CAAC,CAAC,GAAG,EAAE;oBACd,KAAK,WAAW,CAAC,CAAC;wBACjB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;wBACtB,MAAM;qBACN;oBACD,KAAK,YAAY,CAAC,CAAC;wBAClB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;wBACrB,MAAM;qBACN;oBACD,KAAK,OAAO,CAAC,CAAC;wBACb,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;qBAClC;oBACD,OAAO,CAAC,CAAC;qBACR;iBACD;YACF,CAAC,IAEA,MAAM,CAAC,KAAK,CACP,CACP,CAAC,CACI,CACD,CACP,CAAC;AACH,CAAC,CAAC","sourcesContent":["import React, { useRef } from \"react\";\nimport \"./css/FinsembleToggle.css\";\n\nexport interface FinsembleToggleButtonBarProps {\n\tlabel?: string;\n\tselected: any; // <T>\n\toptions: {\n\t\tlabel: string | React.ReactChild;\n\t\tvalue: any; // <T>\n\t}[];\n\tonChange: (newSelected: any /* <T> */) => void;\n\tenabled?: boolean;\n}\n\nexport const FinsembleToggleButtonBar = ({\n\tselected,\n\toptions,\n\tonChange,\n\tenabled = true,\n}: FinsembleToggleButtonBarProps) => {\n\tconst buttonList = useRef<HTMLDivElement>(null);\n\n\tconst changeButton = (fromKey: number, direction: 1 | -1) => {\n\t\tconst buttons = buttonList.current?.querySelectorAll(\"[role='radio']\") as NodeListOf<HTMLElement> | undefined;\n\t\tif (buttons === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (fromKey === buttons.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet newKey = fromKey + direction;\n\t\tif (newKey < 0) {\n\t\t\tnewKey = buttons.length - 1;\n\t\t} else if (newKey >= buttons.length) {\n\t\t\tnewKey = 0;\n\t\t}\n\n\t\tbuttons[fromKey + direction]?.focus();\n\t};\n\n\treturn (\n\t\t<span className=\"finsembleToggle\">\n\t\t\t<span className=\"toggle-text-label-wrapper\" role=\"radiogroup\" ref={buttonList}>\n\t\t\t\t{options.map((option, key) => (\n\t\t\t\t\t<span\n\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\tclassName={`toggle-text-label ${enabled ? \"\" : \"disabled\"} toggle-${key}`}\n\t\t\t\t\t\trole=\"radio\"\n\t\t\t\t\t\taria-checked={selected === option.value}\n\t\t\t\t\t\ttabIndex={selected === option.value && enabled ? 0 : -1}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tenabled && onChange(option.value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\tswitch (e.key) {\n\t\t\t\t\t\t\t\tcase \"ArrowLeft\": {\n\t\t\t\t\t\t\t\t\tchangeButton(key, -1);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcase \"ArrowRight\": {\n\t\t\t\t\t\t\t\t\tchangeButton(key, 1);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcase \"Enter\": {\n\t\t\t\t\t\t\t\t\tenabled && onChange(option.value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{option.label}\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\t\t\t</span>\n\t\t</span>\n\t);\n};\n"]}
|
|
@@ -118,10 +118,17 @@ export const TimeSelect = ({ initialTime, enabled = true, label = "Time:", onCha
|
|
|
118
118
|
return time.hour;
|
|
119
119
|
}
|
|
120
120
|
};
|
|
121
|
+
const getDisplayMinute = () => {
|
|
122
|
+
if (time.minute === 0)
|
|
123
|
+
return "00";
|
|
124
|
+
else {
|
|
125
|
+
return String(time.minute).length === 1 ? `0${time.minute}` : time.minute;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
121
128
|
return (React.createElement("div", { className: wrapClasses, style: { display: "flex" } },
|
|
122
129
|
React.createElement("span", { className: "time-select-label" }, label),
|
|
123
130
|
React.createElement("div", { className: "row-section", style: { width: "10px", marginRight: "40px" } },
|
|
124
|
-
React.createElement(DefaultDropdownButton, { classNames: "push-right", allowEmpty: false, caretLocation: "right", buttonOptions: hourOptions, defaultSelection: {
|
|
131
|
+
React.createElement(DefaultDropdownButton, { classNames: "push-right", allowEmpty: false, caretLocation: "right", buttonOptions: hourOptions, buttonLabel: `Hour, ${getDisplayHour().toString()}`, defaultSelection: {
|
|
125
132
|
optionLabel: getDisplayHour().toString(),
|
|
126
133
|
optionValue: getDisplayHour(),
|
|
127
134
|
clickHandler: () => {
|
|
@@ -130,8 +137,8 @@ export const TimeSelect = ({ initialTime, enabled = true, label = "Time:", onCha
|
|
|
130
137
|
}, enabled: enabled })),
|
|
131
138
|
React.createElement("div", { className: "row-section", style: { marginLeft: 30, marginRight: 10, marginTop: 5 } }, "\u00A0:\u00A0"),
|
|
132
139
|
React.createElement("div", { style: { width: "10px", marginRight: "65px" } },
|
|
133
|
-
React.createElement(DefaultDropdownButton, { classNames: "push-right", allowEmpty: false, caretLocation: "right", buttonOptions: minuteOptions, defaultSelection: {
|
|
134
|
-
optionLabel: (
|
|
140
|
+
React.createElement(DefaultDropdownButton, { classNames: "push-right", allowEmpty: false, caretLocation: "right", buttonOptions: minuteOptions, buttonLabel: `Minute, ${getDisplayMinute()}`, defaultSelection: {
|
|
141
|
+
optionLabel: getDisplayMinute(),
|
|
135
142
|
optionValue: time.minute,
|
|
136
143
|
clickHandler: () => {
|
|
137
144
|
setMinute(time.minute);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeSelect.js","sourceRoot":"","sources":["../../../src/components/common/TimeSelect.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport \"./css/time-select.css\";\nimport DefaultDropdownButton from \"../shared/DefaultDropdownButton\";\n\nexport interface TimeSelectProps {\n\tlabel?: string;\n\tinitialTime?: TimeSelectTime;\n\tonChange?: (time: TimeSelectTime) => void;\n\tenabled?: boolean;\n\tclassName?: string;\n\tminuteInterval?: number;\n}\n\nexport type TimeSelectTime = {\n\thour: number;\n\tminute: number;\n\tmeridiem?: string;\n};\n\nconst DEFAULT_VALUE: TimeSelectTime = {\n\thour: 4,\n\tminute: 0,\n\tmeridiem: \"AM\",\n};\n\nexport const TimeSelect: React.FunctionComponent<TimeSelectProps> = ({\n\tinitialTime,\n\tenabled = true,\n\tlabel = \"Time:\",\n\tonChange,\n\tclassName = \"\",\n\tminuteInterval = 15,\n}) => {\n\t/**\n\t * Prevents change event from triggering on initial setup\n\t */\n\tconst [changed, setChanged] = useState<boolean>(false);\n\tconst [time, setTime] = useState<TimeSelectTime>(initialTime ?? DEFAULT_VALUE);\n\n\tlet wrapClasses = `time-select ${className}`;\n\tif (!enabled) {\n\t\twrapClasses = `${wrapClasses} disabled-time-select`;\n\t}\n\n\t// Create an array 1-12.\n\tlet HOURS: Array<number> = [];\n\tfor (let i = 1; i < 13; i++) {\n\t\tHOURS.push(i);\n\t}\n\n\tlet MINUTES: any = [\"00\"];\n\tfor (let i = 1; i < 60; i++) {\n\t\tif (i % minuteInterval == 0) {\n\t\t\tMINUTES.push(i);\n\t\t}\n\t}\n\n\t/**\n\t * This method will transform 8 PM into 20:00. It also handles when the user changes the meridiem.\n\t * e.g., 8PM (20) => 8AM (8).\n\t * Set the minute, then set the 'finsemble.scheduledRestart' preference via the method on the Actions object.\n\t * @param {event} e\n\t */\n\tconst setHour = (e: any) => {\n\t\tlet hour = Number(e);\n\t\tif (hour < 12 && time.meridiem === \"PM\") {\n\t\t\thour = hour + 12;\n\t\t} else if (hour > 12 && time.meridiem === \"AM\") {\n\t\t\thour = hour - 12;\n\t\t} else if (time.meridiem === \"AM\" && hour === 12) {\n\t\t\thour = 0;\n\t\t}\n\n\t\tsetTime({ ...time, hour });\n\t};\n\n\t/**\n\t * Set the minute, then set the 'finsemble.scheduledRestart' preference via the method on the Actions object.\n\t * @param {event} e\n\t */\n\tconst setMinute = (e: any) => {\n\t\tconst minute = Number(e);\n\t\ttime.minute = minute;\n\t\tsetTime({ ...time, minute });\n\t};\n\n\t/**\n\t * Sets the meridiem for the time (AM or PM). This will trigger setHour to be called in a hook\n\t * @param {event} e\n\t */\n\tconst setMeridiem = (e: any) => {\n\t\tconst meridiem = e;\n\t\tsetTime({ ...time, meridiem });\n\t};\n\n\tconst correctMeridiem = () => {\n\t\tif (!time.meridiem) {\n\t\t\tlet localMeridiem = \"AM\";\n\t\t\tif (time.hour > 12 || (time.hour == 0 && time.minute == 0)) {\n\t\t\t\tlocalMeridiem = \"PM\";\n\t\t\t}\n\t\t\tsetMeridiem(localMeridiem);\n\t\t}\n\t};\n\n\t/**\n\t * The meridiem has changed, update the hour\n\t */\n\tuseEffect(() => {\n\t\tsetHour(time.hour);\n\t}, [time.meridiem]);\n\n\t/**\n\t * Call on change when the hour and minute values have changed\n\t */\n\tuseEffect(() => {\n\t\tcorrectMeridiem();\n\t\tif (enabled && onChange && changed) {\n\t\t\tonChange(time);\n\t\t}\n\t}, [time.hour, time.minute]);\n\n\tconst hourOptions: Array<any> = HOURS.map((hour: number) => {\n\t\treturn {\n\t\t\toptionLabel: hour,\n\t\t\toptionValue: hour,\n\t\t\tclickHandler: () => {\n\t\t\t\tsetChanged(true);\n\t\t\t\tsetHour(hour);\n\t\t\t},\n\t\t};\n\t});\n\tconst minuteOptions: Array<any> = MINUTES.map((minute: any) => {\n\t\treturn {\n\t\t\toptionLabel: minute,\n\t\t\toptionValue: minute,\n\t\t\tclickHandler: () => {\n\t\t\t\tsetChanged(true);\n\t\t\t\tsetMinute(minute);\n\t\t\t},\n\t\t};\n\t});\n\n\tconst getDisplayHour = () => {\n\t\tif (time.meridiem === \"AM\" && time.hour === 0) {\n\t\t\treturn 12;\n\t\t} else if (time.meridiem === \"PM\" && time.hour > 12) {\n\t\t\treturn time.hour - 12;\n\t\t} else {\n\t\t\treturn time.hour;\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className={wrapClasses} style={{ display: \"flex\" }}>\n\t\t\t<span className=\"time-select-label\">{label}</span>\n\t\t\t{/* HOURS */}\n\t\t\t<div className=\"row-section\" style={{ width: \"10px\", marginRight: \"40px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={hourOptions}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: getDisplayHour().toString(),\n\t\t\t\t\t\toptionValue: getDisplayHour(),\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetHour(getDisplayHour());\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"row-section\" style={{ marginLeft: 30, marginRight: 10, marginTop: 5 }}>\n\t\t\t\t : \n\t\t\t</div>\n\t\t\t{/* MINUTES */}\n\t\t\t<div style={{ width: \"10px\", marginRight: \"65px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={minuteOptions}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: (time.minute === 0 ? \"00\" : time.minute) as string,\n\t\t\t\t\t\toptionValue: time.minute,\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetMinute(time.minute);\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t \n\t\t\t{/* MERIDIEM */}\n\t\t\t<div className=\"row-section\" style={{ width: \"10px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptionLabel: \"AM\",\n\t\t\t\t\t\t\toptionValue: \"AM\",\n\t\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\t\tsetChanged(true);\n\t\t\t\t\t\t\t\tsetMeridiem(\"AM\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptionLabel: \"PM\",\n\t\t\t\t\t\t\toptionValue: \"PM\",\n\t\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\t\tsetChanged(true);\n\t\t\t\t\t\t\t\tsetMeridiem(\"PM\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t]}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: time.meridiem as string,\n\t\t\t\t\t\toptionValue: time.meridiem,\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetHour(time.meridiem);\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"TimeSelect.js","sourceRoot":"","sources":["../../../src/components/common/TimeSelect.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport \"./css/time-select.css\";\nimport DefaultDropdownButton from \"../shared/DefaultDropdownButton\";\n\nexport interface TimeSelectProps {\n\tlabel?: string;\n\tinitialTime?: TimeSelectTime;\n\tonChange?: (time: TimeSelectTime) => void;\n\tenabled?: boolean;\n\tclassName?: string;\n\tminuteInterval?: number;\n}\n\nexport type TimeSelectTime = {\n\thour: number;\n\tminute: number;\n\tmeridiem?: string;\n};\n\nconst DEFAULT_VALUE: TimeSelectTime = {\n\thour: 4,\n\tminute: 0,\n\tmeridiem: \"AM\",\n};\n\nexport const TimeSelect: React.FunctionComponent<TimeSelectProps> = ({\n\tinitialTime,\n\tenabled = true,\n\tlabel = \"Time:\",\n\tonChange,\n\tclassName = \"\",\n\tminuteInterval = 15,\n}) => {\n\t/**\n\t * Prevents change event from triggering on initial setup\n\t */\n\tconst [changed, setChanged] = useState<boolean>(false);\n\tconst [time, setTime] = useState<TimeSelectTime>(initialTime ?? DEFAULT_VALUE);\n\n\tlet wrapClasses = `time-select ${className}`;\n\tif (!enabled) {\n\t\twrapClasses = `${wrapClasses} disabled-time-select`;\n\t}\n\n\t// Create an array 1-12.\n\tlet HOURS: Array<number> = [];\n\tfor (let i = 1; i < 13; i++) {\n\t\tHOURS.push(i);\n\t}\n\n\tlet MINUTES: any = [\"00\"];\n\tfor (let i = 1; i < 60; i++) {\n\t\tif (i % minuteInterval == 0) {\n\t\t\tMINUTES.push(i);\n\t\t}\n\t}\n\n\t/**\n\t * This method will transform 8 PM into 20:00. It also handles when the user changes the meridiem.\n\t * e.g., 8PM (20) => 8AM (8).\n\t * Set the minute, then set the 'finsemble.scheduledRestart' preference via the method on the Actions object.\n\t * @param {event} e\n\t */\n\tconst setHour = (e: any) => {\n\t\tlet hour = Number(e);\n\t\tif (hour < 12 && time.meridiem === \"PM\") {\n\t\t\thour = hour + 12;\n\t\t} else if (hour > 12 && time.meridiem === \"AM\") {\n\t\t\thour = hour - 12;\n\t\t} else if (time.meridiem === \"AM\" && hour === 12) {\n\t\t\thour = 0;\n\t\t}\n\n\t\tsetTime({ ...time, hour });\n\t};\n\n\t/**\n\t * Set the minute, then set the 'finsemble.scheduledRestart' preference via the method on the Actions object.\n\t * @param {event} e\n\t */\n\tconst setMinute = (e: any) => {\n\t\tconst minute = Number(e);\n\t\ttime.minute = minute;\n\t\tsetTime({ ...time, minute });\n\t};\n\n\t/**\n\t * Sets the meridiem for the time (AM or PM). This will trigger setHour to be called in a hook\n\t * @param {event} e\n\t */\n\tconst setMeridiem = (e: any) => {\n\t\tconst meridiem = e;\n\t\tsetTime({ ...time, meridiem });\n\t};\n\n\tconst correctMeridiem = () => {\n\t\tif (!time.meridiem) {\n\t\t\tlet localMeridiem = \"AM\";\n\t\t\tif (time.hour > 12 || (time.hour == 0 && time.minute == 0)) {\n\t\t\t\tlocalMeridiem = \"PM\";\n\t\t\t}\n\t\t\tsetMeridiem(localMeridiem);\n\t\t}\n\t};\n\n\t/**\n\t * The meridiem has changed, update the hour\n\t */\n\tuseEffect(() => {\n\t\tsetHour(time.hour);\n\t}, [time.meridiem]);\n\n\t/**\n\t * Call on change when the hour and minute values have changed\n\t */\n\tuseEffect(() => {\n\t\tcorrectMeridiem();\n\t\tif (enabled && onChange && changed) {\n\t\t\tonChange(time);\n\t\t}\n\t}, [time.hour, time.minute]);\n\n\tconst hourOptions: Array<any> = HOURS.map((hour: number) => {\n\t\treturn {\n\t\t\toptionLabel: hour,\n\t\t\toptionValue: hour,\n\t\t\tclickHandler: () => {\n\t\t\t\tsetChanged(true);\n\t\t\t\tsetHour(hour);\n\t\t\t},\n\t\t};\n\t});\n\tconst minuteOptions: Array<any> = MINUTES.map((minute: any) => {\n\t\treturn {\n\t\t\toptionLabel: minute,\n\t\t\toptionValue: minute,\n\t\t\tclickHandler: () => {\n\t\t\t\tsetChanged(true);\n\t\t\t\tsetMinute(minute);\n\t\t\t},\n\t\t};\n\t});\n\n\tconst getDisplayHour = () => {\n\t\tif (time.meridiem === \"AM\" && time.hour === 0) {\n\t\t\treturn 12;\n\t\t} else if (time.meridiem === \"PM\" && time.hour > 12) {\n\t\t\treturn time.hour - 12;\n\t\t} else {\n\t\t\treturn time.hour;\n\t\t}\n\t};\n\n\tconst getDisplayMinute = () => {\n\t\tif (time.minute === 0) return \"00\";\n\t\telse {\n\t\t\treturn String(time.minute).length === 1 ? `0${time.minute}` : time.minute;\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className={wrapClasses} style={{ display: \"flex\" }}>\n\t\t\t<span className=\"time-select-label\">{label}</span>\n\t\t\t{/* HOURS */}\n\t\t\t<div className=\"row-section\" style={{ width: \"10px\", marginRight: \"40px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={hourOptions}\n\t\t\t\t\tbuttonLabel={`Hour, ${getDisplayHour().toString()}`}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: getDisplayHour().toString(),\n\t\t\t\t\t\toptionValue: getDisplayHour(),\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetHour(getDisplayHour());\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"row-section\" style={{ marginLeft: 30, marginRight: 10, marginTop: 5 }}>\n\t\t\t\t : \n\t\t\t</div>\n\t\t\t{/* MINUTES */}\n\t\t\t<div style={{ width: \"10px\", marginRight: \"65px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={minuteOptions}\n\t\t\t\t\tbuttonLabel={`Minute, ${getDisplayMinute() as string}`}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: getDisplayMinute() as string,\n\t\t\t\t\t\toptionValue: time.minute,\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetMinute(time.minute);\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t \n\t\t\t{/* MERIDIEM */}\n\t\t\t<div className=\"row-section\" style={{ width: \"10px\" }}>\n\t\t\t\t<DefaultDropdownButton\n\t\t\t\t\tclassNames={\"push-right\"}\n\t\t\t\t\tallowEmpty={false}\n\t\t\t\t\tcaretLocation={\"right\"}\n\t\t\t\t\tbuttonOptions={[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptionLabel: \"AM\",\n\t\t\t\t\t\t\toptionValue: \"AM\",\n\t\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\t\tsetChanged(true);\n\t\t\t\t\t\t\t\tsetMeridiem(\"AM\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toptionLabel: \"PM\",\n\t\t\t\t\t\t\toptionValue: \"PM\",\n\t\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\t\tsetChanged(true);\n\t\t\t\t\t\t\t\tsetMeridiem(\"PM\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t]}\n\t\t\t\t\tdefaultSelection={{\n\t\t\t\t\t\toptionLabel: time.meridiem as string,\n\t\t\t\t\t\toptionValue: time.meridiem,\n\t\t\t\t\t\tclickHandler: () => {\n\t\t\t\t\t\t\tsetHour(time.meridiem);\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tenabled={enabled}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/components/common/helpers.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { FileInputUploadCb } from \"./FileInput\";\nimport { Story } from \"@storybook/react/types-6-0\";\n\nimport { SDServerInfo } from \"../../types/smartDesktopDesignerTypes\";\nimport { Provider } from \"react-redux\";\nimport { createStore } from \"../../store\";\n\nexport const uploadFunction: FileInputUploadCb = (fileObject: File) =>\n\tnew Promise((resolve) => {\n\t\tresolve({\n\t\t\terr: \"\",\n\t\t\tpath: fileObject.name,\n\t\t});\n\t});\n\nexport const initFSBL = (windowObject?: any) => {\n\t// Poor man's global that can take any appendage\n\tconst globalAsAny: any = global;\n\n\tif (!windowObject) {\n\t\twindowObject = globalAsAny.window = {} as any;\n\t} else {\n\t\twindowObject = window;\n\n\t\tsetTimeout(() => {\n\t\t\tconst event = window.document.createEvent(\"Event\");\n\n\t\t\tevent?.initEvent(\"FSBLReady\", true, true);\n\n\t\t\twindow.dispatchEvent(event);\n\t\t});\n\t}\n\n\tglobalAsAny.FSBL = windowObject.FSBL = {\n\t\taddEventListener: (name: String, callback: () => void) => {\n\t\t\tcallback();\n\t\t},\n\t\tgetFSBLInfo: () =>\n\t\t\tnew Promise((resolve) => {\n\t\t\t\tresolve({\n\t\t\t\t\tFSBLVersion: \"1.0.0\",\n\t\t\t\t});\n\t\t\t}),\n\t\tClients: {\n\t\t\tTmpSmartDesktopClient: {\n\t\t\t\tcheckValidURL(url: string) {\n\t\t\t\t\tif (url.length === 0) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn /^https?:\\/\\/[^\\s]+$/.test(url);\n\t\t\t\t},\n\t\t\t\tcheckValidProjectName(name: string) {\n\t\t\t\t\treturn /^[a-zA-Z0-9 \\-_.]{1,}$/.test(name) && /[a-zA-Z0-9]{1,}/.test(name);\n\t\t\t\t},\n\t\t\t} as unknown,\n\t\t\tConfigClient: {\n\t\t\t\tsetPreference: () => {},\n\t\t\t\tgetValues: () => {},\n\t\t\t\tgetPreferences: () => {},\n\t\t\t},\n\t\t\tDialogManager: {\n\t\t\t\tspawnDialog: (obj1: any) => {\n\t\t\t\t\tconsole.table(obj1);\n\t\t\t\t},\n\t\t\t\tregisterDialogCallback: () => {},\n\t\t\t\trespondToOpener: () => {},\n\t\t\t},\n\t\t\tLauncherClient: {\n\t\t\t\tshowWindow: () => {},\n\t\t\t},\n\t\t\tLogger: {\n\t\t\t\tlog: () => {},\n\t\t\t\terror: () => {},\n\t\t\t\tsystem: {\n\t\t\t\t\tdebug: () => {},\n\t\t\t\t\tlog: () => {},\n\t\t\t\t\terror: () => {},\n\t\t\t\t\tverbose: () => {},\n\t\t\t\t\tdeprecated: () => {},\n\t\t\t\t},\n\t\t\t},\n\t\t\tRouterClient: {\n\t\t\t\ttransmit: () => {},\n\t\t\t\taddListener: () => {},\n\t\t\t\tsubscribe: () => {},\n\t\t\t},\n\t\t\tSearchClient: {\n\t\t\t\tinvokeItemAction: () => {},\n\t\t\t},\n\t\t\tStorageClient: {\n\t\t\t\tsave: () => {},\n\t\t\t\tclearCache: () => {},\n\t\t\t},\n\t\t\tWindowClient: {\n\t\t\t\tfitToDOM: () => {},\n\t\t\t},\n\t\t\tWorkspaceClient: {\n\t\t\t\tbringWindowsToFront: () => {},\n\t\t\t\tautoArrange: () => {},\n\t\t\t\tminimizeAll: () => {},\n\t\t\t\tactiveWorkspace: {\n\t\t\t\t\tname: \" \",\n\t\t\t\t},\n\t\t\t\tgetWorkspaceDefinition: (obj: Object, cb: Function) => {\n\t\t\t\t\tcb(null, null);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tonShutdown: () => {},\n\t\tSystem: {\n\t\t\tgetSDServerInfo: () =>\n\t\t\t\tnew Promise((resolve) => {\n\t\t\t\t\tresolve({} as SDServerInfo);\n\t\t\t\t}),\n\t\t},\n\t\tSystemManagerClient: {\n\t\t\tpublishCheckpointState: () => {},\n\t\t},\n\t} as any;\n\n\tglobalAsAny.FSBL.Clients = {\n\t\t...globalAsAny.FSBL.Clients,\n\t\tWindowClient: {\n\t\t\tfitToDOM: () => {},\n\t\t} as any,\n\t};\n\n\tglobalAsAny.finsembleWindow = windowObject.finsembleWindow = {\n\t\tsetAlwaysOnTop: () => {},\n\t\taddEventListener: () => {},\n\t\tremoveEventListener: () => {},\n\t};\n};\n\nexport function createStory<T>(Component: Function, args: T) {\n\tconst template: Story<T> = (props: T) => {\n\t\tinitFSBL(window);\n\n\t\treturn (\n\t\t\t<Provider store={createStore()}>\n\t\t\t\t<Component {...{ ...args, ...props }} />\n\t\t\t</Provider>\n\t\t);\n\t};\n\n\ttemplate.args = args;\n\n\treturn template;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/components/common/helpers.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { FileInputUploadCb } from \"./FileInput\";\nimport { Story } from \"@storybook/react/types-6-0\";\n\nimport { SDServerInfo } from \"../../types/smartDesktopDesignerTypes\";\nimport { Provider } from \"react-redux\";\nimport { createStore } from \"../../store\";\n\nexport const uploadFunction: FileInputUploadCb = (fileObject: File) =>\n\tnew Promise((resolve) => {\n\t\tresolve({\n\t\t\terr: \"\",\n\t\t\tpath: fileObject.name,\n\t\t});\n\t});\n\nexport const initFSBL = (windowObject?: any) => {\n\t// Poor man's global that can take any appendage\n\tconst globalAsAny: any = global;\n\n\tif (!windowObject) {\n\t\twindowObject = globalAsAny.window = {} as any;\n\t} else {\n\t\twindowObject = window;\n\n\t\tsetTimeout(() => {\n\t\t\tconst event = window.document.createEvent(\"Event\");\n\n\t\t\tevent?.initEvent(\"FSBLReady\", true, true);\n\n\t\t\twindow.dispatchEvent(event);\n\t\t});\n\t}\n\n\tglobalAsAny.FSBL = windowObject.FSBL = {\n\t\taddEventListener: (name: String, callback: () => void) => {\n\t\t\tcallback();\n\t\t},\n\t\tgetFSBLInfo: () =>\n\t\t\tnew Promise((resolve) => {\n\t\t\t\tresolve({\n\t\t\t\t\tFSBLVersion: \"1.0.0\",\n\t\t\t\t});\n\t\t\t}),\n\t\tClients: {\n\t\t\tTmpSmartDesktopClient: {\n\t\t\t\tcheckValidURL(url: string) {\n\t\t\t\t\tif (url.length === 0) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn /^https?:\\/\\/[^\\s]+$/.test(url);\n\t\t\t\t},\n\t\t\t\tcheckValidProjectName(name: string) {\n\t\t\t\t\treturn /^[a-zA-Z0-9 \\-_.]{1,}$/.test(name) && /[a-zA-Z0-9]{1,}/.test(name);\n\t\t\t\t},\n\t\t\t} as unknown,\n\t\t\tConfigClient: {\n\t\t\t\tsetPreference: () => {},\n\t\t\t\tgetValues: () => {},\n\t\t\t\tgetPreferences: () => {},\n\t\t\t},\n\t\t\tDialogManager: {\n\t\t\t\tspawnDialog: (obj1: any) => {\n\t\t\t\t\tconsole.table(obj1);\n\t\t\t\t},\n\t\t\t\tregisterDialogCallback: () => {},\n\t\t\t\trespondToOpener: () => {},\n\t\t\t},\n\t\t\tLauncherClient: {\n\t\t\t\tshowWindow: () => {},\n\t\t\t},\n\t\t\tLogger: {\n\t\t\t\tlog: () => {},\n\t\t\t\terror: () => {},\n\t\t\t\tsystem: {\n\t\t\t\t\tdebug: () => {},\n\t\t\t\t\tlog: () => {},\n\t\t\t\t\terror: () => {},\n\t\t\t\t\tverbose: () => {},\n\t\t\t\t\tdeprecated: () => {},\n\t\t\t\t},\n\t\t\t},\n\t\t\tRouterClient: {\n\t\t\t\ttransmit: () => {},\n\t\t\t\taddListener: () => {},\n\t\t\t\tsubscribe: () => {},\n\t\t\t},\n\t\t\tSearchClient: {\n\t\t\t\tinvokeItemAction: () => {},\n\t\t\t},\n\t\t\tStorageClient: {\n\t\t\t\tsave: () => {},\n\t\t\t\tclearCache: () => {},\n\t\t\t},\n\t\t\tWindowClient: {\n\t\t\t\tfitToDOM: () => {},\n\t\t\t},\n\t\t\tWorkspaceClient: {\n\t\t\t\taddEventListener: () => {},\n\t\t\t\tbringWindowsToFront: () => {},\n\t\t\t\tautoArrange: () => {},\n\t\t\t\tminimizeAll: () => {},\n\t\t\t\tactiveWorkspace: {\n\t\t\t\t\tname: \" \",\n\t\t\t\t},\n\t\t\t\tgetWorkspaceDefinition: (obj: Object, cb: Function) => {\n\t\t\t\t\tcb(null, null);\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tonShutdown: () => {},\n\t\tSystem: {\n\t\t\tgetSDServerInfo: () =>\n\t\t\t\tnew Promise((resolve) => {\n\t\t\t\t\tresolve({} as SDServerInfo);\n\t\t\t\t}),\n\t\t},\n\t\tSystemManagerClient: {\n\t\t\tpublishCheckpointState: () => {},\n\t\t},\n\t} as any;\n\n\tglobalAsAny.FSBL.Clients = {\n\t\t...globalAsAny.FSBL.Clients,\n\t\tWindowClient: {\n\t\t\tfitToDOM: () => {},\n\t\t} as any,\n\t};\n\n\tglobalAsAny.finsembleWindow = windowObject.finsembleWindow = {\n\t\tsetAlwaysOnTop: () => {},\n\t\taddEventListener: () => {},\n\t\tremoveEventListener: () => {},\n\t};\n};\n\nexport function createStory<T>(Component: Function, args: T) {\n\tconst template: Story<T> = (props: T) => {\n\t\tinitFSBL(window);\n\n\t\treturn (\n\t\t\t<Provider store={createStore()}>\n\t\t\t\t<Component {...{ ...args, ...props }} />\n\t\t\t</Provider>\n\t\t);\n\t};\n\n\ttemplate.args = args;\n\n\treturn template;\n}\n"]}
|
|
@@ -8,6 +8,13 @@ import { useDispatch, useSelector, Provider } from "react-redux";
|
|
|
8
8
|
import { actions, store } from "./remoteRedux";
|
|
9
9
|
import "../../assets/css/linkerWindow.css";
|
|
10
10
|
import { LinkerElement as LinkerElementDeprecated } from "./LinkerMenuDeprecated";
|
|
11
|
+
const returnToCallingWindow = async (activeWindowName) => {
|
|
12
|
+
if (activeWindowName === undefined) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const { wrap } = await FSBL.FinsembleWindow.getInstance({ windowName: activeWindowName });
|
|
16
|
+
wrap.focus();
|
|
17
|
+
};
|
|
11
18
|
const LinkerElement = () => {
|
|
12
19
|
var _a, _b, _c, _d;
|
|
13
20
|
const state = useSelector((currentState) => currentState);
|
|
@@ -18,13 +25,22 @@ const LinkerElement = () => {
|
|
|
18
25
|
// Track which menu item has focus for keyboard users
|
|
19
26
|
const [focusedMenuIndex, setFocusedMenuIndex] = useState(0);
|
|
20
27
|
const containerElement = useRef(null);
|
|
28
|
+
const moveFocus = (newIndex) => {
|
|
29
|
+
var _a;
|
|
30
|
+
setFocusedMenuIndex(newIndex);
|
|
31
|
+
const elements = (_a = containerElement.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll("[role='menuitemcheckbox']");
|
|
32
|
+
elements === null || elements === void 0 ? void 0 : elements[newIndex].focus();
|
|
33
|
+
};
|
|
21
34
|
const hideWindow = () => {
|
|
22
35
|
// Must blur or you end up having to click twice to show the window.
|
|
23
36
|
// If you just hide, the first time the user clicks
|
|
24
37
|
// on the linker button, the blur will trigger, which will hide the window.
|
|
25
38
|
finsembleWindow.blur();
|
|
26
39
|
finsembleWindow.hide();
|
|
27
|
-
|
|
40
|
+
moveFocus(0);
|
|
41
|
+
// By default, after the linker menu closes, the calling window doesn't receive focus.
|
|
42
|
+
// Send focus back to it.
|
|
43
|
+
returnToCallingWindow(activeWindowName);
|
|
28
44
|
};
|
|
29
45
|
useEffect(() => {
|
|
30
46
|
// Move focus to container element, so that keystrokes can be captured for keyboard users (accessibility)
|
|
@@ -72,19 +88,19 @@ const LinkerElement = () => {
|
|
|
72
88
|
hideWindow();
|
|
73
89
|
};
|
|
74
90
|
const channelElements = activeWindowName &&
|
|
75
|
-
allChannels.map(({ name, cssClassName }
|
|
91
|
+
allChannels.map(({ name, cssClassName }) => {
|
|
76
92
|
const active = joinedChannels.includes(name);
|
|
77
|
-
return (React.createElement("div", { key: name, className: `channel-wrapper ${cssClassName}
|
|
93
|
+
return (React.createElement("div", { key: name, className: `channel-wrapper ${cssClassName}`, onClick: () => toggleChannel(name), tabIndex: -1, role: "menuitemcheckbox", "aria-checked": active },
|
|
78
94
|
React.createElement("div", { className: "channel-label" }, name),
|
|
79
|
-
React.createElement("div", { className: "linker-glyph" }, active ? React.createElement("i", { className: "active-linker-group ff-check-mark" }) : null)));
|
|
95
|
+
React.createElement("div", { className: "linker-glyph" }, active ? React.createElement("i", { className: "active-linker-group ff-check-mark", "aria-hidden": "true" }) : null)));
|
|
80
96
|
});
|
|
81
97
|
const manageKeyboardNavigation = (evt) => {
|
|
82
98
|
const lastChannelIndex = allChannels.length - 1;
|
|
83
99
|
if (evt.key === "ArrowDown") {
|
|
84
|
-
|
|
100
|
+
moveFocus(focusedMenuIndex >= lastChannelIndex ? 0 : focusedMenuIndex + 1);
|
|
85
101
|
}
|
|
86
102
|
else if (evt.key === "ArrowUp") {
|
|
87
|
-
|
|
103
|
+
moveFocus(focusedMenuIndex <= 0 ? lastChannelIndex : focusedMenuIndex - 1);
|
|
88
104
|
}
|
|
89
105
|
else if (evt.key === "Enter") {
|
|
90
106
|
toggleChannel(allChannels[focusedMenuIndex].name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LinkerMenu.js","sourceRoot":"","sources":["../../../src/components/linker/LinkerMenu.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright 2020 by ChartIQ, Inc.\n * All rights reserved.\n */\nimport React, { useEffect, useState, useRef } from \"react\";\nimport { FinsembleProvider } from \"../FinsembleProvider\";\nimport { useDispatch, useSelector, Provider } from \"react-redux\";\nimport { LinkerStore, actions, store } from \"./remoteRedux\";\nimport \"../../assets/css/linkerWindow.css\";\nimport { LinkerElement as LinkerElementDeprecated } from \"./LinkerMenuDeprecated\";\n\ntype Channel = LinkerStore[\"allChannels\"][0];\ntype JoinedChannels = string[];\n\nconst LinkerElement: React.FunctionComponent = () => {\n\tconst state: LinkerStore = useSelector((currentState: any) => currentState);\n\tconst dispatch = useDispatch();\n\tconst { activeWindowName } = state;\n\tconst joinedChannels: JoinedChannels = state?.clients?.[activeWindowName ?? \"\"]?.joinedChannels ?? [];\n\tconst allChannels: Channel[] = state?.allChannels ?? [];\n\t// Track which menu item has focus for keyboard users\n\tconst [focusedMenuIndex, setFocusedMenuIndex] = useState(0);\n\tconst containerElement = useRef<HTMLDivElement>(null);\n\n\tconst hideWindow = () => {\n\t\t// Must blur or you end up having to click twice to show the window.\n\t\t// If you just hide, the first time the user clicks\n\t\t// on the linker button, the blur will trigger, which will hide the window.\n\t\tfinsembleWindow.blur();\n\t\tfinsembleWindow.hide();\n\t\tsetFocusedMenuIndex(0);\n\t};\n\n\tuseEffect(() => {\n\t\t// Move focus to container element, so that keystrokes can be captured for keyboard users (accessibility)\n\t\tcontainerElement.current && containerElement.current.focus();\n\n\t\t// Without these events, the linker menu is opened but doesn't focus, so the blur event never fires, and the menu is left\n\t\t// orphaned and sad.\n\n\t\tconst focusWindow = () => {\n\t\t\tfinsembleWindow.focus();\n\t\t};\n\n\t\tFSBL.Clients.Logger.system.log(\"Linker component is mounted. Initializing.\");\n\t\tfinsembleWindow.addEventListener(\"blurred\", hideWindow);\n\t\tfinsembleWindow.addEventListener(\"shown\", focusWindow);\n\n\t\treturn () => {\n\t\t\tFSBL.Clients.Logger.system.log(\"Linker component is unmounted. Cleaning up the event listeners.\");\n\t\t\tfinsembleWindow.removeEventListener(\"blurred\", hideWindow);\n\t\t\tfinsembleWindow.removeEventListener(\"shown\", focusWindow);\n\t\t};\n\t}, []);\n\n\tconst toggleChannel = (name: string) => {\n\t\t// These action creators can now be imported from finsemble-api\n\t\tif (activeWindowName) {\n\t\t\tif (joinedChannels.includes(name)) {\n\t\t\t\tdispatch(\n\t\t\t\t\tactions.unlinkChannels({\n\t\t\t\t\t\ttype: \"linker/unlinkChannels\",\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tchannels: [name],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\twindowName: activeWindowName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tdispatch(\n\t\t\t\t\tactions.linkChannels({\n\t\t\t\t\t\ttype: \"linker/linkChannels\",\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tchannels: [name],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\twindowName: activeWindowName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\thideWindow();\n\t};\n\n\tconst channelElements =\n\t\tactiveWindowName &&\n\t\tallChannels.map(({ name, cssClassName }, index: number) => {\n\t\t\tconst active = joinedChannels.includes(name);\n\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tkey={name}\n\t\t\t\t\tclassName={`channel-wrapper ${cssClassName} ${focusedMenuIndex === index ? \"focused\" : \"\"}`}\n\t\t\t\t\tonClick={() => toggleChannel(name)}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"channel-label\">{name}</div>\n\t\t\t\t\t<div className=\"linker-glyph\">{active ? <i className=\"active-linker-group ff-check-mark\"></i> : null}</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t});\n\n\tconst manageKeyboardNavigation = (evt: React.KeyboardEvent<HTMLDivElement>) => {\n\t\tconst lastChannelIndex = allChannels.length - 1;\n\t\tif (evt.key === \"ArrowDown\") {\n\t\t\tsetFocusedMenuIndex(focusedMenuIndex >= lastChannelIndex ? 0 : focusedMenuIndex + 1);\n\t\t} else if (evt.key === \"ArrowUp\") {\n\t\t\tsetFocusedMenuIndex(focusedMenuIndex <= 0 ? lastChannelIndex : focusedMenuIndex - 1);\n\t\t} else if (evt.key === \"Enter\") {\n\t\t\ttoggleChannel(allChannels[focusedMenuIndex].name);\n\t\t} else if (evt.key === \"Escape\") {\n\t\t\thideWindow();\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"linkerContainer\"\n\t\t\ttabIndex={0}\n\t\t\trole=\"menu\"\n\t\t\tonKeyDown={manageKeyboardNavigation}\n\t\t\tref={containerElement}\n\t\t>\n\t\t\t{channelElements}\n\t\t</div>\n\t);\n};\n\n/**\n * Picks whether to display the current or deprecated LinkerElement.\n * If config `finsemble.servicesConfig.linker.enabled` is set to true then the deprecated version will be used.\n *\n * This code should be removed once the linkerClient is removed from Finsemble.\n */\nconst WhichLinker = () => {\n\tconst [whichLinker, setWhichLinker] = React.useState(\"\");\n\n\tuseEffect(() => {\n\t\t(async () => {\n\t\t\tconst { data } = await FSBL.Clients.ConfigClient.getValue({\n\t\t\t\tfield: \"finsemble.servicesConfig.linker.enabled\",\n\t\t\t});\n\t\t\tif (data) {\n\t\t\t\tsetWhichLinker(\"LinkerElementDeprecated\");\n\t\t\t} else {\n\t\t\t\tsetWhichLinker(\"LinkerElement\");\n\t\t\t}\n\t\t})();\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t{whichLinker === \"LinkerElement\" && (\n\t\t\t\t<Provider store={store}>\n\t\t\t\t\t<LinkerElement />\n\t\t\t\t</Provider>\n\t\t\t)}\n\t\t\t{whichLinker === \"LinkerElementDeprecated\" && <LinkerElementDeprecated />}\n\t\t</>\n\t);\n};\n\n/**\n * The Linker icon on the window titlebar that launches the linker menu.\n */\nexport const LinkerMenu = () => (\n\t<FinsembleProvider>\n\t\t<WhichLinker />\n\t</FinsembleProvider>\n);\n"]}
|
|
1
|
+
{"version":3,"file":"LinkerMenu.js","sourceRoot":"","sources":["../../../src/components/linker/LinkerMenu.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright 2020 by ChartIQ, Inc.\n * All rights reserved.\n */\nimport React, { useEffect, useState, useRef } from \"react\";\nimport { FinsembleProvider } from \"../FinsembleProvider\";\nimport { useDispatch, useSelector, Provider } from \"react-redux\";\nimport { LinkerStore, actions, store } from \"./remoteRedux\";\nimport \"../../assets/css/linkerWindow.css\";\nimport { LinkerElement as LinkerElementDeprecated } from \"./LinkerMenuDeprecated\";\n\ntype Channel = LinkerStore[\"allChannels\"][0];\ntype JoinedChannels = string[];\n\nconst returnToCallingWindow = async (activeWindowName?: string) => {\n\tif (activeWindowName === undefined) {\n\t\treturn;\n\t}\n\n\tconst { wrap } = await FSBL.FinsembleWindow.getInstance({ windowName: activeWindowName });\n\twrap.focus();\n};\n\nconst LinkerElement: React.FunctionComponent = () => {\n\tconst state: LinkerStore = useSelector((currentState: any) => currentState);\n\tconst dispatch = useDispatch();\n\tconst { activeWindowName } = state;\n\tconst joinedChannels: JoinedChannels = state?.clients?.[activeWindowName ?? \"\"]?.joinedChannels ?? [];\n\tconst allChannels: Channel[] = state?.allChannels ?? [];\n\t// Track which menu item has focus for keyboard users\n\tconst [focusedMenuIndex, setFocusedMenuIndex] = useState(0);\n\tconst containerElement = useRef<HTMLDivElement>(null);\n\n\tconst moveFocus = (newIndex: number) => {\n\t\tsetFocusedMenuIndex(newIndex);\n\t\tconst elements = containerElement.current?.querySelectorAll(\n\t\t\t\"[role='menuitemcheckbox']\"\n\t\t) as NodeListOf<HTMLDivElement>;\n\t\telements?.[newIndex].focus();\n\t};\n\n\tconst hideWindow = () => {\n\t\t// Must blur or you end up having to click twice to show the window.\n\t\t// If you just hide, the first time the user clicks\n\t\t// on the linker button, the blur will trigger, which will hide the window.\n\t\tfinsembleWindow.blur();\n\t\tfinsembleWindow.hide();\n\t\tmoveFocus(0);\n\n\t\t// By default, after the linker menu closes, the calling window doesn't receive focus.\n\t\t// Send focus back to it.\n\t\treturnToCallingWindow(activeWindowName);\n\t};\n\n\tuseEffect(() => {\n\t\t// Move focus to container element, so that keystrokes can be captured for keyboard users (accessibility)\n\t\tcontainerElement.current && containerElement.current.focus();\n\n\t\t// Without these events, the linker menu is opened but doesn't focus, so the blur event never fires, and the menu is left\n\t\t// orphaned and sad.\n\n\t\tconst focusWindow = () => {\n\t\t\tfinsembleWindow.focus();\n\t\t};\n\n\t\tFSBL.Clients.Logger.system.log(\"Linker component is mounted. Initializing.\");\n\t\tfinsembleWindow.addEventListener(\"blurred\", hideWindow);\n\t\tfinsembleWindow.addEventListener(\"shown\", focusWindow);\n\n\t\treturn () => {\n\t\t\tFSBL.Clients.Logger.system.log(\"Linker component is unmounted. Cleaning up the event listeners.\");\n\t\t\tfinsembleWindow.removeEventListener(\"blurred\", hideWindow);\n\t\t\tfinsembleWindow.removeEventListener(\"shown\", focusWindow);\n\t\t};\n\t}, []);\n\n\tconst toggleChannel = (name: string) => {\n\t\t// These action creators can now be imported from finsemble-api\n\t\tif (activeWindowName) {\n\t\t\tif (joinedChannels.includes(name)) {\n\t\t\t\tdispatch(\n\t\t\t\t\tactions.unlinkChannels({\n\t\t\t\t\t\ttype: \"linker/unlinkChannels\",\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tchannels: [name],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\twindowName: activeWindowName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tdispatch(\n\t\t\t\t\tactions.linkChannels({\n\t\t\t\t\t\ttype: \"linker/linkChannels\",\n\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\tchannels: [name],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\twindowName: activeWindowName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\thideWindow();\n\t};\n\n\tconst channelElements =\n\t\tactiveWindowName &&\n\t\tallChannels.map(({ name, cssClassName }) => {\n\t\t\tconst active = joinedChannels.includes(name);\n\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tkey={name}\n\t\t\t\t\tclassName={`channel-wrapper ${cssClassName}`}\n\t\t\t\t\tonClick={() => toggleChannel(name)}\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\trole=\"menuitemcheckbox\"\n\t\t\t\t\taria-checked={active}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"channel-label\">{name}</div>\n\t\t\t\t\t<div className=\"linker-glyph\">\n\t\t\t\t\t\t{active ? <i className=\"active-linker-group ff-check-mark\" aria-hidden=\"true\"></i> : null}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t});\n\n\tconst manageKeyboardNavigation = (evt: React.KeyboardEvent<HTMLDivElement>) => {\n\t\tconst lastChannelIndex = allChannels.length - 1;\n\t\tif (evt.key === \"ArrowDown\") {\n\t\t\tmoveFocus(focusedMenuIndex >= lastChannelIndex ? 0 : focusedMenuIndex + 1);\n\t\t} else if (evt.key === \"ArrowUp\") {\n\t\t\tmoveFocus(focusedMenuIndex <= 0 ? lastChannelIndex : focusedMenuIndex - 1);\n\t\t} else if (evt.key === \"Enter\") {\n\t\t\ttoggleChannel(allChannels[focusedMenuIndex].name);\n\t\t} else if (evt.key === \"Escape\") {\n\t\t\thideWindow();\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"linkerContainer\"\n\t\t\ttabIndex={0}\n\t\t\trole=\"menu\"\n\t\t\tonKeyDown={manageKeyboardNavigation}\n\t\t\tref={containerElement}\n\t\t>\n\t\t\t{channelElements}\n\t\t</div>\n\t);\n};\n\n/**\n * Picks whether to display the current or deprecated LinkerElement.\n * If config `finsemble.servicesConfig.linker.enabled` is set to true then the deprecated version will be used.\n *\n * This code should be removed once the linkerClient is removed from Finsemble.\n */\nconst WhichLinker = () => {\n\tconst [whichLinker, setWhichLinker] = React.useState(\"\");\n\n\tuseEffect(() => {\n\t\t(async () => {\n\t\t\tconst { data } = await FSBL.Clients.ConfigClient.getValue({\n\t\t\t\tfield: \"finsemble.servicesConfig.linker.enabled\",\n\t\t\t});\n\t\t\tif (data) {\n\t\t\t\tsetWhichLinker(\"LinkerElementDeprecated\");\n\t\t\t} else {\n\t\t\t\tsetWhichLinker(\"LinkerElement\");\n\t\t\t}\n\t\t})();\n\t}, []);\n\n\treturn (\n\t\t<>\n\t\t\t{whichLinker === \"LinkerElement\" && (\n\t\t\t\t<Provider store={store}>\n\t\t\t\t\t<LinkerElement />\n\t\t\t\t</Provider>\n\t\t\t)}\n\t\t\t{whichLinker === \"LinkerElementDeprecated\" && <LinkerElementDeprecated />}\n\t\t</>\n\t);\n};\n\n/**\n * The Linker icon on the window titlebar that launches the linker menu.\n */\nexport const LinkerMenu = () => (\n\t<FinsembleProvider>\n\t\t<WhichLinker />\n\t</FinsembleProvider>\n);\n"]}
|
|
@@ -165,7 +165,7 @@ const showHideResizeWindow = async ({ childWindow, show, thisMenuId, menuHeight,
|
|
|
165
165
|
* side of the toolbar. Finally, showWindow() forces windows to open entirely on a monitor, so it will slide the
|
|
166
166
|
* menu to the left or right as necessary to prevent it from straddling.
|
|
167
167
|
*/
|
|
168
|
-
FSBL.Clients.LauncherClient.showWindow({ windowName: name }, params);
|
|
168
|
+
await FSBL.Clients.LauncherClient.showWindow({ windowName: name }, params);
|
|
169
169
|
// Ensures that the menu has keyboard focus for accessibility
|
|
170
170
|
finWindow.focus();
|
|
171
171
|
// Ensures that the menu is positioned above any other windows that have setAlwaysOnTop flagged
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuPortal.js","sourceRoot":"","sources":["../../../src/components/menu/MenuPortal.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\nimport { MenuContext } from \"./menuContext\";\nimport { calculateDimensions, injectCSS } from \"./menuHelpers\";\nimport { applyMenuKeyboardNavigation } from \"./keyboardNavigation\";\nimport { MenuAutoResizer } from \"./MenuAutoResizer\";\nimport { useState, useEffect, useContext } from \"react\";\nimport { useMenu } from \"../../hooks/useMenu\";\nimport { services, FEA } from \"@finsemble/finsemble-api\";\n\ntype SpawnParams = services.window.types.SpawnParams;\n\n/**\n * Proxy/fake events are needed because when `document.addEventListener` is used inside a component\n * that is rendered inside react portal, `document` will refer to the toolbar's document instead\n * of the childWindow's document. Clicking inside a portal will not therefore capture those events.\n *\n * This code intercepts these events inside the portal and then forwards them to the parent (toolbar).\n */\nconst setupEventForwarding = (newWindow: Window) => {\n\t[\"mouseDown\", \"click\", \"mouseUp\"].forEach((eventName) => {\n\t\tnewWindow.document.addEventListener(eventName, (event) => {\n\t\t\tdocument.dispatchEvent(\n\t\t\t\tnew CustomEvent(`portal:${eventName}`, {\n\t\t\t\t\tdetail: {\n\t\t\t\t\t\t// Devs may need access to the x and y of the cursor\n\t\t\t\t\t\tmouseEvent: new MouseEvent(eventName, event),\n\t\t\t\t\t\t// And possibly the target element\n\t\t\t\t\t\ttarget: event.target,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t});\n\n\t/**\n\t * Proxies keyboard events from the portal up into the parent window.\n\t * instead of e.key, you'll need to access e.detail.key.\n\t */\n\t[\"keyup\", \"keydown\", \"keypress\"].forEach((eventName) => {\n\t\tnewWindow?.document.addEventListener(eventName, (event) => {\n\t\t\tdocument.dispatchEvent(\n\t\t\t\tnew CustomEvent(`portal:${eventName}`, {\n\t\t\t\t\tdetail: new KeyboardEvent(event.type, event),\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t});\n};\n\n/**\n * The window (opened by window.open) is an empty html document.\n * This function creates a containerDiv for the parent to insert its\n * React DOM. That containerDiv is set through the `setElement()` method\n * which must be passed in.\n *\n * This function also does portal housekeeping such as transferring CSS and window\n * events.\n */\nconst insertWindowContent = ({\n\tnewWindow,\n\tisAutoResizable,\n\tclassName,\n\tsetElement,\n\tmenuHeight,\n}: {\n\tnewWindow: Window;\n\tisAutoResizable: boolean;\n\tclassName?: string;\n\tmenuHeight?: number;\n\tsetElement: React.Dispatch<React.SetStateAction<HTMLElement | undefined>>;\n}) => {\n\t// Set the child window's <html> tag to class \"menu-portal\" for scrollbar styling\n\tnewWindow.document.documentElement.className = \"menu-portal\";\n\tif (isAutoResizable) newWindow.document.body.setAttribute(\"resizing\", \"true\");\n\n\t// Create the element which will hold our react elements and then append it into the child window's body.\n\tconst containerDiv: HTMLElement = document.createElement(\"div\");\n\tnewWindow.document.body.appendChild(containerDiv);\n\n\t// The className that was passed to MenuShell is added to the child window's <body>\n\tclassName?.split(\" \").forEach((name: string) => newWindow!.document.body.classList.add(name));\n\n\t// This will update local state which will cause the parent React Functional Component\n\t// to return a react portal. See comments at the end of this file.\n\tsetElement(containerDiv);\n\n\t// Inject css into the child window's <head>\n\tinjectCSS(newWindow);\n\n\t// THE FOLLOWING IS LIKELY DEPRECATED BUT KEEPING JUST IN CASE\n\t// Place height on the portal.\n\t// inside of the portal, window.outerHeight === 39 (toolbar height).\n\t// Knowing the height of the window is important because some menus use that\n\t// information to force overflow on certain sections of the menu.\n\t(newWindow as any).portalHeight = menuHeight;\n};\n\n/**\n * React hook to create a drop down menu. This hook creates a new window using window.open\n * and assigns it as the childWindow to the MenuPortal. It then uses insertWindowContent()\n * to establish the React/DOM connection with the parent (e.g. Toolbar).\n */\nconst useCreateDropdown = ({\n\tsetElement,\n\tchildWindow,\n\tsetChildWindow,\n}: {\n\tsetElement: React.Dispatch<React.SetStateAction<HTMLElement | undefined>>;\n\tchildWindow: Window | null;\n\tsetChildWindow: React.Dispatch<React.SetStateAction<Window | null>>;\n}) => {\n\tconst { thisMenuId, menuWidth, menuHeight, className, maxHeight, minHeight } = useContext(MenuContext);\n\tconst { blurMenu } = useMenu();\n\tconst isAutoResizable = !menuHeight;\n\n\t/**\n\t * Initialize the window. This should only run once though it is possible\n\t * to run multiple times if MenuContext changes.\n\t */\n\tuseEffect(() => {\n\t\tlet menuAutoResizer: any = null;\n\n\t\t/**\n\t\t * Initial size and location of the menu is irrelevant because it is hidden.\n\t\t * The menu will be resized and positioned correctly when it is shown.\n\t\t */\n\t\tconst features = `height=1,width=${menuWidth},left=0,top=0,opacity=1`;\n\n\t\t/**\n\t\t * Opens the window which will contain the menu contents. This looks like a browser window open\n\t\t * but actually opens an Electron window which FEA intercepts. FEA uses the `childWindowOptions`\n\t\t * json configuration to determine how to display the window. `childWindowOptions.show` should\n\t\t * be set to `false` otherwise a white window will flash prior to the menu being rendered.\n\t\t *\n\t\t *\n\t\t * The \"/component/toolbar/menu.html\" is just an empty page. It's necessary to reference a real page\n\t\t * rather than about:blank in order that the \"origin\" is correct for the page. Many CSS ui-assets such\n\t\t * as fonts and images are set with relative paths that require a correct origin.\n\t\t *\n\t\t * Note, we append the menu ID for automated testing. This allows Selenium to\n\t\t * uniquely identify each menu.\n\t\t */\n\t\tconst newWindow = window.open(`./menu.html#${thisMenuId}`, `(Menu) ${thisMenuId}`, features);\n\t\tsetChildWindow(newWindow);\n\n\t\tif (newWindow) {\n\t\t\tconst onLoad = () => {\n\t\t\t\tinsertWindowContent({ newWindow, isAutoResizable, className, setElement, menuHeight });\n\t\t\t\tsetupEventForwarding(newWindow);\n\t\t\t\t/* Close window when a user clicks away.\n\t\t\t\t\tAre you wondering why not just close the window without calling\n\t\t\t\t\ttoggle? because we want to update the state in the store first\n\t\t\t\t\twhich will cause openMenuId to no longer match the shell id\n\t\t\t\t\tand eventually destroy this component which will cause the window\n\t\t\t\t\tto close (see cleanup function).\n\t\t\t\t*/\n\t\t\t\tnewWindow.addEventListener(\"blur\", blurMenu);\n\t\t\t\tnewWindow.addEventListener(\"keydown\", (e) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tblurMenu();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tapplyMenuKeyboardNavigation(newWindow);\n\n\t\t\t\t// Attach MenuAutoResizer only if the menu doesn't have a fixed height\n\t\t\t\tif (isAutoResizable)\n\t\t\t\t\tmenuAutoResizer = new MenuAutoResizer(newWindow, thisMenuId, menuWidth, maxHeight, minHeight);\n\t\t\t};\n\t\t\tnewWindow.addEventListener(\"load\", onLoad, true);\n\t\t} else {\n\t\t\tFSBL.Clients.Logger.system.error(`MenuPortal error: window.open returned null for \"./menu.html#${thisMenuId}\"`);\n\t\t}\n\n\t\treturn () => {\n\t\t\t// imesner 20210406 childwindow and keyboardNavigation were both null but hadn't closed the window or released global hotkeys\n\t\t\tconst win = childWindow || menuAutoResizer?.childWindow;\n\n\t\t\tmenuAutoResizer?.disconnect();\n\t\t\twin?.close();\n\t\t\tsetChildWindow(null);\n\t\t};\n\t}, [blurMenu, className, menuWidth, menuHeight, maxHeight, thisMenuId]);\n};\n\n/**\n * Sets visibility, size and location of the window. This can be called numerous times\n * during the lifetime of the MenuPortal.\n */\nconst showHideResizeWindow = async ({\n\tchildWindow,\n\tshow,\n\tthisMenuId,\n\tmenuHeight,\n\tmaxHeight,\n\tminHeight,\n}: {\n\tchildWindow: Window;\n\tshow: boolean;\n\tthisMenuId: string;\n\tmenuHeight?: number;\n\tmaxHeight: number;\n\tminHeight: number;\n}) => {\n\tconst finWindow: FEA.FEAWindow = childWindow.fin.desktop.Window.getCurrent();\n\tif (show) {\n\t\tconst { left, top, height } = await calculateDimensions(childWindow, thisMenuId, menuHeight, maxHeight, minHeight);\n\n\t\tconst params: SpawnParams = {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: left,\n\t\t\ttop: top,\n\t\t\theight: height,\n\t\t\tforceOntoMonitor: \"monitorRect\",\n\t\t};\n\n\t\tconst { name } = childWindow;\n\n\t\t/**\n\t\t * Use Finsemble to show the window. We might be tempted simply to use childWindow.moveTo() or childWindow.resizeTo()\n\t\t * but those commands limit the child window to a single monitor. We want to position the window relative to the\n\t\t * monitor on which the toolbar currently resides. showWindow() is monitor aware, so by using monitor=\"mine\" we can\n\t\t * ensure that the menu will always open on the same monitor as the toolbar. Since our toolbar has built in logic\n\t\t * to avoid straddling, we can be sure that the menu will never have to guess whether it exists on the left or right\n\t\t * side of the toolbar. Finally, showWindow() forces windows to open entirely on a monitor, so it will slide the\n\t\t * menu to the left or right as necessary to prevent it from straddling.\n\t\t */\n\t\tFSBL.Clients.LauncherClient.showWindow({ windowName: name }, params);\n\n\t\t// Ensures that the menu has keyboard focus for accessibility\n\t\tfinWindow.focus();\n\n\t\t// Ensures that the menu is positioned above any other windows that have setAlwaysOnTop flagged\n\t\tFSBL.FinsembleWindow.getInstance({ name: name }, (e: any, fsblWindow: any) => {\n\t\t\tfsblWindow.setAlwaysOnTop({ alwaysOnTop: true });\n\t\t});\n\t} else {\n\t\tconst { name } = childWindow;\n\t\tFSBL.FinsembleWindow.getInstance({ name: name }, (e: any, fsblWindow: any) => {\n\t\t\tfsblWindow.setAlwaysOnTop({ alwaysOnTop: false });\n\t\t});\n\n\t\tfinWindow.hide();\n\t}\n};\n\n/**\n * Closes the menu portal if the menu button is removed from the toolbar\n *\n * @param {Node} element - HTML element to observe\n *\n */\nconst closePortal = (element: Node) => {\n\tconst { closeMenu } = useMenu();\n\n\tconst options = {\n\t\tchildList: true,\n\t\tsubtree: true,\n\t};\n\n\t/**\n\t * MutationObserver interface provides the ability to watch for\n\t * changes to the DOM tree using the observe method\n\t */\n\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\tmutations.forEach((mutation) => {\n\t\t\tif (\n\t\t\t\tmutation.removedNodes?.length &&\n\t\t\t\t// prevents menu closing if the favorite apps have been changed\n\t\t\t\t(mutation.target as HTMLDivElement)?.id !== \"favoritesContainer\"\n\t\t\t) {\n\t\t\t\tcloseMenu();\n\t\t\t}\n\n\t\t\t// stops the MutationObserver from receiving notification from observer\n\t\t\tmutationObserver.disconnect();\n\t\t});\n\t});\n\n\t// watches for DOM changes\n\tmutationObserver.observe(element, options);\n};\n\nexport const MenuPortal: React.FunctionComponent<{\n\tshow: boolean;\n}> = ({ show, children }) => {\n\tconst { thisMenuId, menuHeight, maxHeight, minHeight } = useContext(MenuContext);\n\n\t// Container div for React portal\n\tconst [element, setElement] = useState<HTMLElement>();\n\tconst [childWindow, setChildWindow] = useState<Window | null>(null);\n\n\t/**\n\t * Show and hide window. This effect will run whenever the `show` prop changes,\n\t * generally initiated by a click to <MenuToggle>.\n\t */\n\tuseEffect(() => {\n\t\t// If child window isn't yet initialized then no-op\n\t\tif (!childWindow) return;\n\n\t\tshowHideResizeWindow({ childWindow, show, thisMenuId, menuHeight, maxHeight, minHeight });\n\t\treturn () => {};\n\t}, [show]);\n\n\t// Create the dropdown. (if MenuContext changes then the dropdown will be removed and recreated).\n\tuseCreateDropdown({ childWindow, setElement, setChildWindow });\n\n\tconst toolbar = document.getElementById(\"Toolbar-tsx\");\n\n\tif (toolbar) closePortal(toolbar);\n\n\t// We should only return a react portal when window is ready\n\t// and container div appended to its body\n\t// See Dan abramov comment about this at:\n\t// https://github.com/facebook/react/issues/12355#issuecomment-410996235\n\treturn element ? ReactDOM.createPortal(children, element) : null;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"MenuPortal.js","sourceRoot":"","sources":["../../../src/components/menu/MenuPortal.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\nimport { MenuContext } from \"./menuContext\";\nimport { calculateDimensions, injectCSS } from \"./menuHelpers\";\nimport { applyMenuKeyboardNavigation } from \"./keyboardNavigation\";\nimport { MenuAutoResizer } from \"./MenuAutoResizer\";\nimport { useState, useEffect, useContext } from \"react\";\nimport { useMenu } from \"../../hooks/useMenu\";\nimport { services, FEA } from \"@finsemble/finsemble-api\";\n\ntype SpawnParams = services.window.types.SpawnParams;\n\n/**\n * Proxy/fake events are needed because when `document.addEventListener` is used inside a component\n * that is rendered inside react portal, `document` will refer to the toolbar's document instead\n * of the childWindow's document. Clicking inside a portal will not therefore capture those events.\n *\n * This code intercepts these events inside the portal and then forwards them to the parent (toolbar).\n */\nconst setupEventForwarding = (newWindow: Window) => {\n\t[\"mouseDown\", \"click\", \"mouseUp\"].forEach((eventName) => {\n\t\tnewWindow.document.addEventListener(eventName, (event) => {\n\t\t\tdocument.dispatchEvent(\n\t\t\t\tnew CustomEvent(`portal:${eventName}`, {\n\t\t\t\t\tdetail: {\n\t\t\t\t\t\t// Devs may need access to the x and y of the cursor\n\t\t\t\t\t\tmouseEvent: new MouseEvent(eventName, event),\n\t\t\t\t\t\t// And possibly the target element\n\t\t\t\t\t\ttarget: event.target,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t});\n\n\t/**\n\t * Proxies keyboard events from the portal up into the parent window.\n\t * instead of e.key, you'll need to access e.detail.key.\n\t */\n\t[\"keyup\", \"keydown\", \"keypress\"].forEach((eventName) => {\n\t\tnewWindow?.document.addEventListener(eventName, (event) => {\n\t\t\tdocument.dispatchEvent(\n\t\t\t\tnew CustomEvent(`portal:${eventName}`, {\n\t\t\t\t\tdetail: new KeyboardEvent(event.type, event),\n\t\t\t\t})\n\t\t\t);\n\t\t});\n\t});\n};\n\n/**\n * The window (opened by window.open) is an empty html document.\n * This function creates a containerDiv for the parent to insert its\n * React DOM. That containerDiv is set through the `setElement()` method\n * which must be passed in.\n *\n * This function also does portal housekeeping such as transferring CSS and window\n * events.\n */\nconst insertWindowContent = ({\n\tnewWindow,\n\tisAutoResizable,\n\tclassName,\n\tsetElement,\n\tmenuHeight,\n}: {\n\tnewWindow: Window;\n\tisAutoResizable: boolean;\n\tclassName?: string;\n\tmenuHeight?: number;\n\tsetElement: React.Dispatch<React.SetStateAction<HTMLElement | undefined>>;\n}) => {\n\t// Set the child window's <html> tag to class \"menu-portal\" for scrollbar styling\n\tnewWindow.document.documentElement.className = \"menu-portal\";\n\tif (isAutoResizable) newWindow.document.body.setAttribute(\"resizing\", \"true\");\n\n\t// Create the element which will hold our react elements and then append it into the child window's body.\n\tconst containerDiv: HTMLElement = document.createElement(\"div\");\n\tnewWindow.document.body.appendChild(containerDiv);\n\n\t// The className that was passed to MenuShell is added to the child window's <body>\n\tclassName?.split(\" \").forEach((name: string) => newWindow!.document.body.classList.add(name));\n\n\t// This will update local state which will cause the parent React Functional Component\n\t// to return a react portal. See comments at the end of this file.\n\tsetElement(containerDiv);\n\n\t// Inject css into the child window's <head>\n\tinjectCSS(newWindow);\n\n\t// THE FOLLOWING IS LIKELY DEPRECATED BUT KEEPING JUST IN CASE\n\t// Place height on the portal.\n\t// inside of the portal, window.outerHeight === 39 (toolbar height).\n\t// Knowing the height of the window is important because some menus use that\n\t// information to force overflow on certain sections of the menu.\n\t(newWindow as any).portalHeight = menuHeight;\n};\n\n/**\n * React hook to create a drop down menu. This hook creates a new window using window.open\n * and assigns it as the childWindow to the MenuPortal. It then uses insertWindowContent()\n * to establish the React/DOM connection with the parent (e.g. Toolbar).\n */\nconst useCreateDropdown = ({\n\tsetElement,\n\tchildWindow,\n\tsetChildWindow,\n}: {\n\tsetElement: React.Dispatch<React.SetStateAction<HTMLElement | undefined>>;\n\tchildWindow: Window | null;\n\tsetChildWindow: React.Dispatch<React.SetStateAction<Window | null>>;\n}) => {\n\tconst { thisMenuId, menuWidth, menuHeight, className, maxHeight, minHeight } = useContext(MenuContext);\n\tconst { blurMenu } = useMenu();\n\tconst isAutoResizable = !menuHeight;\n\n\t/**\n\t * Initialize the window. This should only run once though it is possible\n\t * to run multiple times if MenuContext changes.\n\t */\n\tuseEffect(() => {\n\t\tlet menuAutoResizer: any = null;\n\n\t\t/**\n\t\t * Initial size and location of the menu is irrelevant because it is hidden.\n\t\t * The menu will be resized and positioned correctly when it is shown.\n\t\t */\n\t\tconst features = `height=1,width=${menuWidth},left=0,top=0,opacity=1`;\n\n\t\t/**\n\t\t * Opens the window which will contain the menu contents. This looks like a browser window open\n\t\t * but actually opens an Electron window which FEA intercepts. FEA uses the `childWindowOptions`\n\t\t * json configuration to determine how to display the window. `childWindowOptions.show` should\n\t\t * be set to `false` otherwise a white window will flash prior to the menu being rendered.\n\t\t *\n\t\t *\n\t\t * The \"/component/toolbar/menu.html\" is just an empty page. It's necessary to reference a real page\n\t\t * rather than about:blank in order that the \"origin\" is correct for the page. Many CSS ui-assets such\n\t\t * as fonts and images are set with relative paths that require a correct origin.\n\t\t *\n\t\t * Note, we append the menu ID for automated testing. This allows Selenium to\n\t\t * uniquely identify each menu.\n\t\t */\n\t\tconst newWindow = window.open(`./menu.html#${thisMenuId}`, `(Menu) ${thisMenuId}`, features);\n\t\tsetChildWindow(newWindow);\n\n\t\tif (newWindow) {\n\t\t\tconst onLoad = () => {\n\t\t\t\tinsertWindowContent({ newWindow, isAutoResizable, className, setElement, menuHeight });\n\t\t\t\tsetupEventForwarding(newWindow);\n\t\t\t\t/* Close window when a user clicks away.\n\t\t\t\t\tAre you wondering why not just close the window without calling\n\t\t\t\t\ttoggle? because we want to update the state in the store first\n\t\t\t\t\twhich will cause openMenuId to no longer match the shell id\n\t\t\t\t\tand eventually destroy this component which will cause the window\n\t\t\t\t\tto close (see cleanup function).\n\t\t\t\t*/\n\t\t\t\tnewWindow.addEventListener(\"blur\", blurMenu);\n\t\t\t\tnewWindow.addEventListener(\"keydown\", (e) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tblurMenu();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tapplyMenuKeyboardNavigation(newWindow);\n\n\t\t\t\t// Attach MenuAutoResizer only if the menu doesn't have a fixed height\n\t\t\t\tif (isAutoResizable)\n\t\t\t\t\tmenuAutoResizer = new MenuAutoResizer(newWindow, thisMenuId, menuWidth, maxHeight, minHeight);\n\t\t\t};\n\t\t\tnewWindow.addEventListener(\"load\", onLoad, true);\n\t\t} else {\n\t\t\tFSBL.Clients.Logger.system.error(`MenuPortal error: window.open returned null for \"./menu.html#${thisMenuId}\"`);\n\t\t}\n\n\t\treturn () => {\n\t\t\t// imesner 20210406 childwindow and keyboardNavigation were both null but hadn't closed the window or released global hotkeys\n\t\t\tconst win = childWindow || menuAutoResizer?.childWindow;\n\n\t\t\tmenuAutoResizer?.disconnect();\n\t\t\twin?.close();\n\t\t\tsetChildWindow(null);\n\t\t};\n\t}, [blurMenu, className, menuWidth, menuHeight, maxHeight, thisMenuId]);\n};\n\n/**\n * Sets visibility, size and location of the window. This can be called numerous times\n * during the lifetime of the MenuPortal.\n */\nconst showHideResizeWindow = async ({\n\tchildWindow,\n\tshow,\n\tthisMenuId,\n\tmenuHeight,\n\tmaxHeight,\n\tminHeight,\n}: {\n\tchildWindow: Window;\n\tshow: boolean;\n\tthisMenuId: string;\n\tmenuHeight?: number;\n\tmaxHeight: number;\n\tminHeight: number;\n}) => {\n\tconst finWindow: FEA.FEAWindow = childWindow.fin.desktop.Window.getCurrent();\n\tif (show) {\n\t\tconst { left, top, height } = await calculateDimensions(childWindow, thisMenuId, menuHeight, maxHeight, minHeight);\n\n\t\tconst params: SpawnParams = {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: left,\n\t\t\ttop: top,\n\t\t\theight: height,\n\t\t\tforceOntoMonitor: \"monitorRect\",\n\t\t};\n\n\t\tconst { name } = childWindow;\n\n\t\t/**\n\t\t * Use Finsemble to show the window. We might be tempted simply to use childWindow.moveTo() or childWindow.resizeTo()\n\t\t * but those commands limit the child window to a single monitor. We want to position the window relative to the\n\t\t * monitor on which the toolbar currently resides. showWindow() is monitor aware, so by using monitor=\"mine\" we can\n\t\t * ensure that the menu will always open on the same monitor as the toolbar. Since our toolbar has built in logic\n\t\t * to avoid straddling, we can be sure that the menu will never have to guess whether it exists on the left or right\n\t\t * side of the toolbar. Finally, showWindow() forces windows to open entirely on a monitor, so it will slide the\n\t\t * menu to the left or right as necessary to prevent it from straddling.\n\t\t */\n\t\tawait FSBL.Clients.LauncherClient.showWindow({ windowName: name }, params);\n\n\t\t// Ensures that the menu has keyboard focus for accessibility\n\t\tfinWindow.focus();\n\n\t\t// Ensures that the menu is positioned above any other windows that have setAlwaysOnTop flagged\n\t\tFSBL.FinsembleWindow.getInstance({ name: name }, (e: any, fsblWindow: any) => {\n\t\t\tfsblWindow.setAlwaysOnTop({ alwaysOnTop: true });\n\t\t});\n\t} else {\n\t\tconst { name } = childWindow;\n\t\tFSBL.FinsembleWindow.getInstance({ name: name }, (e: any, fsblWindow: any) => {\n\t\t\tfsblWindow.setAlwaysOnTop({ alwaysOnTop: false });\n\t\t});\n\n\t\tfinWindow.hide();\n\t}\n};\n\n/**\n * Closes the menu portal if the menu button is removed from the toolbar\n *\n * @param {Node} element - HTML element to observe\n *\n */\nconst closePortal = (element: Node) => {\n\tconst { closeMenu } = useMenu();\n\n\tconst options = {\n\t\tchildList: true,\n\t\tsubtree: true,\n\t};\n\n\t/**\n\t * MutationObserver interface provides the ability to watch for\n\t * changes to the DOM tree using the observe method\n\t */\n\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\tmutations.forEach((mutation) => {\n\t\t\tif (\n\t\t\t\tmutation.removedNodes?.length &&\n\t\t\t\t// prevents menu closing if the favorite apps have been changed\n\t\t\t\t(mutation.target as HTMLDivElement)?.id !== \"favoritesContainer\"\n\t\t\t) {\n\t\t\t\tcloseMenu();\n\t\t\t}\n\n\t\t\t// stops the MutationObserver from receiving notification from observer\n\t\t\tmutationObserver.disconnect();\n\t\t});\n\t});\n\n\t// watches for DOM changes\n\tmutationObserver.observe(element, options);\n};\n\nexport const MenuPortal: React.FunctionComponent<{\n\tshow: boolean;\n}> = ({ show, children }) => {\n\tconst { thisMenuId, menuHeight, maxHeight, minHeight } = useContext(MenuContext);\n\n\t// Container div for React portal\n\tconst [element, setElement] = useState<HTMLElement>();\n\tconst [childWindow, setChildWindow] = useState<Window | null>(null);\n\n\t/**\n\t * Show and hide window. This effect will run whenever the `show` prop changes,\n\t * generally initiated by a click to <MenuToggle>.\n\t */\n\tuseEffect(() => {\n\t\t// If child window isn't yet initialized then no-op\n\t\tif (!childWindow) return;\n\n\t\tshowHideResizeWindow({ childWindow, show, thisMenuId, menuHeight, maxHeight, minHeight });\n\t\treturn () => {};\n\t}, [show]);\n\n\t// Create the dropdown. (if MenuContext changes then the dropdown will be removed and recreated).\n\tuseCreateDropdown({ childWindow, setElement, setChildWindow });\n\n\tconst toolbar = document.getElementById(\"Toolbar-tsx\");\n\n\tif (toolbar) closePortal(toolbar);\n\n\t// We should only return a react portal when window is ready\n\t// and container div appended to its body\n\t// See Dan abramov comment about this at:\n\t// https://github.com/facebook/react/issues/12355#issuecomment-410996235\n\treturn element ? ReactDOM.createPortal(children, element) : null;\n};\n"]}
|
|
@@ -12,7 +12,7 @@ export const MenuToggle = ({ children }) => {
|
|
|
12
12
|
if (["Enter", "Space"].includes(e.key)) {
|
|
13
13
|
toggleMenu();
|
|
14
14
|
}
|
|
15
|
-
} },
|
|
15
|
+
}, "aria-expanded": "false", "aria-haspopup": "true" },
|
|
16
16
|
children,
|
|
17
17
|
React.createElement("i", { className: "finsemble-toolbar-button-icon ff-chevron-down", "aria-hidden": "true" })));
|
|
18
18
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuToggle.js","sourceRoot":"","sources":["../../../src/components/menu/MenuToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAA4B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/C,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAErD,MAAM,eAAe,GAAW,YAAY,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAEpE,OAAO,CACN,6BACC,EAAE,EAAE,GAAG,UAAU,cAAc,EAC/B,SAAS,EAAE,4BAA4B,eAAe,EAAE,EACxD,WAAW,EAAE,UAAU,EACvB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,CAAsC,EAAE,EAAE;YACrD,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;gBACvC,UAAU,EAAE,CAAC;aACb;QACF,CAAC;
|
|
1
|
+
{"version":3,"file":"MenuToggle.js","sourceRoot":"","sources":["../../../src/components/menu/MenuToggle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAA4B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IACnE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/C,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAErD,MAAM,eAAe,GAAW,YAAY,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAEpE,OAAO,CACN,6BACC,EAAE,EAAE,GAAG,UAAU,cAAc,EAC/B,SAAS,EAAE,4BAA4B,eAAe,EAAE,EACxD,WAAW,EAAE,UAAU,EACvB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,CAAsC,EAAE,EAAE;YACrD,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;gBACvC,UAAU,EAAE,CAAC;aACb;QACF,CAAC,mBACa,OAAO,mBACP,MAAM;QAEnB,QAAQ;QACT,2BAAG,SAAS,EAAC,+CAA+C,iBAAa,MAAM,GAAK,CAC/E,CACN,CAAC;AACH,CAAC,CAAC","sourcesContent":["import * as React from \"react\";\nimport { MenuContext } from \"./menuContext\";\nimport { useMenu } from \"../../hooks/useMenu\";\n\n/**\n * A menu button that opens and closes the menu.\n */\nexport const MenuToggle: React.FunctionComponent = ({ children }) => {\n\tconst { toggleMenu, isMenuActive } = useMenu();\n\tconst { thisMenuId } = React.useContext(MenuContext);\n\n\tconst menuActiveClass: string = isMenuActive() ? \"menu-active\" : \"\";\n\n\treturn (\n\t\t<div\n\t\t\tid={`${thisMenuId}-menu-toggle`}\n\t\t\tclassName={`finsemble-toolbar-button ${menuActiveClass}`}\n\t\t\tonMouseDown={toggleMenu}\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t\tonKeyDown={(e: React.KeyboardEvent<HTMLDivElement>) => {\n\t\t\t\tif ([\"Enter\", \"Space\"].includes(e.key)) {\n\t\t\t\t\ttoggleMenu();\n\t\t\t\t}\n\t\t\t}}\n\t\t\taria-expanded=\"false\"\n\t\t\taria-haspopup=\"true\"\n\t\t>\n\t\t\t{children}\n\t\t\t<i className=\"finsemble-toolbar-button-icon ff-chevron-down\" aria-hidden=\"true\"></i>\n\t\t</div>\n\t);\n};\n"]}
|
package/react/components/notifications/components/notificationsToasts/NotificationsToasts.js
CHANGED
|
@@ -136,7 +136,6 @@ export const NotificationsToasts = (props) => {
|
|
|
136
136
|
finsembleWindow.setShape([roundedRect]);
|
|
137
137
|
}
|
|
138
138
|
else {
|
|
139
|
-
await finsembleWindow.show();
|
|
140
139
|
const { err, data } = await FSBL.Clients.LauncherClient.getMonitorInfo({ monitor: "mine" });
|
|
141
140
|
if (err || !data) {
|
|
142
141
|
console.error(err);
|
|
@@ -153,6 +152,8 @@ export const NotificationsToasts = (props) => {
|
|
|
153
152
|
width: width,
|
|
154
153
|
},
|
|
155
154
|
});
|
|
155
|
+
// show the window after it bounds has been calculated
|
|
156
|
+
await finsembleWindow.show();
|
|
156
157
|
}
|
|
157
158
|
}
|
|
158
159
|
});
|