@splunk/react-ui 5.4.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/AnchorMenu.d.ts +2 -0
  2. package/AnchorMenu.js +286 -0
  3. package/Badge.d.ts +2 -0
  4. package/Badge.js +154 -0
  5. package/CHANGELOG.md +42 -0
  6. package/Code.js +1097 -500
  7. package/Color.js +142 -141
  8. package/ComboBox.js +6 -5
  9. package/Link.js +74 -44
  10. package/MIGRATION.md +32 -1
  11. package/Menu.js +41 -43
  12. package/Multiselect.js +615 -2156
  13. package/Number.js +3 -3
  14. package/PhoneNumber.d.ts +2 -0
  15. package/PhoneNumber.js +769 -0
  16. package/Popover.js +73 -75
  17. package/RadioList.js +166 -151
  18. package/ResultsMenu.js +27 -29
  19. package/Select.js +179 -1768
  20. package/SelectBase.d.ts +2 -0
  21. package/SelectBase.js +1714 -0
  22. package/Slider.js +358 -302
  23. package/SlidingPanels.js +55 -62
  24. package/Switch.js +42 -27
  25. package/TabBar.js +295 -294
  26. package/TabLayout.js +14 -14
  27. package/Table.js +1087 -1040
  28. package/TransitionOpen.js +65 -58
  29. package/cypress/support/commands.ts +40 -0
  30. package/cypress/support/component.ts +1 -1
  31. package/cypress/support/index.d.ts +22 -0
  32. package/docker-compose.yml +99 -52
  33. package/package.json +9 -5
  34. package/stubs-splunkui.d.ts +0 -86
  35. package/test-runner-jest.config.js +1 -0
  36. package/types/src/AnchorMenu/AnchorMenu.d.ts +36 -0
  37. package/types/src/AnchorMenu/AnchorMenuContext.d.ts +6 -0
  38. package/types/src/AnchorMenu/Item.d.ts +35 -0
  39. package/types/src/AnchorMenu/docs/examples/Basic.d.ts +6 -0
  40. package/types/src/AnchorMenu/index.d.ts +3 -0
  41. package/types/src/Badge/Badge.d.ts +29 -0
  42. package/types/src/Badge/docs/examples/Basic.d.ts +5 -0
  43. package/types/src/Badge/docs/examples/Count.d.ts +6 -0
  44. package/types/src/Badge/docs/examples/CustomColors.d.ts +8 -0
  45. package/types/src/Badge/docs/examples/Icon.d.ts +6 -0
  46. package/types/src/Badge/index.d.ts +2 -0
  47. package/types/src/Code/Code.d.ts +4 -3
  48. package/types/src/Code/index.d.ts +1 -0
  49. package/types/src/Link/Link.d.ts +4 -0
  50. package/types/src/Link/LinkContext.d.ts +14 -0
  51. package/types/src/Link/docs/examples/Visited.d.ts +7 -0
  52. package/types/src/Link/index.d.ts +1 -0
  53. package/types/src/Menu/Item.d.ts +1 -1
  54. package/types/src/Multiselect/Compact.d.ts +8 -1
  55. package/types/src/Multiselect/Multiselect.d.ts +8 -1
  56. package/types/src/PhoneNumber/PhoneNumber.d.ts +139 -0
  57. package/types/src/PhoneNumber/docs/examples/Controlled.d.ts +7 -0
  58. package/types/src/PhoneNumber/docs/examples/DefaultCountry.d.ts +7 -0
  59. package/types/src/PhoneNumber/docs/examples/Disabled.d.ts +6 -0
  60. package/types/src/PhoneNumber/docs/examples/Error.d.ts +6 -0
  61. package/types/src/PhoneNumber/docs/examples/Inline.d.ts +7 -0
  62. package/types/src/PhoneNumber/docs/examples/Uncontrolled.d.ts +7 -0
  63. package/types/src/PhoneNumber/index.d.ts +2 -0
  64. package/types/src/PhoneNumber/utils.d.ts +47 -0
  65. package/types/src/RadioList/Option.d.ts +6 -1
  66. package/types/src/RadioList/docs/examples/Description.d.ts +6 -0
  67. package/types/src/Select/Option.d.ts +8 -3
  68. package/types/src/Select/Select.d.ts +1 -1
  69. package/types/src/{Select → SelectBase}/OptionBase.d.ts +8 -2
  70. package/types/src/{Select → SelectBase}/SelectBase.d.ts +11 -2
  71. package/types/src/SelectBase/index.d.ts +2 -0
  72. package/types/src/Slider/Slider.d.ts +7 -1
  73. package/types/src/Switch/Switch.d.ts +4 -1
  74. package/types/src/Table/Body.d.ts +6 -1
  75. package/types/src/Table/Cell.d.ts +5 -1
  76. package/types/src/Table/Head.d.ts +6 -2
  77. package/types/src/Table/HeadCell.d.ts +5 -1
  78. package/types/src/Table/Row.d.ts +5 -1
  79. package/types/src/Table/Table.d.ts +20 -1
  80. package/types/src/Table/TableContext.d.ts +1 -0
  81. package/types/src/Table/docs/examples/HorizontalOverflowScroll.d.ts +8 -0
  82. package/types/src/Table/docs/examples/PinActionColumn.d.ts +7 -0
  83. package/types/src/TransitionOpen/TransitionOpen.d.ts +3 -1
  84. package/types/src/useResizeObserver/useResizeObserver.d.ts +2 -0
  85. package/types/src/useRovingFocus/useRovingFocus.d.ts +8 -1
  86. package/usePrevious.d.ts +2 -0
  87. package/useResizeObserver.js +59 -92
  88. package/useRovingFocus.js +96 -41
  89. /package/types/src/{Select → SelectBase}/SelectAllOption.d.ts +0 -0
