orc-shared 5.10.1-dev.7 → 5.10.1-dev.9

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.
Files changed (133) hide show
  1. package/dist/components/Authenticate.js +41 -17
  2. package/dist/components/ErrorPlaceholder.js +8 -24
  3. package/dist/components/{Icon.js → Form/Inputs/MultiSelector.js} +33 -20
  4. package/dist/components/Form/Inputs/index.js +1 -1
  5. package/dist/components/LoadingIcon.js +6 -16
  6. package/dist/components/MaterialUI/Inputs/Select.js +10 -0
  7. package/dist/components/MaterialUI/Inputs/SelectProps.js +3 -1
  8. package/dist/components/MaterialUI/Navigation/DropDownMenu.js +2 -4
  9. package/dist/components/Provision.js +30 -13
  10. package/dist/components/Routing/SegmentPage.js +115 -56
  11. package/dist/components/Scope/ScopeNode.js +68 -45
  12. package/dist/components/Sidepanel.js +57 -23
  13. package/dist/components/Spritesheet.js +33 -17
  14. package/dist/components/Text.js +1 -60
  15. package/dist/components/Treeview/Branch.js +82 -20
  16. package/dist/components/Treeview/Label.js +108 -31
  17. package/dist/components/Treeview/Leaf.js +56 -12
  18. package/dist/components/Treeview/Node.js +22 -9
  19. package/dist/components/Treeview/index.js +7 -1
  20. package/dist/components/Treeview/settings.js +7 -5
  21. package/dist/utils/index.js +0 -4
  22. package/dist/utils/testUtils.js +1 -12
  23. package/package.json +1 -1
  24. package/src/components/ApplicationModuleLoader.test.js +14 -27
  25. package/src/components/Authenticate.js +29 -21
  26. package/src/components/Authenticate.test.js +18 -27
  27. package/src/components/ErrorPlaceholder.js +4 -21
  28. package/src/components/ErrorPlaceholder.test.js +7 -14
  29. package/src/components/Form/InputField.test.js +2 -1
  30. package/src/components/Form/Inputs/MultiSelector.js +23 -0
  31. package/src/components/Form/Inputs/MultiSelector.test.js +112 -0
  32. package/src/components/Form/Inputs/index.js +1 -1
  33. package/src/components/Loader.test.js +21 -33
  34. package/src/components/LoadingIcon.js +2 -15
  35. package/src/components/LoadingIcon.test.js +2 -20
  36. package/src/components/MaterialUI/DataDisplay/Table.test.js +1 -1
  37. package/src/components/MaterialUI/Inputs/Select.js +7 -0
  38. package/src/components/MaterialUI/Inputs/Select.test.js +45 -0
  39. package/src/components/MaterialUI/Inputs/SelectProps.js +2 -0
  40. package/src/components/MaterialUI/Inputs/SelectProps.test.js +2 -0
  41. package/src/components/MaterialUI/Navigation/DropDownMenu.js +2 -2
  42. package/src/components/MaterialUI/Navigation/DropDownMenu.test.js +5 -6
  43. package/src/components/Navigation/Navigation.test.js +0 -5
  44. package/src/components/Navigation/useNavigationState.test.js +79 -222
  45. package/src/components/Provision.js +36 -42
  46. package/src/components/Provision.test.js +10 -26
  47. package/src/components/Routing/SegmentPage.js +68 -52
  48. package/src/components/Routing/SegmentPage.test.js +4 -12
  49. package/src/components/Scope/ScopeNode.js +61 -54
  50. package/src/components/Scope/ScopeNode.test.js +61 -154
  51. package/src/components/ScopeExtendedConfigurationLoader.test.js +1 -4
  52. package/src/components/Sidepanel.js +38 -32
  53. package/src/components/Sidepanel.test.js +49 -27
  54. package/src/components/Spritesheet.js +23 -21
  55. package/src/components/Spritesheet.test.js +10 -10
  56. package/src/components/Text.js +0 -49
  57. package/src/components/Treeview/Branch.js +63 -45
  58. package/src/components/Treeview/Branch.test.js +21 -24
  59. package/src/components/Treeview/Label.js +66 -52
  60. package/src/components/Treeview/Label.test.js +42 -60
  61. package/src/components/Treeview/Leaf.js +41 -22
  62. package/src/components/Treeview/Leaf.test.js +15 -10
  63. package/src/components/Treeview/Node.js +16 -9
  64. package/src/components/Treeview/Node.test.js +269 -200
  65. package/src/components/Treeview/Treeview.test.js +248 -248
  66. package/src/components/Treeview/index.js +6 -0
  67. package/src/components/Treeview/settings.js +7 -6
  68. package/src/utils/index.js +0 -4
  69. package/src/utils/testUtils.js +0 -10
  70. package/src/utils/testUtils.test.js +0 -68
  71. package/dist/components/Button.js +0 -70
  72. package/dist/components/Checkbox.js +0 -103
  73. package/dist/components/IconButton.js +0 -80
  74. package/dist/components/Input.js +0 -101
  75. package/dist/components/Modal/Background.js +0 -55
  76. package/dist/components/Modal/Dialog.js +0 -75
  77. package/dist/components/Modal/Wrapper.js +0 -69
  78. package/dist/components/Modal/index.js +0 -86
  79. package/dist/components/MultiSelector.js +0 -187
  80. package/dist/components/Navigation/Bar.js +0 -293
  81. package/dist/components/Navigation/Tab.js +0 -182
  82. package/dist/components/Placeholder.js +0 -114
  83. package/dist/components/Scope/Selector.js +0 -123
  84. package/dist/components/Selector.js +0 -185
  85. package/dist/components/Switch.js +0 -128
  86. package/dist/components/Toolbar.js +0 -227
  87. package/dist/components/Tooltip.js +0 -66
  88. package/dist/getTheme.js +0 -153
  89. package/dist/getThemeOverrides.js +0 -93
  90. package/dist/hocs/withAuthentication.js +0 -72
  91. package/dist/utils/styledPropFuncs.js +0 -88
  92. package/src/components/Button.js +0 -90
  93. package/src/components/Button.test.js +0 -49
  94. package/src/components/Checkbox.js +0 -63
  95. package/src/components/Checkbox.test.js +0 -122
  96. package/src/components/Icon.js +0 -18
  97. package/src/components/IconButton.js +0 -30
  98. package/src/components/IconButton.test.js +0 -61
  99. package/src/components/Input.js +0 -35
  100. package/src/components/Input.test.js +0 -34
  101. package/src/components/Modal/Background.js +0 -10
  102. package/src/components/Modal/Dialog.js +0 -27
  103. package/src/components/Modal/Dialog.test.js +0 -20
  104. package/src/components/Modal/Modal.test.js +0 -52
  105. package/src/components/Modal/Wrapper.js +0 -32
  106. package/src/components/Modal/Wrapper.test.js +0 -55
  107. package/src/components/Modal/index.js +0 -22
  108. package/src/components/MultiSelector.js +0 -104
  109. package/src/components/MultiSelector.test.js +0 -348
  110. package/src/components/Navigation/Bar.js +0 -212
  111. package/src/components/Navigation/Bar.test.js +0 -552
  112. package/src/components/Navigation/Tab.js +0 -156
  113. package/src/components/Navigation/Tab.test.js +0 -404
  114. package/src/components/Placeholder.js +0 -61
  115. package/src/components/Placeholder.test.js +0 -106
  116. package/src/components/Scope/Selector.js +0 -70
  117. package/src/components/Scope/Selector.test.js +0 -138
  118. package/src/components/Selector.js +0 -191
  119. package/src/components/Selector.test.js +0 -157
  120. package/src/components/Switch.js +0 -112
  121. package/src/components/Switch.test.js +0 -130
  122. package/src/components/Text.test.js +0 -132
  123. package/src/components/Toolbar.js +0 -178
  124. package/src/components/Toolbar.test.js +0 -478
  125. package/src/components/Tooltip.js +0 -51
  126. package/src/components/Tooltip.test.js +0 -21
  127. package/src/getTheme.js +0 -98
  128. package/src/getTheme.test.js +0 -92
  129. package/src/getThemeOverrides.js +0 -27
  130. package/src/hocs/withAuthentication.js +0 -18
  131. package/src/hocs/withAuthentication.test.js +0 -120
  132. package/src/utils/styledPropFuncs.js +0 -20
  133. package/src/utils/styledPropFuncs.test.js +0 -166
