@instructure/ui-select 10.18.2-snapshot-0 → 10.18.2-snapshot-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.
@@ -18,7 +18,7 @@ var _IconDownloadSolid = require("@instructure/ui-icons/lib/IconDownloadSolid.js
18
18
  var _IconEyeSolid = require("@instructure/ui-icons/lib/IconEyeSolid.js");
19
19
  var _jsxRuntime = require("@emotion/react/jsx-runtime");
20
20
  var _react3 = require("@emotion/react");
21
- var _Select, _Select2, _Select3, _Select4, _Select5, _Select6, _Select7;
21
+ var _Select$Option, _Select, _Select2, _Select3, _Select4, _Select5, _Select6, _Select7;
22
22
  /*
23
23
  * The MIT License (MIT)
24
24
  *
@@ -212,43 +212,67 @@ describe('<Select />', () => {
212
212
  afterEach(() => {
213
213
  consoleErrorMock.mockRestore();
214
214
  });
215
+ it('should not crash for weird option ids', async () => {
216
+ const weirdID = 'some_`w@ei:r|!@#$%^&*(()|\\.l/d"id';
217
+ _vitest.vi.useFakeTimers();
218
+ const _render = (0, _react2.render)((0, _jsxRuntime.jsxs)(_index.default, {
219
+ renderLabel: "Choose an option",
220
+ scrollToHighlightedOption: true,
221
+ isShowingOptions: true,
222
+ children: [(0, _jsxRuntime.jsx)(_index.default.Option, {
223
+ id: weirdID,
224
+ value: "2",
225
+ isHighlighted: true,
226
+ children: "op1"
227
+ }, "1"), _Select$Option || (_Select$Option = (0, _jsxRuntime.jsx)(_index.default.Option, {
228
+ id: "sdfsdfsd",
229
+ value: "2",
230
+ children: "op2"
231
+ }, "2"))]
232
+ })),
233
+ container = _render.container;
234
+ _vitest.vi.advanceTimersToNextFrame();
235
+ _vitest.vi.useRealTimers();
236
+ const input = container.querySelector('input');
237
+ expect(input).toBeInTheDocument();
238
+ });
215
239
  it('should have role button in Safari without onInputChange', async () => {
216
- const _render = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
240
+ const _render2 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
217
241
  renderLabel: "Choose an option",
218
242
  children: getOptions()
219
243
  })),
220
- container = _render.container;
244
+ container = _render2.container;
221
245
  const input = container.querySelector('input');
222
246
  expect(input).toHaveAttribute('role', 'button');
223
247
  });
224
248
  it('should have role combobox in different browsers than Safari without onInputChange', async () => {
225
249
  mockUtils.isSafari = _vitest.vi.fn(() => false);
226
- const _render2 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
250
+ const _render3 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
227
251
  renderLabel: "Choose an option",
228
252
  children: getOptions()
229
253
  })),
230
- container = _render2.container;
254
+ container = _render3.container;
231
255
  const input = container.querySelector('input');
232
256
  expect(input).toHaveAttribute('role', 'combobox');
233
257
  });
234
258
  it('should have role combobox with onInputChange', async () => {
235
- const _render3 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
259
+ const _render4 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
236
260
  renderLabel: "Choose an option",
237
261
  onInputChange: () => {},
238
262
  children: getOptions()
239
263
  })),
240
- container = _render3.container;
264
+ container = _render4.container;
241
265
  const input = container.querySelector('input');
242
266
  expect(input).toHaveAttribute('role', 'combobox');
243
267
  });
244
268
  it('should render an input and a list', async () => {
245
- const _render4 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
269
+ const _render5 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
246
270
  renderLabel: "Choose an option",
247
271
  isShowingOptions: true,
248
272
  "data-testid": "subidubi",
249
273
  children: getOptions()
250
274
  })),
251
- container = _render4.container;
275
+ container = _render5.container;
252
276
  const select = container.querySelector('span[class$="-select"]');
253
277
  const label = _react2.screen.getByLabelText('Choose an option');
254
278
  const input = container.querySelector('input[id^="Select_"]');
@@ -341,20 +365,20 @@ describe('<Select />', () => {
341
365
  });
342
366
  describe('input', () => {
343
367
  it('should render with a generated id by default', () => {
344
- const _render5 = (0, _react2.render)(_Select3 || (_Select3 = (0, _jsxRuntime.jsx)(_index.default, {
368
+ const _render6 = (0, _react2.render)(_Select3 || (_Select3 = (0, _jsxRuntime.jsx)(_index.default, {
345
369
  renderLabel: "Choose an option"
346
370
  }))),
347
- container = _render5.container;
371
+ container = _render6.container;
348
372
  const input = container.querySelector('input[id^="Select_"]');
349
373
  expect(input).toBeInTheDocument();
350
374
  expect(input).toHaveAttribute('id', expect.stringContaining('Select_'));
351
375
  });
352
376
  it('should render with a custom id if given', () => {
353
- const _render6 = (0, _react2.render)(_Select4 || (_Select4 = (0, _jsxRuntime.jsx)(_index.default, {
377
+ const _render7 = (0, _react2.render)(_Select4 || (_Select4 = (0, _jsxRuntime.jsx)(_index.default, {
354
378
  renderLabel: "Choose an option",
355
379
  id: "customSelect"
356
380
  }))),
357
- container = _render6.container;
381
+ container = _render7.container;
358
382
  const input = container.querySelector('input[id^="customSelect"]');
359
383
  expect(input).toBeInTheDocument();
360
384
  expect(input.getAttribute('id')).toEqual('customSelect');
@@ -460,11 +484,11 @@ describe('<Select />', () => {
460
484
  expect(input).toHaveAttribute('data-custom-attr', 'true');
461
485
  });
462
486
  it('should allow override of autoComplete prop', () => {
463
- const _render7 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
487
+ const _render8 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
464
488
  renderLabel: "Choose an option",
465
489
  children: getOptions()
466
490
  })),
467
- rerender = _render7.rerender;
491
+ rerender = _render8.rerender;
468
492
  const input = _react2.screen.getByLabelText('Choose an option');
469
493
  expect(input).toHaveAttribute('autocomplete', 'off');
470
494
  rerender((0, _jsxRuntime.jsx)(_index.default, {
@@ -487,170 +511,170 @@ describe('<Select />', () => {
487
511
  });
488
512
  });
489
513
  it("should not render option's before content in input field when isOptionContentAppliedToInput is set to false", async () => {
490
- const _render8 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
514
+ const _render9 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
491
515
  renderLabel: "Choose an option",
492
516
  isOptionContentAppliedToInput: false,
493
517
  inputValue: optionsWithBeforeContent[0].label,
494
518
  children: getOptionsWithBeforeContent('opt1')
495
519
  })),
496
- container = _render8.container;
520
+ container = _render9.container;
497
521
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
498
522
  expect(beforeContent).not.toHaveTextContent('XY');
499
523
  });
500
524
  it('should render arrow in input field when isOptionContentAppliedToInput is set to false', async () => {
501
- const _render9 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
525
+ const _render10 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
502
526
  renderLabel: "Choose an option",
503
527
  isOptionContentAppliedToInput: false,
504
528
  inputValue: optionsWithBeforeContent[0].label,
505
529
  children: getOptionsWithBeforeContent('opt1')
506
530
  })),
507
- container = _render9.container;
531
+ container = _render10.container;
508
532
  const spanElement = container.querySelector('span[class$="-textInput__afterElement"]');
509
533
  const svgElement = spanElement.querySelector('svg[name="IconArrowOpenDown"]');
510
534
  expect(svgElement).toBeInTheDocument();
511
535
  });
512
536
  it("should render option's before content in input field when isOptionContentAppliedToInput is set to true", async () => {
513
- const _render10 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
537
+ const _render11 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
514
538
  renderLabel: "Choose an option",
515
539
  isOptionContentAppliedToInput: true,
516
540
  inputValue: optionsWithBeforeContent[0].label,
517
541
  children: getOptionsWithBeforeContent('opt1')
518
542
  })),
519
- container = _render10.container;
543
+ container = _render11.container;
520
544
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
521
545
  expect(beforeContent).toHaveTextContent('XY');
522
546
  });
523
547
  it('should render arrow icon when isOptionContentAppliedToInput is set to true with before content', async () => {
524
- const _render11 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
548
+ const _render12 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
525
549
  renderLabel: "Choose an option",
526
550
  isOptionContentAppliedToInput: true,
527
551
  inputValue: optionsWithBeforeContent[0].label,
528
552
  children: getOptionsWithBeforeContent('opt1')
529
553
  })),
530
- container = _render11.container;
554
+ container = _render12.container;
531
555
  const spanElement = container.querySelector('span[class$="-textInput__afterElement"]');
532
556
  const svgElement = spanElement.querySelector('svg[name="IconArrowOpenDown"]');
533
557
  expect(svgElement).toBeInTheDocument();
534
558
  });
535
559
  it("should render option's after content in input field when isOptionContentAppliedToInput is set to true", async () => {
536
- const _render12 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
560
+ const _render13 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
537
561
  renderLabel: "Choose an option",
538
562
  isOptionContentAppliedToInput: true,
539
563
  inputValue: optionsWithAfterContent[0].label,
540
564
  children: getOptionsWithAfterContent('opt1')
541
565
  })),
542
- container = _render12.container;
566
+ container = _render13.container;
543
567
  const beforeContent = container.querySelector('span[class$="-textInput__afterElement"]');
544
568
  expect(beforeContent).toHaveTextContent('XY');
545
569
  });
546
570
  it("should render option's before content in input field when isOptionContentAppliedToInput is set to true but renderBeforeInput is also set", async () => {
547
- const _render13 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
571
+ const _render14 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
548
572
  renderLabel: "Choose an option",
549
573
  isOptionContentAppliedToInput: true,
550
574
  inputValue: optionsWithBeforeContent[0].label,
551
575
  renderBeforeInput: "ZZ",
552
576
  children: getOptionsWithBeforeContent('opt1')
553
577
  })),
554
- container = _render13.container;
578
+ container = _render14.container;
555
579
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
556
580
  expect(beforeContent).toHaveTextContent('XY');
557
581
  });
558
582
  it("should render option's after content in input field when isOptionContentAppliedToInput is set to true but renderAfterInput is also set", async () => {
559
- const _render14 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
583
+ const _render15 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
560
584
  renderLabel: "Choose an option",
561
585
  isOptionContentAppliedToInput: true,
562
586
  inputValue: optionsWithAfterContent[0].label,
563
587
  renderAfterInput: "ZZ",
564
588
  children: getOptionsWithAfterContent('opt1')
565
589
  })),
566
- container = _render14.container;
590
+ container = _render15.container;
567
591
  const afterContent = container.querySelector('span[class$="-textInput__afterElement"]');
568
592
  expect(afterContent).toHaveTextContent('XY');
569
593
  });
570
594
  it("should not render option's before content in input field when isOptionContentAppliedToInput is set to true but inputValue is not set", async () => {
571
- const _render15 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
595
+ const _render16 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
572
596
  renderLabel: "Choose an option",
573
597
  isOptionContentAppliedToInput: true,
574
598
  children: getOptionsWithBeforeContent('opt1')
575
599
  })),
576
- container = _render15.container;
600
+ container = _render16.container;
577
601
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
578
602
  expect(beforeContent).not.toHaveTextContent('XY');
579
603
  });
580
604
  it("should render option's before content in input field when isOptionContentAppliedToInput is set to true and both optionBeforeContent and optionAfterContent are provided", async () => {
581
- const _render16 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
605
+ const _render17 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
582
606
  renderLabel: "Choose an option",
583
607
  isOptionContentAppliedToInput: true,
584
608
  inputValue: optionsWithBeforeAndAfterContent[0].label,
585
609
  children: getOptionsWithBeforeAndAfterContent('opt1')
586
610
  })),
587
- container = _render16.container;
611
+ container = _render17.container;
588
612
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
589
613
  expect(beforeContent).toHaveTextContent('XY');
590
614
  });
591
615
  it("should render option's after content in input field when isOptionContentAppliedToInput is set to true and both optionBeforeContent and optionAfterContent are provided", async () => {
592
- const _render17 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
616
+ const _render18 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
593
617
  renderLabel: "Choose an option",
594
618
  isOptionContentAppliedToInput: true,
595
619
  inputValue: optionsWithBeforeAndAfterContent[0].label,
596
620
  children: getOptionsWithBeforeAndAfterContent('opt1')
597
621
  })),
598
- container = _render17.container;
622
+ container = _render18.container;
599
623
  const afterContent = container.querySelector('span[class$="-textInput__afterElement"]');
600
624
  expect(afterContent).toHaveTextContent('ZZ');
601
625
  });
602
626
  it('should render arrow in input field when isOptionContentAppliedToInput is set to true but inputValue is not set', async () => {
603
- const _render18 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
627
+ const _render19 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
604
628
  renderLabel: "Choose an option",
605
629
  isOptionContentAppliedToInput: true,
606
630
  children: getOptionsWithBeforeContent('opt1')
607
631
  })),
608
- container = _render18.container;
632
+ container = _render19.container;
609
633
  const spanElement = container.querySelector('span[class$="-textInput__afterElement"]');
610
634
  const svgElement = spanElement.querySelector('svg[name="IconArrowOpenDown"]');
611
635
  expect(svgElement).toBeInTheDocument();
612
636
  });
613
637
  it("should not render option's after content in input field when isOptionContentAppliedToInput is set to true but inputValue is not set", async () => {
614
- const _render19 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
638
+ const _render20 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
615
639
  renderLabel: "Choose an option",
616
640
  isOptionContentAppliedToInput: true,
617
641
  children: getOptionsWithBeforeContent('opt1')
618
642
  })),
619
- container = _render19.container;
643
+ container = _render20.container;
620
644
  const afterContent = container.querySelector('span[class$="-textInput__afterElement"]');
621
645
  expect(afterContent).not.toHaveTextContent('XY');
622
646
  });
623
647
  it("should render option's before content input field when isOptionContentAppliedToInput is set to true with group options", async () => {
624
- const _render20 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
648
+ const _render21 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
625
649
  renderLabel: "Choose an option",
626
650
  isOptionContentAppliedToInput: true,
627
651
  inputValue: groupOptionsWithBeforeContent.Options1[0].label,
628
652
  children: getGroupOptionsWithBeforeContent('opt1')
629
653
  })),
630
- container = _render20.container;
654
+ container = _render21.container;
631
655
  const beforeContent = container.querySelector('span[class$="-textInput__layout"]');
632
656
  expect(beforeContent).toHaveTextContent('XY');
633
657
  });
634
658
  it('should render arrow icon when isOptionContentAppliedToInput is set to true with before content and group options', async () => {
635
- const _render21 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
659
+ const _render22 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
636
660
  renderLabel: "Choose an option",
637
661
  isOptionContentAppliedToInput: true,
638
662
  inputValue: groupOptionsWithBeforeContent.Options1[0].label,
639
663
  children: getGroupOptionsWithBeforeContent('opt1')
640
664
  })),
641
- container = _render21.container;
665
+ container = _render22.container;
642
666
  const spanElement = container.querySelector('span[class$="-textInput__afterElement"]');
643
667
  const svgElement = spanElement.querySelector('svg[name="IconArrowOpenDown"]');
644
668
  expect(svgElement).toBeInTheDocument();
645
669
  });
646
670
  it("should render option's after content input field when isOptionContentAppliedToInput is set to true with group options", async () => {
647
- const _render22 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
671
+ const _render23 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
648
672
  renderLabel: "Choose an option",
649
673
  isOptionContentAppliedToInput: true,
650
674
  inputValue: groupOptionsWithAfterContent.Options2[0].label,
651
675
  children: getGroupOptionsWithAfterContent('opt4')
652
676
  })),
653
- container = _render22.container;
677
+ container = _render23.container;
654
678
  const afterContent = container.querySelector('span[class$="-textInput__afterElement"]');
655
679
  expect(afterContent).toHaveTextContent('AB');
656
680
  });
@@ -703,13 +727,13 @@ describe('<Select />', () => {
703
727
  describe('should fire onRequestShowOptions', () => {
704
728
  it('when root is clicked', async () => {
705
729
  const onRequestShowOptions = _vitest.vi.fn();
706
- const _render23 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
730
+ const _render24 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
707
731
  renderLabel: "Choose an option",
708
732
  onRequestShowOptions: onRequestShowOptions,
709
733
  children: getOptions()
710
734
  })),
711
- container = _render23.container,
712
- rerender = _render23.rerender;
735
+ container = _render24.container,
736
+ rerender = _render24.rerender;
713
737
  const icon = container.querySelector('svg[name="IconArrowOpenDown"]');
714
738
  const label = _react2.screen.getByText('Choose an option');
715
739
  expect(icon).toBeInTheDocument();
@@ -735,12 +759,12 @@ describe('<Select />', () => {
735
759
  });
736
760
  it('when input is clicked', async () => {
737
761
  const onRequestShowOptions = _vitest.vi.fn();
738
- const _render24 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
762
+ const _render25 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
739
763
  renderLabel: "Choose an option",
740
764
  onRequestShowOptions: onRequestShowOptions,
741
765
  children: getOptions()
742
766
  })),
743
- rerender = _render24.rerender;
767
+ rerender = _render25.rerender;
744
768
  const input = _react2.screen.getByLabelText('Choose an option');
745
769
  await _userEvent.default.click(input);
746
770
  await (0, _react2.waitFor)(() => {
@@ -776,12 +800,12 @@ describe('<Select />', () => {
776
800
  });
777
801
  it('when space is pressed', async () => {
778
802
  const onRequestShowOptions = _vitest.vi.fn();
779
- const _render25 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
803
+ const _render26 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
780
804
  renderLabel: "Choose an option",
781
805
  onRequestShowOptions: onRequestShowOptions,
782
806
  children: getOptions()
783
807
  })),
784
- rerender = _render25.rerender;
808
+ rerender = _render26.rerender;
785
809
  const input = _react2.screen.getByLabelText('Choose an option');
786
810
  await _userEvent.default.type(input, '{space}');
787
811
  await (0, _react2.waitFor)(() => {
@@ -802,13 +826,13 @@ describe('<Select />', () => {
802
826
  describe('should fire onRequestHideOptions', () => {
803
827
  it('when root is clicked and isShowingOptions is true', async () => {
804
828
  const onRequestHideOptions = _vitest.vi.fn();
805
- const _render26 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
829
+ const _render27 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
806
830
  renderLabel: "Choose an option",
807
831
  isShowingOptions: true,
808
832
  onRequestHideOptions: onRequestHideOptions,
809
833
  children: getOptions()
810
834
  })),
811
- container = _render26.container;
835
+ container = _render27.container;
812
836
  const icon = container.querySelector('svg[name="IconArrowOpenUp"]');
813
837
  const label = _react2.screen.getByText('Choose an option');
814
838
  expect(icon).toBeInTheDocument();
@@ -839,13 +863,13 @@ describe('<Select />', () => {
839
863
  });
840
864
  it('when input is clicked', async () => {
841
865
  const onRequestHideOptions = _vitest.vi.fn();
842
- const _render27 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
866
+ const _render28 = (0, _react2.render)((0, _jsxRuntime.jsx)(_index.default, {
843
867
  renderLabel: "Choose an option",
844
868
  isShowingOptions: true,
845
869
  onRequestHideOptions: onRequestHideOptions,
846
870
  children: getOptions()
847
871
  })),
848
- rerender = _render27.rerender;
872
+ rerender = _render28.rerender;
849
873
  const input = _react2.screen.getByLabelText('Choose an option');
850
874
  await _userEvent.default.click(input);
851
875
  await (0, _react2.waitFor)(() => {
@@ -935,8 +959,8 @@ describe('<Select />', () => {
935
959
  it.each(generatedComponents)('should be accessible with example: $description', async ({
936
960
  content
937
961
  }) => {
938
- const _render28 = (0, _react2.render)(content),
939
- container = _render28.container;
962
+ const _render29 = (0, _react2.render)(content),
963
+ container = _render29.container;
940
964
  const axeCheck = await (0, _runAxeCheck.runAxeCheck)(container);
941
965
  expect(axeCheck).toBe(true);
942
966
  });
@@ -212,19 +212,18 @@ let Select = exports.Select = (_dec = (0, _withDeterministicId.withDeterministic
212
212
  return selectedOptionId;
213
213
  }
214
214
  scrollToOption(id) {
215
- if (this._listView) {
216
- const option = this._listView.querySelector(`[id="${id}"]`);
217
- if (!option) return;
218
- const listItem = option.parentNode;
219
- const parentTop = (0, _getBoundingClientRect.getBoundingClientRect)(this._listView).top;
220
- const elemTop = (0, _getBoundingClientRect.getBoundingClientRect)(listItem).top;
221
- const parentBottom = parentTop + this._listView.clientHeight;
222
- const elemBottom = elemTop + (listItem ? listItem.clientHeight : 0);
223
- if (elemBottom > parentBottom) {
224
- this._listView.scrollTop += elemBottom - parentBottom;
225
- } else if (elemTop < parentTop) {
226
- this._listView.scrollTop -= parentTop - elemTop;
227
- }
215
+ if (!this._listView || !id) return;
216
+ const option = this._listView.querySelector(`[id="${CSS.escape(id)}"]`);
217
+ if (!option) return;
218
+ const listItem = option.parentNode;
219
+ const parentTop = (0, _getBoundingClientRect.getBoundingClientRect)(this._listView).top;
220
+ const elemTop = (0, _getBoundingClientRect.getBoundingClientRect)(listItem).top;
221
+ const parentBottom = parentTop + this._listView.clientHeight;
222
+ const elemBottom = elemTop + (listItem ? listItem.clientHeight : 0);
223
+ if (elemBottom > parentBottom) {
224
+ this._listView.scrollTop += elemBottom - parentBottom;
225
+ } else if (elemTop < parentTop) {
226
+ this._listView.scrollTop -= parentTop - elemTop;
228
227
  }
229
228
  }
230
229
  highlightOption(event, id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-select",
3
- "version": "10.18.2-snapshot-0",
3
+ "version": "10.18.2-snapshot-2",
4
4
  "description": "A component for select and autocomplete behavior.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -23,12 +23,12 @@
23
23
  },
24
24
  "license": "MIT",
25
25
  "devDependencies": {
26
- "@instructure/ui-axe-check": "10.18.2-snapshot-0",
27
- "@instructure/ui-babel-preset": "10.18.2-snapshot-0",
28
- "@instructure/ui-color-utils": "10.18.2-snapshot-0",
29
- "@instructure/ui-scripts": "10.18.2-snapshot-0",
30
- "@instructure/ui-test-utils": "10.18.2-snapshot-0",
31
- "@instructure/ui-themes": "10.18.2-snapshot-0",
26
+ "@instructure/ui-axe-check": "10.18.2-snapshot-2",
27
+ "@instructure/ui-babel-preset": "10.18.2-snapshot-2",
28
+ "@instructure/ui-color-utils": "10.18.2-snapshot-2",
29
+ "@instructure/ui-scripts": "10.18.2-snapshot-2",
30
+ "@instructure/ui-test-utils": "10.18.2-snapshot-2",
31
+ "@instructure/ui-themes": "10.18.2-snapshot-2",
32
32
  "@testing-library/jest-dom": "^6.6.3",
33
33
  "@testing-library/react": "^16.0.1",
34
34
  "@testing-library/user-event": "^14.5.2",
@@ -36,22 +36,22 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@babel/runtime": "^7.26.0",
39
- "@instructure/emotion": "10.18.2-snapshot-0",
40
- "@instructure/shared-types": "10.18.2-snapshot-0",
41
- "@instructure/ui-dom-utils": "10.18.2-snapshot-0",
42
- "@instructure/ui-form-field": "10.18.2-snapshot-0",
43
- "@instructure/ui-icons": "10.18.2-snapshot-0",
44
- "@instructure/ui-options": "10.18.2-snapshot-0",
45
- "@instructure/ui-popover": "10.18.2-snapshot-0",
46
- "@instructure/ui-position": "10.18.2-snapshot-0",
47
- "@instructure/ui-prop-types": "10.18.2-snapshot-0",
48
- "@instructure/ui-react-utils": "10.18.2-snapshot-0",
49
- "@instructure/ui-selectable": "10.18.2-snapshot-0",
50
- "@instructure/ui-testable": "10.18.2-snapshot-0",
51
- "@instructure/ui-text-input": "10.18.2-snapshot-0",
52
- "@instructure/ui-utils": "10.18.2-snapshot-0",
53
- "@instructure/ui-view": "10.18.2-snapshot-0",
54
- "@instructure/uid": "10.18.2-snapshot-0",
39
+ "@instructure/emotion": "10.18.2-snapshot-2",
40
+ "@instructure/shared-types": "10.18.2-snapshot-2",
41
+ "@instructure/ui-dom-utils": "10.18.2-snapshot-2",
42
+ "@instructure/ui-form-field": "10.18.2-snapshot-2",
43
+ "@instructure/ui-icons": "10.18.2-snapshot-2",
44
+ "@instructure/ui-options": "10.18.2-snapshot-2",
45
+ "@instructure/ui-popover": "10.18.2-snapshot-2",
46
+ "@instructure/ui-position": "10.18.2-snapshot-2",
47
+ "@instructure/ui-prop-types": "10.18.2-snapshot-2",
48
+ "@instructure/ui-react-utils": "10.18.2-snapshot-2",
49
+ "@instructure/ui-selectable": "10.18.2-snapshot-2",
50
+ "@instructure/ui-testable": "10.18.2-snapshot-2",
51
+ "@instructure/ui-text-input": "10.18.2-snapshot-2",
52
+ "@instructure/ui-utils": "10.18.2-snapshot-2",
53
+ "@instructure/ui-view": "10.18.2-snapshot-2",
54
+ "@instructure/uid": "10.18.2-snapshot-2",
55
55
  "prop-types": "^15.8.1"
56
56
  },
57
57
  "peerDependencies": {
@@ -316,6 +316,29 @@ describe('<Select />', () => {
316
316
  consoleErrorMock.mockRestore()
317
317
  })
318
318
 
319
+ it('should not crash for weird option ids', async () => {
320
+ const weirdID = 'some_`w@ei:r|!@#$%^&*(()|\\.l/d"id'
321
+ vi.useFakeTimers()
322
+ const { container } = render(
323
+ <Select
324
+ renderLabel="Choose an option"
325
+ scrollToHighlightedOption
326
+ isShowingOptions
327
+ >
328
+ <Select.Option id={weirdID} key="1" value="2" isHighlighted={true}>
329
+ op1
330
+ </Select.Option>
331
+ <Select.Option id="sdfsdfsd" key="2" value="2">
332
+ op2
333
+ </Select.Option>
334
+ </Select>
335
+ )
336
+ vi.advanceTimersToNextFrame()
337
+ vi.useRealTimers()
338
+ const input = container.querySelector('input')
339
+ expect(input).toBeInTheDocument()
340
+ })
341
+
319
342
  it('should have role button in Safari without onInputChange', async () => {
320
343
  const { container } = render(
321
344
  <Select renderLabel="Choose an option">{getOptions()}</Select>
@@ -291,22 +291,21 @@ class Select extends Component<SelectProps> {
291
291
  }
292
292
 
293
293
  scrollToOption(id?: string) {
294
- if (this._listView) {
295
- const option = this._listView.querySelector(`[id="${id}"]`)
296
- if (!option) return
297
-
298
- const listItem = option.parentNode
299
- const parentTop = getBoundingClientRect(this._listView).top
300
- const elemTop = getBoundingClientRect(listItem).top
301
- const parentBottom = parentTop + this._listView.clientHeight
302
- const elemBottom =
303
- elemTop + (listItem ? (listItem as Element).clientHeight : 0)
304
-
305
- if (elemBottom > parentBottom) {
306
- this._listView.scrollTop += elemBottom - parentBottom
307
- } else if (elemTop < parentTop) {
308
- this._listView.scrollTop -= parentTop - elemTop
309
- }
294
+ if (!this._listView || !id) return
295
+ const option = this._listView.querySelector(`[id="${CSS.escape(id)}"]`)
296
+ if (!option) return
297
+
298
+ const listItem = option.parentNode
299
+ const parentTop = getBoundingClientRect(this._listView).top
300
+ const elemTop = getBoundingClientRect(listItem).top
301
+ const parentBottom = parentTop + this._listView.clientHeight
302
+ const elemBottom =
303
+ elemTop + (listItem ? (listItem as Element).clientHeight : 0)
304
+
305
+ if (elemBottom > parentBottom) {
306
+ this._listView.scrollTop += elemBottom - parentBottom
307
+ } else if (elemTop < parentTop) {
308
+ this._listView.scrollTop -= parentTop - elemTop
310
309
  }
311
310
  }
312
311