package/TransitionOpen.js CHANGED
@@ -181,9 +181,9 @@
181
181
  function k(e) {
182
182
  if (Array.isArray(e)) return e;
183
183
  }
184
- function x(e, t) {
184
+ function F(e, t) {
185
185
  if (null == e) return {};
186
- var r, n, o = F(e, t);
186
+ var r, n, o = x(e, t);
187
187
  if (Object.getOwnPropertySymbols) {
188
188
  var i = Object.getOwnPropertySymbols(e);
189
189
  for (n = 0; n < i.length; n++) {
@@ -192,7 +192,7 @@
192
192
  }
193
193
  return o;
194
194
  }
195
- function F(e, t) {
195
+ function x(e, t) {
196
196
  if (null == e) return {};
197
197
  var r = {};
198
198
  for (var n in e) {
@@ -217,26 +217,26 @@
217
217
  for (var t = 1; t < arguments.length; t++) {
218
218
  var r = null != arguments[t] ? arguments[t] : {};
219
219
  t % 2 ? C(Object(r), !0).forEach((function(t) {
220
- T(e, t, r[t]);
220
+ A(e, t, r[t]);
221
221
  })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(r)) : C(Object(r)).forEach((function(t) {
222
222
  Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(r, t));
223
223
  }));
224
224
  }
225
225
  return e;
226
226
  }
227
- function T(e, t, r) {
228
- return (t = E(t)) in e ? Object.defineProperty(e, t, {
227
+ function A(e, t, r) {
228
+ return (t = T(t)) in e ? Object.defineProperty(e, t, {
229
229
  value: r,
230
230
  enumerable: !0,
231
231
  configurable: !0,
232
232
  writable: !0
233
233
  }) : e[t] = r, e;
234
234
  }
235
- function E(e) {
236
- var t = A(e, "string");
235
+ function T(e) {
236
+ var t = E(e, "string");
237
237
  return "symbol" == h(t) ? t : t + "";
238
238
  }
239
- function A(e, t) {
239
+ function E(e, t) {
240
240
  if ("object" != h(e) || !e) return e;
241
241
  var r = e[Symbol.toPrimitive];
242
242
  if (void 0 !== r) {
@@ -256,6 +256,7 @@
256
256
  innerClassName: i().string,
257
257
  innerStyle: i().object,
258
258
  onAnimationEnd: i().func,
259
+ onAnimationStart: i().func,
259
260
  open: i().bool,
260
261
  outerClassName: i().string,
261
262
  outerId: i().string,
@@ -330,7 +331,7 @@
330
331
  }, a)
331
332
  };
332
333
  };
333
- var _ = function e(t) {
334
+ var W = function e(t) {
334
335
  var r = t.animation, n = t.el, o = t.takeFocusProp;
335
336
  var i = 0;
336
337
  if (n) {
@@ -353,89 +354,95 @@
353
354
  }
354
355
  return i;
355
356
  };
357
+ var _ = {};
356
358
  var R = {};
357
- var W = {};
358
359
  function D(e) {
359
- var t = e.animation, o = t === void 0 ? "expandHeight" : t, i = e.animateOnMount, u = e.children, f = e.className, d = e.elementRef, m = e.id, p = e.innerClassName, h = e.innerStyle, S = h === void 0 ? R : h, j = e.onAnimationEnd, w = e.open, P = e.outerClassName, k = e.outerId, F = e.outerStyle, C = F === void 0 ? W : F, E = e.renderChildrenWhenCollapsed, A = e.retainFocus, I = e.takeFocus, D = x(e, [ "animation", "animateOnMount", "children", "className", "elementRef", "id", "innerClassName", "innerStyle", "onAnimationEnd", "open", "outerClassName", "outerId", "outerStyle", "renderChildrenWhenCollapsed", "retainFocus", "takeFocus" ]);
360
+ var t = e.animation, o = t === void 0 ? "expandHeight" : t, i = e.animateOnMount, u = e.children, f = e.className, d = e.elementRef, m = e.id, p = e.innerClassName, h = e.innerStyle, S = h === void 0 ? _ : h, j = e.onAnimationEnd, w = e.onAnimationStart, P = e.open, k = e.outerClassName, x = e.outerId, C = e.outerStyle, T = C === void 0 ? R : C, E = e.renderChildrenWhenCollapsed, I = e.retainFocus, D = e.takeFocus, H = F(e, [ "animation", "animateOnMount", "children", "className", "elementRef", "id", "innerClassName", "innerStyle", "onAnimationEnd", "onAnimationStart", "open", "outerClassName", "outerId", "outerStyle", "renderChildrenWhenCollapsed", "retainFocus", "takeFocus" ]);
360
361
  // @docs-props-type TransitionOpenPropsBase
361
- var H = l()(w);
362
- var L = (0, r.useRef)(true);
363
- var $ = (0, r.useState)(i ? w : false), B = O($, 2), K = B[0], U = B[1];
364
- var X = (0, r.useState)(null), Y = O(X, 2), z = Y[0], G = Y[1];
365
- var J = (0, r.useState)(0), Q = O(J, 2), V = Q[0], Z = Q[1];
362
+ var L = l()(P);
363
+ var $ = (0, r.useRef)(true);
364
+ var B = (0, r.useState)(i ? P : false), K = O(B, 2), U = K[0], X = K[1];
365
+ var Y = (0, r.useState)(null), z = O(Y, 2), G = z[0], J = z[1];
366
+ var Q = (0, r.useState)(0), V = O(Q, 2), Z = V[0], ee = V[1];
366
367
  (0, r.useEffect)((function() {
367
368
  // prevOpen starts undefined, and we don't want to make the comparison in that situation
368
- if (H !== undefined && w !== H) {
369
- U(true);
369
+ if (L !== undefined && P !== L) {
370
+ X(true);
370
371
  }
371
- }), [ w, H ]);
372
+ }), [ P, L ]);
372
373
  // equivalent to componentDidMount and componentWillUnmount
373
374
  (0, r.useEffect)((function() {
374
375
  // we need to set this to true on every mount because React.StrictMode will call the effect twice
375
376
  // and we need to ensure that allowAnimationUpdates is true while the component is mounted
376
- L.current = true;
377
+ $.current = true;
377
378
  return function() {
378
- L.current = false;
379
+ $.current = false;
379
380
  };
380
381
  }), []);
381
- var ee = (0, r.useCallback)((function(e) {
382
- G(e);
383
- Z(_({
382
+ var te = (0, r.useCallback)((function(e) {
383
+ J(e);
384
+ ee(W({
384
385
  animation: o,
385
386
  el: e,
386
- takeFocusProp: I
387
+ takeFocusProp: D
387
388
  }));
388
389
  b(d, e);
389
- }), [ o, I, d ]);
390
- var te = (0, r.useCallback)((function() {
391
- if (L.current) {
392
- U(false);
390
+ }), [ o, D, d ]);
391
+ var re = (0, r.useCallback)((function() {
392
+ w === null || w === void 0 ? void 0 : w();
393
+ }), [ w ]);
394
+ var ne = (0, r.useCallback)((function() {
395
+ if ($.current) {
396
+ X(false);
393
397
  }
394
398
  j === null || j === void 0 ? void 0 : j();
395
399
  }), [ j ]);
396
- var re = (0, r.useCallback)((function(e) {
397
- if (z) {
398
- (0, s.handleTab)(z, e);
400
+ var oe = (0, r.useCallback)((function(e) {
401
+ if (G) {
402
+ (0, s.handleTab)(G, e);
399
403
  }
400
- }), [ z ]);
401
- var ne = (0, a.useAnimation)(N(N({}, M({
404
+ }), [ G ]);
405
+ var ie = (0, a.useAnimation)(N(N({}, M({
402
406
  animation: o,
403
- open: w,
404
- value: V
407
+ open: P,
408
+ value: Z
405
409
  })), {}, {
406
410
  immediate: o === "none",
407
- onRest: te
408
- })), oe = ne.value, ie = ne.transform;
409
- var ae;
410
- if (K || E) {
411
- ae = q(o);
411
+ onRest: ne,
412
+ onStart: re
413
+ })), ae = ie.value, ue = ie.transform;
414
+ var le;
415
+ /* to avoid setting and unsetting dimension which causes flickering
416
+ we always set the dimension if it is a slide animation
417
+ else only set it when animating || renderChildrenWhenCollapsed */ if (o.startsWith("slideFrom") || U || E) {
418
+ le = q(o);
412
419
  }
413
420
  // if renderChildrenWhenCollapsed is true, we hide the content by setting the height of the wrapper to 0
414
- var ue = E && !w && !K ? 0 : oe;
415
- var le = (0, r.useMemo)((function() {
416
- return N(N({}, C), ae && T({}, ae, ue));
417
- }), [ ae, ue, C ]);
418
- var se = (0, r.useMemo)((function() {
421
+ var se = E && !P && !U ? 0 : ae;
422
+ var ce = (0, r.useMemo)((function() {
423
+ return N(N({}, T), le && A({}, le, se));
424
+ }), [ le, se, T ]);
425
+ var fe = (0, r.useMemo)((function() {
419
426
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
420
427
  return N(N({}, S), {}, {
421
- transform: ie
428
+ transform: ue
422
429
  });
423
- }), [ S, ie ]);
430
+ }), [ S, ue ]);
424
431
 
425
432
  return n().createElement(v, {
426
- $hideOverflow: !w || K || false,
427
- className: (0, c.toClassName)(f, P),
428
- style: le,
429
- id: k
430
- }, (w || K || E) && n().createElement(y, g({
433
+ $hideOverflow: !P || U || false,
434
+ className: (0, c.toClassName)(f, k),
435
+ style: ce,
436
+ id: x
437
+ }, (P || U || E) && n().createElement(y, g({
431
438
  "data-test": "transition-open"
432
- }, D, {
433
- ref: ee,
439
+ }, H, {
440
+ ref: te,
434
441
  tabIndex: -1,
435
442
  className: p,
436
443
  id: m,
437
- onKeyDown: A ? re : undefined,
438
- style: se
444
+ onKeyDown: I ? oe : undefined,
445
+ style: fe
439
446
  }), u));
440
447
  }
441
448
  D.propTypes = I;
@@ -19,3 +19,43 @@ Cypress.Commands.add('hover', (selector: string) => {
19
19
  return cy.wrap($el).trigger('mouseover', { force: true });
20
20
  });
21
21
  });
22
+
23
+ const calcDiffPct = (target: number, actual: number) => {
24
+ try {
25
+ const diff = (200 * Math.abs(target - actual)) / (target + actual);
26
+ const side = actual > target ? 'ABOVE' : 'BELOW';
27
+
28
+ return { diff: Math.round(diff * 100) / 100, side };
29
+ } catch {
30
+ return { diff: 0, side: '' };
31
+ }
32
+ };
33
+
34
+ Cypress.Commands.add(
35
+ 'verifyPerformance',
36
+ ({ testName, execute, threshold = 0.5, expectedRenderDurationInMs = 100 }) => {
37
+ let startTime = 0;
38
+
39
+ const allowableDurationInMs = expectedRenderDurationInMs * (1 + threshold);
40
+ cy.wrap(null)
41
+ .then(() => {
42
+ startTime = performance.now();
43
+ cy.log(`[${Math.round(startTime)}ms] Starting validation`);
44
+ })
45
+ .then(() => execute())
46
+ .then(() => {
47
+ const endTime = performance.now();
48
+ const durationInMs = Math.round(endTime - startTime);
49
+
50
+ const { diff, side } = calcDiffPct(expectedRenderDurationInMs, durationInMs);
51
+ const logMsg = `Test "${testName}" took ${durationInMs}ms to render (${diff}% ${side} ${expectedRenderDurationInMs}ms expectation)`;
52
+
53
+ cy.log(`[${Math.round(endTime)}ms] ${logMsg}`);
54
+
55
+ assert(
56
+ allowableDurationInMs >= durationInMs,
57
+ `${logMsg}, but should take less than ${allowableDurationInMs}ms`
58
+ );
59
+ });
60
+ }
61
+ );
@@ -1,6 +1,6 @@
1
- import { mount } from 'cypress/react';
2
1
  import { setProjectAnnotations } from '@storybook/react';
3
2
  import { configure } from '@testing-library/cypress';
3
+ import { mount } from 'cypress/react';
4
4
 
5
5
  import * as sbPreview from '../../.storybook/preview';
6
6
  import './commands';
@@ -2,5 +2,27 @@
2
2
  declare namespace Cypress {
3
3
  interface Chainable {
4
4
  hover(selector: string): Chainable; // to support hover custom command
5
+
6
+ /**
7
+ * Runs the custom 'profile' task and verifies the returned value is within the allowable threshold.
8
+ * Threshold of .5 and expectedRenderDurationInMs === 100 would allow the render to take up to 50% more, i.e 150ms
9
+ * @param args - The arguments for the performance verification.
10
+ * @param args.testName - The name of the test to be used in the profiling
11
+ * @param args.threshold - The threshold percentage for the performance test (default is 0.5, meaning 50% more than expected)
12
+ * @param args.expectedRenderDurationInMs - The expected render duration in milliseconds (default is 100ms)
13
+ * @example
14
+ * // Verify that the render duration for 'my-test' is within the threshold
15
+ * cy.verifyPerformance({
16
+ * testName: 'my-test',
17
+ * threshold: 0.5,
18
+ * expectedRenderDurationInMs: 100
19
+ * });
20
+ */
21
+ verifyPerformance(args: {
22
+ testName: string;
23
+ execute: () => Chainable | void;
24
+ threshold?: number;
25
+ expectedRenderDurationInMs?: number;
26
+ }): void;
5
27
  }
6
28
  }
@@ -1,53 +1,100 @@
1
1
  services:
2
- prisma-storybook:
3
- build:
4
- context: .
5
- dockerfile: ../../infra/visual-tests/Dockerfile.storybook
6
- args:
7
- port: 6007
8
- storybookfolder: storybook-static-visual-prisma
9
- workdir: /react-ui
10
- command: npx http-server storybook-static-visual-prisma --port 6007
11
- ports:
12
- - "6007:6007"
13
- enterprise-storybook:
14
- build:
15
- context: .
16
- dockerfile: ../../infra/visual-tests/Dockerfile.storybook
17
- args:
18
- port: 6008
19
- storybookfolder: storybook-static-visual-enterprise
20
- workdir: /react-ui
21
- command: npx http-server storybook-static-visual-enterprise --port 6008
22
- ports:
23
- - "6008:6008"
24
- prisma-visual-test:
25
- build:
26
- context: .
27
- dockerfile: ../../infra/visual-tests/Dockerfile.visual
28
- args:
29
- workdir: /react-ui
30
- env_file:
31
- - ./.storybook-visual/config/.env.visual
32
- working_dir: /react-ui
33
- volumes:
34
- - "./src:/react-ui/src"
35
- - "./test-reports:/react-ui/test-reports"
36
- depends_on:
37
- - prisma-storybook
38
- command: /bin/sh -c "npx wait-on http://prisma-storybook:6007 && yarn cache clean && yarn test-storybook -c .storybook-visual --browsers $${STORYBOOK_BROWSER} $${STORYBOOK_UPDATE_SNAPSHOT} $${STORYBOOK_MAX_WORKERS} --url http://prisma-storybook:6007 --no-index-json"
39
- enterprise-visual-test:
40
- build:
41
- context: .
42
- dockerfile: ../../infra/visual-tests/Dockerfile.visual
43
- args:
44
- workdir: /react-ui
45
- env_file:
46
- - ./.storybook-visual/config/.env.visual
47
- working_dir: /react-ui
48
- volumes:
49
- - "./src:/react-ui/src"
50
- - "./test-reports:/react-ui/test-reports"
51
- depends_on:
52
- - enterprise-storybook
53
- command: /bin/sh -c "npx wait-on http://enterprise-storybook:6008 && yarn cache clean && yarn test-storybook -c .storybook-visual --browsers $${STORYBOOK_BROWSER} $${STORYBOOK_UPDATE_SNAPSHOT} $${STORYBOOK_MAX_WORKERS} --url http://enterprise-storybook:6008 --no-index-json"
2
+ prisma-storybook:
3
+ build:
4
+ context: .
5
+ dockerfile: ../../infra/visual-tests/Dockerfile.storybook
6
+ args:
7
+ port: 6007
8
+ storybookfolder: storybook-static-visual-prisma
9
+ workdir: /react-ui
10
+ command: npx http-server storybook-static-visual-prisma --port 6007
11
+ ports:
12
+ - '6007:6007'
13
+ enterprise-storybook:
14
+ build:
15
+ context: .
16
+ dockerfile: ../../infra/visual-tests/Dockerfile.storybook
17
+ args:
18
+ port: 6008
19
+ storybookfolder: storybook-static-visual-enterprise
20
+ workdir: /react-ui
21
+ command: npx http-server storybook-static-visual-enterprise --port 6008
22
+ ports:
23
+ - '6008:6008'
24
+ splunk-magnetic-storybook:
25
+ build:
26
+ context: .
27
+ dockerfile: ../../infra/visual-tests/Dockerfile.storybook
28
+ args:
29
+ port: 6009
30
+ storybookfolder: storybook-static-visual-splunk-magnetic
31
+ workdir: /react-ui
32
+ command: npx http-server storybook-static-visual-splunk-magnetic --port 6009
33
+ ports:
34
+ - '6009:6009'
35
+ prisma-visual-test:
36
+ build:
37
+ context: .
38
+ dockerfile: ../../infra/visual-tests/Dockerfile.visual
39
+ args:
40
+ workdir: /react-ui
41
+ env_file:
42
+ - ./.storybook-visual/config/.env.visual
43
+ environment:
44
+ - JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1
45
+ - JOB_BROWSER=${JOB_BROWSER}
46
+ working_dir: /react-ui
47
+ volumes:
48
+ - './src:/react-ui/src'
49
+ - './test-reports:/react-ui/test-reports'
50
+ # TODO(SUI-8236): can remove once webpack.test.config.js imports of infra/.config.js are removed as this won't be needed any longer (verify with no cache docker build something else didn't start using it though)
51
+ - '../../infra/.config.js:/infra/.config.js:ro'
52
+ - '../../infra/storybook/utils.js:/infra/storybook/utils.js:ro'
53
+ - '../../infra/visual-tests/orphaned-snapshot-check-reporter.js:/infra/visual-tests/orphaned-snapshot-check-reporter.js:ro'
54
+ depends_on:
55
+ - prisma-storybook
56
+ command: /bin/sh -c "npx wait-on http://prisma-storybook:6007 && yarn cache clean && yarn test-storybook -c .storybook-visual --browsers $${STORYBOOK_BROWSER} $${STORYBOOK_UPDATE_SNAPSHOT} $${STORYBOOK_MAX_WORKERS} --url http://prisma-storybook:6007 --no-index-json"
57
+ enterprise-visual-test:
58
+ build:
59
+ context: .
60
+ dockerfile: ../../infra/visual-tests/Dockerfile.visual
61
+ args:
62
+ workdir: /react-ui
63
+ env_file:
64
+ - ./.storybook-visual/config/.env.visual
65
+ environment:
66
+ - JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1
67
+ - JOB_BROWSER=${JOB_BROWSER}
68
+ working_dir: /react-ui
69
+ volumes:
70
+ - './src:/react-ui/src'
71
+ - './test-reports:/react-ui/test-reports'
72
+ # TODO(SUI-8236): can remove once webpack.test.config.js imports of infra/.config.js are removed as this won't be needed any longer (verify with no cache docker build something else didn't start using it though)
73
+ - '../../infra/.config.js:/infra/.config.js:ro'
74
+ - '../../infra/storybook/utils.js:/infra/storybook/utils.js:ro'
75
+ - '../../infra/visual-tests/orphaned-snapshot-check-reporter.js:/infra/visual-tests/orphaned-snapshot-check-reporter.js:ro'
76
+ depends_on:
77
+ - enterprise-storybook
78
+ command: /bin/sh -c "npx wait-on http://enterprise-storybook:6008 && yarn cache clean && yarn test-storybook -c .storybook-visual --browsers $${STORYBOOK_BROWSER} $${STORYBOOK_UPDATE_SNAPSHOT} $${STORYBOOK_MAX_WORKERS} --url http://enterprise-storybook:6008 --no-index-json"
79
+ splunk-magnetic-visual-test:
80
+ build:
81
+ context: .
82
+ dockerfile: ../../infra/visual-tests/Dockerfile.visual
83
+ args:
84
+ workdir: /react-ui
85
+ env_file:
86
+ - ./.storybook-visual/config/.env.visual
87
+ environment:
88
+ - JEST_IMAGE_SNAPSHOT_TRACK_OBSOLETE=1
89
+ - JOB_BROWSER=${JOB_BROWSER}
90
+ working_dir: /react-ui
91
+ volumes:
92
+ - './src:/react-ui/src'
93
+ - './test-reports:/react-ui/test-reports'
94
+ # TODO(SUI-8236): can remove once webpack.test.config.js imports of infra/.config.js are removed as this won't be needed any longer (verify with no cache docker build something else didn't start using it though)
95
+ - '../../infra/.config.js:/infra/.config.js:ro'
96
+ - '../../infra/storybook/utils.js:/infra/storybook/utils.js:ro'
97
+ - '../../infra/visual-tests/orphaned-snapshot-check-reporter.js:/infra/visual-tests/orphaned-snapshot-check-reporter.js:ro'
98
+ depends_on:
99
+ - splunk-magnetic-storybook
100
+ command: /bin/sh -c "npx wait-on http://splunk-magnetic-storybook:6009 && yarn cache clean && yarn test-storybook -c .storybook-visual --browsers $${STORYBOOK_BROWSER} $${STORYBOOK_UPDATE_SNAPSHOT} $${STORYBOOK_MAX_WORKERS} --url http://splunk-magnetic-storybook:6009 --no-index-json"
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@splunk/react-ui",
3
- "version": "5.4.0",
3
+ "version": "5.6.0",
4
4
  "description": "Library of React components that implement the Splunk design language",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Splunk Inc.",
7
7
  "scripts": {
8
8
  "build": "cross-env NODE_ENV=production webpack && yarn types:build",
9
9
  "docs": "NODE_ENV=production webpack --config docs.gen.webpack.config.js",
10
+ "docs:llm": "NODE_ENV=production webpack --config docs-llm.gen.webpack.config.js",
10
11
  "docs:publish": "eval $(splunk-docs-package docs) && artifact-ci publish generic $DOCS_GEN_OUTPUT_NAME $DOCS_GEN_REMOTE_PATH",
11
12
  "docs:publish:external": "eval $(splunk-docs-package docs-external --suffix=public) && artifact-ci publish generic $DOCS_GEN_OUTPUT_NAME $DOCS_GEN_REMOTE_PATH",
12
13
  "docs:start": "INTERNAL=true webpack serve --config docs.gen.webpack.config.js",
@@ -44,16 +45,18 @@
44
45
  "@dnd-kit/sortable": "^8.0.0",
45
46
  "@dnd-kit/utilities": "^3.2.2",
46
47
  "@react-spring/web": "^9.7.5",
47
- "@splunk/react-icons": "^5.4.0",
48
- "@splunk/themes": "^1.3.0",
49
- "@splunk/ui-utils": "^1.11.0",
48
+ "@splunk/react-icons": "^5.6.0",
49
+ "@splunk/themes": "^1.4.1",
50
+ "@splunk/ui-utils": "^1.12.0",
50
51
  "decimal.js-light": "^2.5.1",
52
+ "intl-tel-input": "^25.3.2",
51
53
  "lodash": "^4.17.14",
52
54
  "moment": "^2.29.4",
53
55
  "prop-types": "^15.6.2",
54
56
  "react-markdown": "^8.0.7",
55
57
  "remark-gfm": "^1.0.0",
56
58
  "tinycolor2": "^1.4.1",
59
+ "use-sync-external-store": "^1.6.0",
57
60
  "use-typed-event-listener": "^3.0.0"
58
61
  },
59
62
  "devDependencies": {
@@ -65,7 +68,7 @@
65
68
  "@splunk/react-docs": "^1.4.0",
66
69
  "@splunk/stylelint-config": "^5.0.0",
67
70
  "@splunk/test-runner-utils": "^0.4.1",
68
- "@splunk/webpack-configs": "^7.0.2",
71
+ "@splunk/webpack-configs": "^7.0.3",
69
72
  "@storybook/addon-a11y": "^7.6.20",
70
73
  "@storybook/addon-essentials": "^7.6.20",
71
74
  "@storybook/addon-interactions": "^7.6.20",
@@ -87,6 +90,7 @@
87
90
  "@types/react-dom": "^18.2.0",
88
91
  "@types/styled-components": "^5.1.0",
89
92
  "@types/tinycolor2": "^1.4.2",
93
+ "@types/use-sync-external-store": "^1.5.0",
90
94
  "@types/webpack-env": "^1.15.2",
91
95
  "@typescript-eslint/eslint-plugin": "^8.29.1",
92
96
  "@typescript-eslint/parser": "^8.29.1",
@@ -8,92 +8,6 @@ declare module '__FONTS_IMPORT__/*' {
8
8
  export default component;
9
9
  }
10
10
 
11
- declare module '@splunk/ui-utils/color' {
12
- function expandShortHandHex<T extends string | null | undefined>(arg: T): T;
13
- function hexToRgb(hex: string): [number, number, number] | null;
14
- function isCSSColor(value: string): boolean;
15
- function isValidHexColor(value: string): boolean;
16
- function isValidRgb(value: string): boolean;
17
- function namedColorToHex(colorName: string): string | undefined;
18
-
19
- const extendedColorKeywords: string[];
20
- const extendedColorKeywordsToHex: { string: string };
21
- }
22
-
23
- declare module '@splunk/ui-utils/filter' {
24
- function keywordLocations(
25
- phrase: string,
26
- keywords: string[]
27
- ): { keyword: string; start: number; end: number }[];
28
- function stringToKeywords(filterPhrase?: string): string[];
29
- function testPhrase(phrase: string, keywords: string[]): boolean;
30
- }
31
-
32
- declare module '@splunk/ui-utils/format' {
33
- // for now, assume this is guaranteed to return a string (and not undefined, null, ...)
34
- function sprintf(...args: any[]): string;
35
- }
36
-
37
- declare module '@splunk/ui-utils/focus' {
38
- // getSortedTabbableElements returns Elements
39
- // handleTab / takeFocus both call focus() which exists only on HTMLElement/SVGElement (modern browsers), but not Element
40
- function getSortedTabbableElements(
41
- container: Element,
42
- options?: { ignoreTabIndex: boolean }
43
- ): Element[];
44
- function isTabKey(event: KeyboardEvent<Element>): boolean;
45
- function handleTab(container: Element, event: KeyboardEvent): Element | null;
46
- function takeFocus(container: Element, defaultElement?: 'first' | 'container'): Element | null;
47
- function handleFocus(
48
- key: string,
49
- actionItems: Element[],
50
- currentIndex: number,
51
- options?: {
52
- enableLoop?: boolean;
53
- orientation?: 'horizontal' | 'vertical';
54
- enableTab?: boolean;
55
- enableHomeEnd?: boolean;
56
- }
57
- ): void;
58
- }
59
-
60
- declare module '@splunk/ui-utils/i18n' {
61
- // for now, assume this is guaranteed to return a string (and not undefined, null, ...)
62
- function _(...args: any[]): string;
63
- }
64
-
65
- declare module '@splunk/ui-utils/id' {
66
- function createDOMID(prefix?: string): string;
67
- function createGUID(): string;
68
- }
69
-
70
- declare module '@splunk/ui-utils/keyboard' {
71
- function addsCharacter(event: KeyboardEvent): boolean | undefined;
72
- function keycode(event: KeyboardEvent | number | string): string;
73
- function isDecimal(event: KeyboardEvent, options?: { locale: string }): boolean;
74
- function isMinus(event: KeyboardEvent): boolean;
75
- function isNumber(event: KeyboardEvent): boolean;
76
- function isNumeric(event: KeyboardEvent, options?: { locale: string }): boolean;
77
- }
78
-
79
- declare module '@splunk/ui-utils/promise' {
80
- interface CancelablePromise<T> {
81
- cancel: () => void;
82
- promise: Promise<T>;
83
- }
84
-
85
- function makeCancelable<T>(arg: Promise<T>): CancelablePromise<T>;
86
- }
87
-
88
- declare module '@splunk/ui-utils/scroll' {
89
- export function scrollIntoViewIfNeeded(el?: HTMLElement | null): void;
90
- }
91
-
92
- declare module '@splunk/ui-utils/style' {
93
- type ClassNameArg = ClassNameArg | Record<string, unknown> | string | undefined | null;
94
- function toClassName(...args: ClassNameArg[]): string;
95
- }
96
-
97
11
  declare module '@splunk/react-docs/DocExample' {
98
12
  function getDependencyVersions(
99
13
  packageJSON: Record<string, unknown>,
@@ -50,6 +50,7 @@ module.exports = {
50
50
  : 'a11y-report.html',
51
51
  },
52
52
  ],
53
+ '../../infra/visual-tests/orphaned-snapshot-check-reporter.js',
53
54
  ],
54
55
  globals: {
55
56
  __DEV__: true,
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { ComponentProps } from '../utils/types';
4
+ interface AnchorMenuPropsBase {
5
+ /**
6
+ * The `itemId` prop of the currently active item.
7
+ */
8
+ activeItemId?: string;
9
+ children?: React.ReactNode;
10
+ /**
11
+ * A React ref which is set to the DOM element when the component mounts and null when it unmounts.
12
+ */
13
+ elementRef?: React.Ref<HTMLElement>;
14
+ /**
15
+ * Hides the side border spine. Useful when the AnchorMenu is placed inside a container with its own border.
16
+ */
17
+ hideSpine?: boolean;
18
+ /**
19
+ * Label text to display above the menu items. Set to `null` to disable the label.
20
+ */
21
+ label?: string | null;
22
+ }
23
+ type AnchorMenuProps = ComponentProps<AnchorMenuPropsBase, 'nav'>;
24
+ declare function AnchorMenu({ activeItemId, children, elementRef, hideSpine, label, ...otherProps }: AnchorMenuProps): React.JSX.Element;
25
+ declare namespace AnchorMenu {
26
+ var propTypes: {
27
+ activeItemId: PropTypes.Requireable<string>;
28
+ children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
29
+ elementRef: PropTypes.Requireable<object>;
30
+ hideSpine: PropTypes.Requireable<boolean>;
31
+ label: PropTypes.Requireable<string>;
32
+ };
33
+ var Item: typeof import("./Item").default;
34
+ }
35
+ export type { AnchorMenuProps, AnchorMenuPropsBase };
36
+ export default AnchorMenu;
@@ -0,0 +1,6 @@
1
+ export interface AnchorMenuContextValue {
2
+ activeItemId?: string;
3
+ hideSpine?: boolean;
4
+ }
5
+ declare const AnchorMenuContext: import("react").Context<AnchorMenuContextValue>;
6
+ export default AnchorMenuContext;