@sap-ux/control-property-editor 0.5.0 → 0.5.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/src/index.tsx CHANGED
@@ -10,8 +10,6 @@ import { initI18n } from './i18n';
10
10
  import './index.css';
11
11
  import App from './App';
12
12
  import { store } from './store';
13
- import type { ThemeName } from './components';
14
- import { setThemeOnDocument } from './components';
15
13
  import { registerAppIcons } from './icons';
16
14
  import { initializeLivereload, setProjectScenario } from './slice';
17
15
 
@@ -41,9 +39,6 @@ export function start(options: StartOptions): void {
41
39
  registerAppIcons();
42
40
  initIcons();
43
41
 
44
- const theme = localStorage.getItem('theme') ?? 'dark';
45
- setThemeOnDocument(theme as ThemeName);
46
-
47
42
  store.dispatch(setProjectScenario(scenario));
48
43
  store.dispatch(initializeLivereload({ port: options.livereloadPort, url: options.livereloadUrl }));
49
44
 
@@ -26,13 +26,14 @@ export function LeftPanel(): ReactElement {
26
26
  sizesAsPercents={true}
27
27
  animation={true}>
28
28
  <UISections.Section
29
- scrollable={true}
29
+ scrollable={false}
30
30
  layout={UISectionLayout.Standard}
31
31
  className="editor__outline"
32
32
  height="100%">
33
33
  <OutlinePanel />
34
34
  </UISections.Section>
35
35
  <UISections.Section
36
+ scrollable={false}
36
37
  layout={UISectionLayout.Standard}
37
38
  className="editor__outline"
38
39
  height="100%"
@@ -3,9 +3,6 @@
3
3
  padding: 15px 15px 15px 15px;
4
4
  flex-direction: row;
5
5
  align-items: center;
6
- position: sticky;
7
- top: 0px;
8
- z-index: 1;
9
6
  background-color: var(--vscode-sideBar-background);
10
7
  }
11
8
 
@@ -23,4 +20,4 @@
23
20
  .infoIcon {
24
21
  margin-left: 15px;
25
22
  margin-top: 5px;
26
- }
23
+ }
@@ -120,7 +120,7 @@ export function ChangesPanel(): ReactElement {
120
120
  onChange={onFilterChange}
121
121
  />
122
122
  </div>
123
- {renderChanges()}
123
+ <div className="app-panel-scroller auto-element-scroller">{renderChanges()}</div>
124
124
  </>
125
125
  );
126
126
  }
@@ -3,12 +3,13 @@
3
3
  padding: 15px 14px 15px 14px;
4
4
  flex-direction: row;
5
5
  align-items: center;
6
- position: sticky;
7
- top: 0px;
8
- z-index: 1;
9
6
  background-color: var(--vscode-sideBar-background);
10
7
  }
11
8
 