@@ -1,552 +0,0 @@
1
- import React, { useRef, useEffect } from "react";
2
- import ReactDOM from "react-dom";
3
- import { IntlProvider } from "react-intl";
4
- import { act } from "react-dom/test-utils";
5
- import { Provider } from "react-redux";
6
- import { MemoryRouter, Router } from "react-router-dom";
7
- import { createMemoryHistory } from "history";
8
- import sinon from "sinon";
9
- import { StylesProvider } from "@material-ui/core";
10
- import { getStyledClassSelector, generateClassName } from "../../utils/testUtils";
11
- import Tab, { PageTab } from "./Tab";
12
- import Bar, { TabBar, ScrollableBar, InnerBar, useTabScroll, StyledMenu, MenuButton } from "./Bar";
13
-
14
- describe("Bar", () => {
15
- let closers;
16
- beforeEach(() => {
17
- closers = [0, 1, 2, 3].map(id => sinon.spy().named("close" + id));
18
- });
19
-
20
- it("renders a bar containing tabs", () =>
21
- expect(
22
- <Provider
23
- store={{
24
- subscribe: () => {},
25
- dispatch: () => {},
26
- getState: () => ({}),
27
- }}
28
- >
29
- <MemoryRouter>
30
- <IntlProvider locale="en">
31
- <Bar
32
- module={{
33
- icon: "test",
34
- label: "A module",
35
- href: "/Foo/modu",
36
- mappedFrom: "/Foo/modu",
37
- }}
38
- pages={[
39
- {
40
- href: "/Foo/modu/1",
41
- mappedFrom: "/Foo/modu/1",
42
- label: "Page 1",
43
- mustTruncate: true,
44
- close: closers[0],
45
- },
46
- {
47
- href: "/Foo/modu/2",
48
- mappedFrom: "/Foo/modu/2",
49
- label: "Page 2",
50
- close: closers[1],
51
- active: true,
52
- },
53
- {
54
- href: "/Foo/modu/3",
55
- mappedFrom: "/Foo/modu/3",
56
- label: "Page 3",
57
- close: closers[2],
58
- },
59
- {
60
- href: "/Foo/modu/4",
61
- mappedFrom: "/Foo/modu/4",
62
- label: "Page 4",
63
- close: closers[3],
64
- },
65
- ]}
66
- />
67
- </IntlProvider>
68
- </MemoryRouter>
69
- </Provider>,
70
- "when mounted",
71
- "to satisfy",
72
- <Provider
73
- store={{
74
- subscribe: () => {},
75
- dispatch: () => {},
76
- getState: () => ({}),
77
- }}
78
- >
79
- <MemoryRouter>
80
- <IntlProvider locale="en">
81
- <TabBar>
82
- <Tab key="/Foo/modu" module icon="test" href="/Foo/modu" mappedFrom="/Foo/modu" label="A module" />
83
- <ScrollableBar>
84
- <Tab
85
- key="/Foo/modu/1"
86
- href="/Foo/modu/1"
87
- mappedFrom="/Foo/modu/1"
88
- label="Page 1"
89
- close={closers[0]}
90
- mustTruncate={true}
91
- hide={false}
92
- />
93
- <Tab
94
- key="/Foo/modu/2"
95
- href="/Foo/modu/2"
96
- mappedFrom="/Foo/modu/2"
97
- label="Page 2"
98
- close={closers[1]}
99
- hide={false}
100
- active
101
- />
102
- <Tab
103
- key="/Foo/modu/3"
104
- href="/Foo/modu/3"
105
- mappedFrom="/Foo/modu/3"
106
- label="Page 3"
107
- close={closers[2]}
108
- hide={false}
109
- />
110
- <Tab
111
- key="/Foo/modu/4"
112
- href="/Foo/modu/4"
113
- mappedFrom="/Foo/modu/4"
114
- label="Page 4"
115
- close={closers[3]}
116
- hide={false}
117
- />
118
- </ScrollableBar>
119
- </TabBar>
120
- </IntlProvider>
121
- </MemoryRouter>
122
- </Provider>,
123
- ));
124
-
125
- it("renders a bar containing only module", () =>
126
- expect(
127
- <Provider
128
- store={{
129
- subscribe: () => {},
130
- dispatch: () => {},
131
- getState: () => ({}),
132
- }}
133
- >
134
- <MemoryRouter>
135
- <IntlProvider locale="en">
136
- <Bar
137
- module={{
138
- icon: "test",
139
- label: "A module",
140
- href: "/Foo/modu",
141
- mappedFrom: "/Foo/modu",
142
- active: true,
143
- }}
144
- pages={[]}
145
- />
146
- </IntlProvider>
147
- </MemoryRouter>
148
- </Provider>,
149
- "when mounted",
150
- "to satisfy",
151
- <Provider
152
- store={{
153
- subscribe: () => {},
154
- dispatch: () => {},
155
- getState: () => ({}),
156
- }}
157
- >
158
- <MemoryRouter>
159
- <IntlProvider locale="en">
160
- <TabBar>
161
- <Tab key="/Foo/modu" module icon="test" href="/Foo/modu" mappedFrom="/Foo/modu" label="A module" active />
162
- <ScrollableBar />
163
- </TabBar>
164
- </IntlProvider>
165
- </MemoryRouter>
166
- </Provider>,
167
- ));
168
-
169
- it("hides tabs and shows dropdown when scrollable bar is too narrow to show them all", () => {
170
- // Needs to be fully rendered to work
171
- const root = document.createElement("div");
172
- document.body.append(root);
173
- const history = createMemoryHistory();
174
- sinon.spy(history, "push");
175
- ReactDOM.render(
176
- <Provider
177
- store={{
178
- subscribe: () => {},
179
- dispatch: () => {},
180
- getState: () => ({}),
181
- }}
182
- >
183
- <Router history={history}>
184
- <StylesProvider generateClassName={generateClassName}>
185
- <IntlProvider locale="en">
186
- <Bar
187
- module={{
188
- icon: "test",
189
- label: "A module",
190
- href: "/Foo/modu",
191
- mappedFrom: "/Foo/modu",
192
- }}
193
- pages={[
194
- {
195
- href: "/Foo/modu/1",
196
- mappedFrom: "/Foo/modu/1",
197
- label: "Page 1",
198
- close: closers[0],
199
- },
200
- {
201
- href: "/Foo/modu/2",
202
- mappedFrom: "/Foo/modu/2",
203
- label: "Page 2",
204
- close: closers[1],
205
- },
206
- {
207
- href: "/Foo/modu/3",
208
- mappedFrom: "/Foo/modu/3",
209
- label: "Page 3",
210
- close: closers[2],
211
- },
212
- {
213
- href: "/Foo/modu/4",
214
- mappedFrom: "/Foo/modu/4",
215
- label: "Page 4",
216
- close: closers[3],
217
- },
218
- ]}
219
- />
220
- </IntlProvider>
221
- </StylesProvider>
222
- </Router>
223
- </Provider>,
224
- root,
225
- );
226
- const bar = root.querySelector("*"); // Get the first child
227
- const barElement = bar.querySelector(getStyledClassSelector(InnerBar));
228
- const tabElements = barElement.querySelectorAll(getStyledClassSelector(PageTab));
229
- act(() => {
230
- // XXX: This is a nasty hack of jsdom, and may break unexpectedly
231
- Object.defineProperty(barElement, "offsetWidth", {
232
- value: 300,
233
- writable: true,
234
- });
235
- tabElements.forEach(tab => {
236
- Object.defineProperty(tab, "offsetWidth", {
237
- value: 130,
238
- });
239
- });
240
- window.dispatchEvent(new Event("resize"));
241
- });
242
- try {
243
- expect(
244
- bar,
245
- "to satisfy",
246
- <Provider
247
- store={{
248
- subscribe: () => {},
249
- dispatch: () => {},
250
- getState: () => ({}),
251
- }}
252
- >
253
- <MemoryRouter>
254
- <StylesProvider generateClassName={generateClassName}>
255
- <IntlProvider locale="en">
256
- <TabBar>
257
- <Tab key="/Foo/modu" module icon="test" href="/Foo/modu" mappedFrom="/Foo/modu" label="A module" />
258
- <ScrollableBar>
259
- <Tab
260
- key="/Foo/modu/1"
261
- href="/Foo/modu/1"
262
- mappedFrom="/Foo/modu/1"
263
- label="Page 1"
264
- close={closers[0]}
265
- hide={false}
266
- />
267
- <Tab
268
- key="/Foo/modu/2"
269
- href="/Foo/modu/2"
270
- mappedFrom="/Foo/modu/2"
271
- label="Page 2"
272
- close={closers[1]}
273
- hide={false}
274
- />
275
- <Tab
276
- key="/Foo/modu/3"
277
- href="/Foo/modu/3"
278
- mappedFrom="/Foo/modu/3"
279
- label="Page 3"
280
- close={closers[2]}
281
- hide={true}
282
- />
283
- <Tab
284
- key="/Foo/modu/4"
285
- href="/Foo/modu/4"
286
- mappedFrom="/Foo/modu/4"
287
- label="Page 4"
288
- close={closers[3]}
289
- hide={true}
290
- />
291
- </ScrollableBar>
292
- <StyledMenu
293
- id="navigationTabs"
294
- menuItems={[
295
- { label: "Page 1", id: "/Foo/modu/1" },
296
- { label: "Page 2", id: "/Foo/modu/2" },
297
- { label: "Page 3", id: "/Foo/modu/3" },
298
- { label: "Page 4", id: "/Foo/modu/4" },
299
- ]}
300
- >
301
- <MenuButton />
302
- </StyledMenu>
303
- </TabBar>
304
- </IntlProvider>
305
- </StylesProvider>
306
- </MemoryRouter>
307
- </Provider>,
308
- );
309
- expect(history.push, "was not called");
310
- act(() => bar.querySelector("#navigationTabsAnchor").click());
311
- expect(bar, "queried for first", "ul", "to have text", "Page 1Page 2Page 3Page 4"); // Menu is showing
312
- act(() => bar.querySelector("#\\/Foo\\/modu\\/3").click());
313
- expect(history.push, "to have calls satisfying", [{ args: ["/Foo/modu/3"] }]);
314
- } finally {
315
- ReactDOM.unmountComponentAtNode(root);
316
- document.body.removeChild(root);
317
- }
318
- });
319
- });
320
-
321
- describe("useTabScroll", () => {
322
- // XXX: BE ADVISED!
323
- // These tests rely on hacking jsdom's representation of layout
324
- // jsdom changes may break these!
325
- const ScrollTest = ({ pages, bar, tabs }) => {
326
- const barRef = useRef(null);
327
- const tabRefs = useRef({});
328
- useEffect(() => {
329
- Object.defineProperty(barRef.current, "offsetWidth", {
330
- value: bar || 0,
331
- writable: true,
332
- });
333
- Object.defineProperty(barRef.current, "scrollLeft", {
334
- value: 0,
335
- writable: true,
336
- });
337
- if (tabs) {
338
- pages.forEach(({ href }, idx) => {
339
- Object.defineProperty(tabRefs.current[href], "offsetWidth", {
340
- value: tabs[idx] || 0,
341
- });
342
- });
343
- }
344
- }, [pages, bar, tabs]);
345
- const { barWidth, tabEdges, lastShownTab, getTabRef, getBarRef } = useTabScroll(
346
- pages,
347
- true, // Debug flag
348
- { barRef, tabRefs },
349
- );
350
- return (
351
- <div id="outerElement">
352
- <InnerBar ref={getBarRef} data-width={barWidth}>
353
- {pages.map(({ href }, idx) => (
354
- <PageTab key={href} ref={getTabRef} data-href={href} data-edge={tabEdges[idx]} />
355
- ))}
356
- </InnerBar>
357
- Last shown tab: {lastShownTab}
358
- </div>
359
- );
360
- };
361
-
362
- let setupTest, root;
363
- beforeEach(() => {
364
- root = document.createElement("div");
365
- document.body.append(root);
366
- setupTest = (pages, widths) => {
367
- ReactDOM.render(
368
- <MemoryRouter>
369
- <ScrollTest pages={pages} {...widths} />
370
- </MemoryRouter>,
371
- root,
372
- );
373
- const element = root.querySelector("div#outerElement");
374
- const barElement = element.querySelector(getStyledClassSelector(InnerBar));
375
- const tabElements = barElement.querySelectorAll(getStyledClassSelector(PageTab));
376
- const setBarWidth = (width = 0) => {
377
- act(() => {
378
- barElement.offsetWidth = width;
379
- window.dispatchEvent(new Event("resize"));
380
- });
381
- };
382
- return { element, barElement, tabElements, setBarWidth };
383
- };
384
- });
385
- afterEach(() => {
386
- ReactDOM.unmountComponentAtNode(root);
387
- document.body.removeChild(root);
388
- });
389
-
390
- describe("test functions", () => {
391
- it("renders a bar with tabs", () => {
392
- const { element } = setupTest([{ href: "foo" }, { href: "bar" }]);
393
- expect(
394
- element,
395
- "to contain",
396
- <InnerBar>
397
- <PageTab data-href="foo" />
398
- <PageTab data-href="bar" />
399
- </InnerBar>,
400
- ).and("to have text", "Last shown tab: 2");
401
- });
402
-
403
- it("can set widths", () => {
404
- const { barElement, tabElements } = setupTest(
405
- [{ href: "foo" }, { href: "bar" }, { href: "bell" }, { href: "lerp" }],
406
- {
407
- bar: 100,
408
- tabs: [20, 25],
409
- },
410
- );
411
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
412
- expect(barElement, "to have property", "offsetWidth", 100);
413
- expect(tabElements[0], "to have property", "offsetWidth", 20);
414
- expect(tabElements[1], "to have property", "offsetWidth", 25);
415
- expect(tabElements[2], "to have property", "offsetWidth", 0);
416
- expect(tabElements[3], "to have property", "offsetWidth", 0);
417
- });
418
- });
419
-
420
- it("can reset bar width", () => {
421
- const { barElement, setBarWidth } = setupTest(
422
- [{ href: "foo" }, { href: "bar" }, { href: "bell" }, { href: "lerp" }],
423
- {
424
- bar: 100,
425
- tabs: [50, 50, 50, 50],
426
- },
427
- );
428
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
429
- expect(barElement, "to have property", "offsetWidth", 100);
430
- setBarWidth(170);
431
- expect(barElement, "to have property", "offsetWidth", 170);
432
- });
433
- });
434
-
435
- it("fires resize event if bar size reset", () => {
436
- const { setBarWidth } = setupTest([{ href: "foo" }, { href: "bar" }, { href: "bell" }, { href: "lerp" }], {
437
- bar: 100,
438
- tabs: [50, 50, 50, 50],
439
- });
440
- const handler = sinon.spy().named("resizeHandler");
441
- window.addEventListener("resize", handler);
442
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
443
- try {
444
- setBarWidth(170);
445
- expect(handler, "was called once");
446
- } finally {
447
- window.removeEventListener("resize", handler);
448
- }
449
- });
450
- });
451
- });
452
-
453
- it("sets its width state", () => {
454
- const { element } = setupTest(
455
- [{ href: "foo" }, { href: "bar" }, { href: "bell" }, { href: "lerp", active: true }],
456
- {
457
- bar: 200,
458
- tabs: [75, 52, 65, 35],
459
- },
460
- );
461
- expect(
462
- element,
463
- "to contain",
464
- <InnerBar data-width="200">
465
- <PageTab data-href="foo" data-edge={75} />
466
- <PageTab data-href="bar" data-edge={75 + 52} />
467
- <PageTab data-href="bell" data-edge={75 + 52 + 65} />
468
- <PageTab data-href="lerp" data-edge={75 + 52 + 65 + 35} />
469
- </InnerBar>,
470
- );
471
- });
472
-
473
- it("scrolls one tab past the active element if possible", () => {
474
- const { barElement } = setupTest(
475
- [{ href: "foo" }, { href: "bar" }, { href: "bell", active: true }, { href: "lerp" }],
476
- {
477
- bar: 150,
478
- tabs: [75, 52, 65, 35],
479
- },
480
- );
481
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
482
- expect(barElement.scrollLeft, "to equal", 75 + 52 + 65 + 35 - 150 + 7);
483
- });
484
- });
485
-
486
- it("scrolls to the active element if it is last", () => {
487
- const { barElement } = setupTest(
488
- [{ href: "foo" }, { href: "bar" }, { href: "bell" }, { href: "lerp", active: true }],
489
- {
490
- bar: 150,
491
- tabs: [75, 52, 65, 35],
492
- },
493
- );
494
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
495
- expect(barElement.scrollLeft, "to equal", 75 + 52 + 65 + 35 - 150 + 7);
496
- });
497
- });
498
-
499
- it("sets last shown tab if bar wide enough to hold all", () => {
500
- const { element } = setupTest(
501
- [{ href: "foo" }, { href: "bar", active: true }, { href: "bell" }, { href: "lerp" }, { href: "meep" }],
502
- {
503
- bar: 300,
504
- tabs: [50, 50, 50, 50, 50],
505
- },
506
- );
507
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
508
- expect(element, "to have text", "Last shown tab: 5");
509
- });
510
- });
511
-
512
- it("sets last shown tab according to how many will fit on screen", () => {
513
- const { element } = setupTest(
514
- [{ href: "foo", active: true }, { href: "bar" }, { href: "bell" }, { href: "lerp" }, { href: "meep" }],
515
- {
516
- bar: 400,
517
- tabs: [120, 120, 120, 120, 120],
518
- },
519
- );
520
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
521
- expect(element, "to have text", "Last shown tab: 2");
522
- });
523
- });
524
-
525
- it("sets last shown tab to make sure active tab + next tab are shown", () => {
526
- const { element } = setupTest(
527
- [{ href: "foo" }, { href: "bar" }, { href: "bell", active: true }, { href: "lerp" }, { href: "meep" }],
528
- {
529
- bar: 300,
530
- tabs: [120, 120, 120, 120, 120],
531
- },
532
- );
533
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
534
- expect(element, "to have text", "Last shown tab: 3");
535
- });
536
- });
537
-
538
- it("changes last shown tab if bar is resized", () => {
539
- const { element, setBarWidth } = setupTest(
540
- [{ href: "foo", active: true }, { href: "bar" }, { href: "bell" }, { href: "lerp" }, { href: "meep" }],
541
- {
542
- bar: 400,
543
- tabs: [120, 120, 120, 120, 120],
544
- },
545
- );
546
- return new Promise(resolve => setTimeout(resolve, 10)).then(() => {
547
- expect(element, "to have text", "Last shown tab: 2");
548
- setBarWidth(500);
549
- expect(element, "to have text", "Last shown tab: 3");
550
- });
551
- });
552
- });
@@ -1,156 +0,0 @@
1
- import React, { useEffect, useRef, useState } from "react";
2
- import styled, { css } from "styled-components";
3
- import { getThemeProp, ifFlag } from "../../utils";
4
- import { Link } from "react-router-dom";
5
- import Icon from "../Icon";
6
- import useLabelMessage from "../../hooks/useLabelMessage";
7
- import { Placeholder } from "../Text";
8
- import { useIntl } from "react-intl";
9
-
10
- export const PageTab = styled.div`
11
- flex: 0 0 auto;
12
- overflow: hidden;
13
- height: 38px;
14
- border: 1px solid ${getThemeProp(["colors", "borderLight"], "#cccccc")};
15
- border-top-left-radius: 5px;
16
- border-top-right-radius: 5px;
17
- margin-left: -1px;
18
- background-color: white;
19
-
20
- ${ifFlag(
21
- "active",
22
- css`
23
- border-bottom-color: white;
24
- color: ${getThemeProp(["colors", "application", "base"], "#ccc")};
25
- `,
26
- css`
27
- color: ${getThemeProp(["colors", "textMedium"], "#999999")};
28
- `,
29
- )};
30
-
31
- ${ifFlag(
32
- "outsideScope",
33
- css`
34
- background-color: #eeeeee;
35
- `,
36
- )}
37
-
38
- ${ifFlag(
39
- "hide",
40
- css`
41
- visibility: hidden;
42
- `,
43
- )}
44
- `;
45
-
46
- // XXX: The below contains an IE10/IE11 targeting CSS hack
47
-
48
- export const ModuleTab = styled(PageTab)`
49
- flex-grow: 0;
50
- flex-shrink: 0;
51
- margin-left: 0px;
52
- z-index: 1;
53
- @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
54
- flex-grow: 1;
55
- }
56
- `;
57
-
58
- const FilteredLink = ({ outsideScope, mustTruncate, ...props }) => <Link {...props} />;
59
-
60
- export const TabLink = styled(FilteredLink)`
61
- min-width: 100px;
62
- overflow: hidden;
63
- color: inherit;
64
- text-decoration: none;
65
- display: flex;
66
- justify-content: center;
67
- padding: 11px 15px;
68
-
69
- ${ifFlag(
70
- "outsideScope",
71
- css`
72
- cursor: not-allowed;
73
- `,
74
- )};
75
- ${ifFlag(
76
- "mustTruncate",
77
- css`
78
- max-width: 220px;
79
- `,
80
- )};
81
- `;
82
-
83
- export const ModuleIcon = styled(Icon)`
84
- vertical-align: middle;
85
- font-size: 20px;
86
- margin-right: 10px;
87
- margin-top: -3px;
88
- `;
89
-
90
- export const TabText = styled.span`
91
- min-width: 50px;
92
- white-space: nowrap;
93
- overflow: hidden;
94
- text-overflow: ellipsis;
95
- `;
96
-
97
- export const CloseIcon = styled(Icon).attrs(props => ({
98
- id: getThemeProp(["icons", "close"], "close")(props),
99
- }))`
100
- flex: 0 0 auto;
101
- margin-left: 10px;
102
- margin-right: -5px;
103
- font-size: 14px;
104
- color: ${getThemeProp(["colors", "textMedium"], "#999999")};
105
-
106
- &:hover {
107
- color: ${getThemeProp(["colors", "application", "base"], "#ccc")};
108
- }
109
- `;
110
-
111
- const Tab = (
112
- { href, label, mustTruncate, icon, module, active, close = () => {}, outsideScope, scopeNotSupported, hide },
113
- ref,
114
- ) => {
115
- const ThisTab = module ? ModuleTab : PageTab;
116
-
117
- const { formatMessage } = useIntl();
118
- const tabTextRef = useRef(null);
119
- const [aTitle, setTitle] = useState(null);
120
- const buildMessage = message => formatMessage(message, message.values);
121
- const [labelMessage] = useLabelMessage(label, buildMessage);
122
-
123
- useEffect(() => {
124
- if (scopeNotSupported) {
125
- close();
126
- } else if (mustTruncate && tabTextRef.current && tabTextRef.current.offsetWidth < tabTextRef.current.scrollWidth) {
127
- setTitle(labelMessage);
128
- }
129
- }, [scopeNotSupported, tabTextRef, setTitle, labelMessage, mustTruncate, close]);
130
-
131
- return (
132
- <ThisTab ref={ref} active={active} outsideScope={outsideScope} hide={hide || scopeNotSupported} data-href={href}>
133
- <TabLink
134
- to={href}
135
- mustTruncate={mustTruncate}
136
- outsideScope={outsideScope}
137
- onClick={
138
- outsideScope
139
- ? event => {
140
- event.preventDefault();
141
- event.stopPropagation();
142
- }
143
- : () => {}
144
- }
145
- >
146
- {module ? <ModuleIcon id={icon} /> : null}
147
- <TabText ref={tabTextRef} title={aTitle}>
148
- {labelMessage ? labelMessage : <Placeholder />}
149
- </TabText>
150
- {module ? null : <CloseIcon onClick={close} />}
151
- </TabLink>
152
- </ThisTab>
153
- );
154
- };
155
-
156
- export default React.forwardRef(Tab);