9
+ .auto-element-scroller {
10
+ height: calc(100% - 55px);
11
+ }
12
+
12
13
  .funnel-icon {
13
14
  margin-left: 16px;
14
15
  i {
@@ -22,6 +22,15 @@ interface OutlineNodeItem extends OutlineNode {
22
22
  }
23
23
 
24
24
  export const Tree = (): ReactElement => {
25
+ // padding + height of `Search` bar
26
+ const SEARCH_HEIGHT = 56;
27
+
28
+ // height of the tree row in a outline
29
+ const TREE_ROW_HEIGHT = 28;
30
+
31
+ // margin of the highlighted control from the top including `Search` bar height and tree row height, it doesn't include the height of main toolbar
32
+ const HIGHLIGHTED_CONTROL_TOP_MARGIN = SEARCH_HEIGHT + TREE_ROW_HEIGHT;
33
+
25
34
  const dispatch = useDispatch();
26
35
  const { t } = useTranslation();
27
36
 
@@ -74,8 +83,10 @@ export const Tree = (): ReactElement => {
74
83
  setTimeout(() => {
75
84
  // make sure that tree is fully rendered
76
85
  const rect = node.getBoundingClientRect();
77
- const outlineContainer = document.getElementsByClassName('section--scrollable')[0];
78
- if (rect.top <= 20 || rect.bottom >= outlineContainer?.clientHeight) {
86
+ const outlineContainer = document.getElementsByClassName('auto-element-scroller')[0];
87
+
88
+ // check if highlighted control is behind the `Search` bar or check if it is outside of viewport from bottom
89
+ if (rect.top <= HIGHLIGHTED_CONTROL_TOP_MARGIN || rect.bottom >= outlineContainer?.clientHeight) {
79
90
  node.scrollIntoView(true);
80
91
  }
81
92
  }, 0);
@@ -462,7 +473,7 @@ export const Tree = (): ReactElement => {
462
473
  };
463
474
 
464
475
  return (
465
- <div id="list-outline" className="app-panel-scroller">
476
+ <div id="list-outline" className="app-panel-scroller auto-element-scroller">
466
477
  <UIList
467
478
  {...listProp}
468
479
  items={items as never[]}
@@ -0,0 +1,19 @@
1
+ import type React from 'react';
2
+ import { useEffect } from 'react';
3
+ import { useLocalStorage } from './use-local-storage';
4
+
5
+ export type ThemeName = 'dark modern' | 'light modern' | 'high contrast black';
6
+ /**
7
+ * React hook that lets you read and update applications theme.
8
+ *
9
+ * @returns [theme, setTheme] [T, React.Dispatch<T>]
10
+ */
11
+ export function useTheme(): [ThemeName, React.Dispatch<ThemeName>] {
12
+ const [theme, setTheme] = useLocalStorage<ThemeName>('theme', 'dark modern');
13
+
14
+ useEffect(() => {
15
+ document.getElementsByTagName('HTML')[0].setAttribute('data-theme', theme);
16
+ }, [theme]);
17
+
18
+ return [theme, setTheme];
19
+ }
@@ -32,12 +32,12 @@ test('renders theme selector callout', () => {
32
32
  });
33
33
 
34
34
  test('check selected theme', () => {
35
- localStorage.setItem('theme', 'light');
35
+ localStorage.setItem('com.sap.ux.control-property-editor.theme', '"light modern"');
36
36
  render(<ThemeSelectorCallout />);
37
37
  screen.getByRole('button').click();
38
38
  const themeCalloutContent = screen.getAllByRole('button', { pressed: true });
39
39
  const pressedButton = themeCalloutContent.find((button) => button.getAttribute('aria-pressed') === 'true');
40
- expect(pressedButton?.getAttribute('id')).toStrictEqual('theme-light-rect');
40
+ expect(pressedButton?.getAttribute('id')).toStrictEqual('theme-light-modern-rect');
41
41
  });
42
42
 
43
43
  test('change theme to light', () => {
@@ -46,12 +46,12 @@ test('change theme to light', () => {
46
46
  screen.getByTitle('Light').click();
47
47
  const themeCalloutContent = screen.getAllByRole('button', { pressed: true });
48
48
  const pressedButton = themeCalloutContent.find((button) => button.getAttribute('aria-pressed') === 'true');
49
- expect(pressedButton?.getAttribute('id')).toStrictEqual('theme-light-rect');
50
- expect(localStorage.getItem('theme')).toStrictEqual('light');
49
+ expect(pressedButton?.getAttribute('id')).toStrictEqual('theme-light-modern-rect');
50
+ expect(localStorage.getItem('com.sap.ux.control-property-editor.theme')).toStrictEqual('"light modern"');
51
51
  });
52
52
 
53
53
  test('change theme to light and navigate via keyboard for dark to have focus', async () => {
54
- localStorage.setItem('theme', 'light');
54
+ localStorage.setItem('com.sap.ux.control-property-editor.theme', '"light modern"');
55
55
  // Use 'isVisible' property to make virtual nodes visible - 'isVisible' is used by fluent for testing purposes
56
56
  Object.defineProperty(HTMLElement.prototype, 'isVisible', {
57
57
  configurable: true,
@@ -75,7 +75,7 @@ test('change theme to light and navigate via keyboard for dark to have focus', a
75
75
  const darkButton = screen.getByTitle('Dark');
76
76
  expect(document.activeElement).toEqual(darkButton);
77
77
  // select focused theme
78
- expect(localStorage.getItem('theme')).toStrictEqual('light');
78
+ expect(localStorage.getItem('com.sap.ux.control-property-editor.theme')).toStrictEqual('"light modern"');
79
79
  triggerKeyDown('Enter', 13);
80
- expect(localStorage.getItem('theme')).toStrictEqual('dark');
80
+ expect(localStorage.getItem('com.sap.ux.control-property-editor.theme')).toStrictEqual('"dark modern"');
81
81
  });