@idds/react 1.5.43 → 1.5.45

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/dist/index.es.js CHANGED
@@ -37,6 +37,17 @@ const iddsColorTokens = {
37
37
  "cyan-700": "var(--ina-cyan-700)",
38
38
  "cyan-800": "var(--ina-cyan-800)",
39
39
  "cyan-900": "var(--ina-cyan-900)",
40
+ // Teal Colors
41
+ "teal-50": "var(--ina-teal-50)",
42
+ "teal-100": "var(--ina-teal-100)",
43
+ "teal-200": "var(--ina-teal-200)",
44
+ "teal-300": "var(--ina-teal-300)",
45
+ "teal-400": "var(--ina-teal-400)",
46
+ "teal-500": "var(--ina-teal-500)",
47
+ "teal-600": "var(--ina-teal-600)",
48
+ "teal-700": "var(--ina-teal-700)",
49
+ "teal-800": "var(--ina-teal-800)",
50
+ "teal-900": "var(--ina-teal-900)",
40
51
  // Green Colors
41
52
  "green-50": "var(--ina-green-50)",
42
53
  "green-100": "var(--ina-green-100)",
@@ -81,6 +92,17 @@ const iddsColorTokens = {
81
92
  "orange-700": "var(--ina-orange-700)",
82
93
  "orange-800": "var(--ina-orange-800)",
83
94
  "orange-900": "var(--ina-orange-900)",
95
+ // Coral Colors
96
+ "coral-50": "var(--ina-coral-50)",
97
+ "coral-100": "var(--ina-coral-100)",
98
+ "coral-200": "var(--ina-coral-200)",
99
+ "coral-300": "var(--ina-coral-300)",
100
+ "coral-400": "var(--ina-coral-400)",
101
+ "coral-500": "var(--ina-coral-500)",
102
+ "coral-600": "var(--ina-coral-600)",
103
+ "coral-700": "var(--ina-coral-700)",
104
+ "coral-800": "var(--ina-coral-800)",
105
+ "coral-900": "var(--ina-coral-900)",
84
106
  // Red Colors
85
107
  "red-50": "var(--ina-red-50)",
86
108
  "red-100": "var(--ina-red-100)",
@@ -114,6 +136,17 @@ const iddsColorTokens = {
114
136
  "magenta-700": "var(--ina-magenta-700)",
115
137
  "magenta-800": "var(--ina-magenta-800)",
116
138
  "magenta-900": "var(--ina-magenta-900)",
139
+ // Violet Colors
140
+ "violet-50": "var(--ina-violet-50)",
141
+ "violet-100": "var(--ina-violet-100)",
142
+ "violet-200": "var(--ina-violet-200)",
143
+ "violet-300": "var(--ina-violet-300)",
144
+ "violet-400": "var(--ina-violet-400)",
145
+ "violet-500": "var(--ina-violet-500)",
146
+ "violet-600": "var(--ina-violet-600)",
147
+ "violet-700": "var(--ina-violet-700)",
148
+ "violet-800": "var(--ina-violet-800)",
149
+ "violet-900": "var(--ina-violet-900)",
117
150
  // Purple Colors
118
151
  "purple-50": "var(--ina-purple-50)",
119
152
  "purple-100": "var(--ina-purple-100)",
@@ -125,6 +158,17 @@ const iddsColorTokens = {
125
158
  "purple-700": "var(--ina-purple-700)",
126
159
  "purple-800": "var(--ina-purple-800)",
127
160
  "purple-900": "var(--ina-purple-900)",
161
+ // Lilac Colors
162
+ "lilac-50": "var(--ina-lilac-50)",
163
+ "lilac-100": "var(--ina-lilac-100)",
164
+ "lilac-200": "var(--ina-lilac-200)",
165
+ "lilac-300": "var(--ina-lilac-300)",
166
+ "lilac-400": "var(--ina-lilac-400)",
167
+ "lilac-500": "var(--ina-lilac-500)",
168
+ "lilac-600": "var(--ina-lilac-600)",
169
+ "lilac-700": "var(--ina-lilac-700)",
170
+ "lilac-800": "var(--ina-lilac-800)",
171
+ "lilac-900": "var(--ina-lilac-900)",
128
172
  // Indigo Colors
129
173
  "indigo-50": "var(--ina-indigo-50)",
130
174
  "indigo-100": "var(--ina-indigo-100)",
@@ -278,6 +322,7 @@ const inapasColorTokens = {
278
322
  };
279
323
  const bgnColorTokens = {
280
324
  // Primary shades
325
+ "primary-25": "var(--ina-primary-25)",
281
326
  "primary-50": "var(--ina-primary-50)",
282
327
  "primary-100": "var(--ina-primary-100)",
283
328
  "primary-200": "var(--ina-primary-200)",
@@ -288,7 +333,19 @@ const bgnColorTokens = {
288
333
  "primary-700": "var(--ina-primary-700)",
289
334
  "primary-800": "var(--ina-primary-800)",
290
335
  "primary-900": "var(--ina-primary-900)",
291
- "primary-primary": "var(--ina-primary-primary)"
336
+ "primary-primary": "var(--ina-primary-primary)",
337
+ // Secondary shades
338
+ "secondary-25": "var(--ina-secondary-25)",
339
+ "secondary-50": "var(--ina-secondary-50)",
340
+ "secondary-100": "var(--ina-secondary-100)",
341
+ "secondary-200": "var(--ina-secondary-200)",
342
+ "secondary-300": "var(--ina-secondary-300)",
343
+ "secondary-400": "var(--ina-secondary-400)",
344
+ "secondary-500": "var(--ina-secondary-500)",
345
+ "secondary-600": "var(--ina-secondary-600)",
346
+ "secondary-700": "var(--ina-secondary-700)",
347
+ "secondary-800": "var(--ina-secondary-800)",
348
+ "secondary-900": "var(--ina-secondary-900)"
292
349
  };
293
350
  const bknColorTokens = {
294
351
  // Primary shades
@@ -2340,6 +2397,13 @@ function BasicDropdown({
2340
2397
  if (disabled) return;
2341
2398
  handleOpenChange(!isOpen);
2342
2399
  };
2400
+ const handleKeyDown = (e) => {
2401
+ if (disabled) return;
2402
+ if (e.key === "Enter" || e.key === " ") {
2403
+ e.preventDefault();
2404
+ handleOpenChange(!isOpen);
2405
+ }
2406
+ };
2343
2407
  useEffect(() => {
2344
2408
  const handleClickOutside = (event) => {
2345
2409
  if (containerRef.current && !containerRef.current.contains(event.target)) {
@@ -2348,11 +2412,18 @@ function BasicDropdown({
2348
2412
  }
2349
2413
  }
2350
2414
  };
2415
+ const handleEscape = (event) => {
2416
+ if (event.key === "Escape" && isOpen) {
2417
+ handleOpenChange(false);
2418
+ }
2419
+ };
2351
2420
  document.addEventListener("mousedown", handleClickOutside);
2352
2421
  document.addEventListener("touchstart", handleClickOutside);
2422
+ document.addEventListener("keydown", handleEscape);
2353
2423
  return () => {
2354
2424
  document.removeEventListener("mousedown", handleClickOutside);
2355
2425
  document.removeEventListener("touchstart", handleClickOutside);
2426
+ document.removeEventListener("keydown", handleEscape);
2356
2427
  };
2357
2428
  }, [isOpen, onOpenChange]);
2358
2429
  const isPrimitiveTrigger = typeof trigger === "string" || typeof trigger === "number";
@@ -2363,11 +2434,18 @@ function BasicDropdown({
2363
2434
  ref: triggerRef,
2364
2435
  className: clsx("ina-basic-dropdown__trigger", triggerClassName),
2365
2436
  onClick: toggle,
2437
+ tabIndex: !isPrimitiveTrigger ? 0 : -1,
2438
+ role: !isPrimitiveTrigger ? "button" : void 0,
2439
+ "aria-haspopup": !isPrimitiveTrigger ? "true" : void 0,
2440
+ "aria-expanded": !isPrimitiveTrigger ? isOpen : void 0,
2441
+ onKeyDown: !isPrimitiveTrigger ? handleKeyDown : void 0,
2366
2442
  children: isPrimitiveTrigger ? /* @__PURE__ */ jsxs(
2367
2443
  "button",
2368
2444
  {
2369
2445
  type: "button",
2370
2446
  disabled,
2447
+ "aria-haspopup": "true",
2448
+ "aria-expanded": isOpen,
2371
2449
  className: clsx(
2372
2450
  "ina-basic-dropdown__trigger-button",
2373
2451
  isOpen && "ina-basic-dropdown__trigger-button--open"
@@ -3601,10 +3679,12 @@ function Modal({
3601
3679
  const [isVisible, setIsVisible] = useState(false);
3602
3680
  const closeBtnRef = useRef(null);
3603
3681
  const labelId = useRef(`modal-title-${Math.random().toString(36).slice(2)}`);
3682
+ const previousFocus = useRef(null);
3604
3683
  useEffect(() => setMounted(true), []);
3605
3684
  useEffect(() => {
3606
3685
  if (open) {
3607
3686
  setShouldRender(true);
3687
+ previousFocus.current = document.activeElement;
3608
3688
  requestAnimationFrame(() => {
3609
3689
  requestAnimationFrame(() => {
3610
3690
  setIsVisible(true);
@@ -3612,6 +3692,10 @@ function Modal({
3612
3692
  });
3613
3693
  } else {
3614
3694
  setIsVisible(false);
3695
+ if (previousFocus.current) {
3696
+ previousFocus.current.focus();
3697
+ previousFocus.current = null;
3698
+ }
3615
3699
  const timer = setTimeout(() => {
3616
3700
  setShouldRender(false);
3617
3701
  }, 300);
@@ -3629,13 +3713,39 @@ function Modal({
3629
3713
  }
3630
3714
  }, [shouldRender, mounted]);
3631
3715
  useEffect(() => {
3632
- var _a;
3633
3716
  if (!shouldRender || !mounted) return;
3634
3717
  if (isVisible) {
3635
- (_a = closeBtnRef.current) == null ? void 0 : _a.focus();
3718
+ setTimeout(() => {
3719
+ var _a;
3720
+ (_a = closeBtnRef.current) == null ? void 0 : _a.focus();
3721
+ }, 50);
3636
3722
  }
3637
3723
  const onKey = (e) => {
3638
- if (e.key === "Escape" && isVisible) onClose();
3724
+ if (e.key === "Escape" && isVisible) {
3725
+ onClose();
3726
+ return;
3727
+ }
3728
+ if (e.key === "Tab" && isVisible) {
3729
+ const modalElement = document.querySelector(".ina-modal__dialog");
3730
+ if (!modalElement) return;
3731
+ const focusableElements = modalElement.querySelectorAll(
3732
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
3733
+ );
3734
+ if (focusableElements.length === 0) return;
3735
+ const firstElement = focusableElements[0];
3736
+ const lastElement = focusableElements[focusableElements.length - 1];
3737
+ if (e.shiftKey) {
3738
+ if (document.activeElement === firstElement) {
3739
+ e.preventDefault();
3740
+ lastElement.focus();
3741
+ }
3742
+ } else {
3743
+ if (document.activeElement === lastElement) {
3744
+ e.preventDefault();
3745
+ firstElement.focus();
3746
+ }
3747
+ }
3748
+ }
3639
3749
  };
3640
3750
  document.addEventListener("keydown", onKey);
3641
3751
  return () => document.removeEventListener("keydown", onKey);
@@ -5221,10 +5331,13 @@ const SelectDropdown = ({
5221
5331
  required,
5222
5332
  selectionTitle
5223
5333
  }) => {
5334
+ var _a;
5224
5335
  const [isOpen, setIsOpen] = useState(false);
5225
5336
  const [internalSearchTerm, setInternalSearchTerm] = useState("");
5337
+ const [focusedIndex, setFocusedIndex] = useState(-1);
5226
5338
  const containerRef = useRef(null);
5227
5339
  const scrollContainerRef = useRef(null);
5340
+ const optionsRefs = useRef([]);
5228
5341
  const searchTimeoutRef = useRef(null);
5229
5342
  const selectedLabelsCacheRef = useRef(/* @__PURE__ */ new Map());
5230
5343
  const isSearchControlled = searchValue !== void 0;
@@ -5251,19 +5364,11 @@ const SelectDropdown = ({
5251
5364
  setInternalSearchTerm(searchValue);
5252
5365
  }
5253
5366
  }, [searchValue, isSearchControlled, internalSearchTerm]);
5254
- const handleLoadMoreClick = () => {
5255
- if (disabled || !hasMore || loading || !onLoadMore) return;
5256
- onLoadMore(currentPage + 1);
5257
- };
5258
5367
  useEffect(() => {
5259
5368
  const handleClickOutside = (e) => {
5260
5369
  if (containerRef.current && !containerRef.current.contains(e.target)) {
5261
5370
  setIsOpen(false);
5262
- if (isSearchControlled) {
5263
- onSearchChange == null ? void 0 : onSearchChange("");
5264
- } else {
5265
- setInternalSearchTerm("");
5266
- }
5371
+ setFocusedIndex(-1);
5267
5372
  onClose == null ? void 0 : onClose();
5268
5373
  }
5269
5374
  };
@@ -5366,6 +5471,18 @@ const SelectDropdown = ({
5366
5471
  const filteredOptions = onSearch ? options : !searchable ? options : options.filter(
5367
5472
  (o) => o.label.toLowerCase().includes(searchTerm.toLowerCase())
5368
5473
  );
5474
+ useEffect(() => {
5475
+ setFocusedIndex(-1);
5476
+ }, [filteredOptions]);
5477
+ useEffect(() => {
5478
+ var _a2;
5479
+ if (isOpen && focusedIndex >= 0 && optionsRefs.current[focusedIndex]) {
5480
+ (_a2 = optionsRefs.current[focusedIndex]) == null ? void 0 : _a2.scrollIntoView({
5481
+ block: "nearest",
5482
+ inline: "nearest"
5483
+ });
5484
+ }
5485
+ }, [focusedIndex, isOpen]);
5369
5486
  const handleSearchChange = (e) => {
5370
5487
  const newValue = e.target.value;
5371
5488
  if (isSearchControlled) {
@@ -5483,11 +5600,11 @@ const SelectDropdown = ({
5483
5600
  return "";
5484
5601
  };
5485
5602
  const handleTriggerClick = () => {
5486
- var _a;
5603
+ var _a2;
5487
5604
  if (!isOpen && !disabled) {
5488
5605
  setIsOpen(true);
5489
5606
  }
5490
- const input = (_a = containerRef.current) == null ? void 0 : _a.querySelector("input");
5607
+ const input = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector("input");
5491
5608
  if (input) {
5492
5609
  input.focus();
5493
5610
  }
@@ -5496,9 +5613,62 @@ const SelectDropdown = ({
5496
5613
  if (!isOpen) setIsOpen(true);
5497
5614
  handleSearchChange(e);
5498
5615
  };
5616
+ const handleOptionSelect = (option) => {
5617
+ var _a2;
5618
+ if (disabled || option.disabled) return;
5619
+ if (multiple) {
5620
+ const prev = Array.isArray(selected) ? [...selected] : [];
5621
+ const newSelected = prev.includes(option.value) ? prev.filter((v) => v !== option.value) : [...prev, option.value];
5622
+ if (prev.includes(option.value)) {
5623
+ selectedLabelsCacheRef.current.delete(option.value);
5624
+ } else {
5625
+ selectedLabelsCacheRef.current.set(option.value, option.label);
5626
+ }
5627
+ onSelect(newSelected);
5628
+ const input = (_a2 = containerRef.current) == null ? void 0 : _a2.querySelector("input");
5629
+ if (input) input.focus();
5630
+ } else {
5631
+ const isSelected = option.value === singleSelected;
5632
+ if (isSelected) {
5633
+ selectedLabelsCacheRef.current.delete(option.value);
5634
+ onSelect(null, option);
5635
+ } else {
5636
+ selectedLabelsCacheRef.current.set(option.value, option.label);
5637
+ onSelect(option.value, option);
5638
+ }
5639
+ setIsOpen(false);
5640
+ setFocusedIndex(-1);
5641
+ if (isSearchControlled) {
5642
+ onSearchChange == null ? void 0 : onSearchChange("");
5643
+ } else {
5644
+ setInternalSearchTerm("");
5645
+ }
5646
+ onClose == null ? void 0 : onClose();
5647
+ }
5648
+ };
5499
5649
  const handleInputKeyDown = (e) => {
5500
- if (e.key === "Enter") {
5650
+ if (e.key === "ArrowDown") {
5651
+ e.preventDefault();
5652
+ if (!isOpen) {
5653
+ setIsOpen(true);
5654
+ setFocusedIndex(0);
5655
+ } else {
5656
+ setFocusedIndex(
5657
+ (prev) => prev < filteredOptions.length - 1 ? prev + 1 : prev
5658
+ );
5659
+ }
5660
+ } else if (e.key === "ArrowUp") {
5501
5661
  e.preventDefault();
5662
+ setFocusedIndex((prev) => prev > 0 ? prev - 1 : prev);
5663
+ } else if (e.key === "Enter") {
5664
+ e.preventDefault();
5665
+ if (isOpen && focusedIndex >= 0 && focusedIndex < filteredOptions.length) {
5666
+ handleOptionSelect(filteredOptions[focusedIndex]);
5667
+ }
5668
+ } else if (e.key === "Escape") {
5669
+ e.preventDefault();
5670
+ setIsOpen(false);
5671
+ setFocusedIndex(-1);
5502
5672
  }
5503
5673
  };
5504
5674
  return /* @__PURE__ */ jsxs(
@@ -5535,7 +5705,8 @@ const SelectDropdown = ({
5535
5705
  onChange: onInputChange,
5536
5706
  onKeyDown: handleInputKeyDown,
5537
5707
  disabled,
5538
- "aria-autocomplete": "list"
5708
+ "aria-autocomplete": "list",
5709
+ "aria-activedescendant": isOpen && focusedIndex >= 0 ? `option-${(_a = filteredOptions[focusedIndex]) == null ? void 0 : _a.value}` : void 0
5539
5710
  }
5540
5711
  ) : /* @__PURE__ */ jsx(
5541
5712
  "span",
@@ -5581,6 +5752,12 @@ const SelectDropdown = ({
5581
5752
  {
5582
5753
  ref: scrollContainerRef,
5583
5754
  className: "ina-select-dropdown__options",
5755
+ onScroll: (e) => {
5756
+ const target = e.currentTarget;
5757
+ if (target.scrollHeight - target.scrollTop - target.clientHeight < 50 && !loading && hasMore && onLoadMore && !disabled) {
5758
+ onLoadMore(currentPage + 1);
5759
+ }
5760
+ },
5584
5761
  children: [
5585
5762
  selectionTitle && /* @__PURE__ */ jsx("div", { className: "ina-select-dropdown__selection-title", children: selectionTitle }),
5586
5763
  filteredOptions.map((option, index) => {
@@ -5618,56 +5795,26 @@ const SelectDropdown = ({
5618
5795
  }
5619
5796
  );
5620
5797
  }
5621
- const handleOptionClick = (e) => {
5622
- var _a;
5623
- e.preventDefault();
5624
- e.stopPropagation();
5625
- if (disabled || option.disabled) return;
5626
- if (multiple) {
5627
- const prev = Array.isArray(selected) ? [...selected] : [];
5628
- const newSelected = prev.includes(option.value) ? prev.filter((v) => v !== option.value) : [...prev, option.value];
5629
- if (prev.includes(option.value)) {
5630
- selectedLabelsCacheRef.current.delete(option.value);
5631
- } else {
5632
- selectedLabelsCacheRef.current.set(
5633
- option.value,
5634
- option.label
5635
- );
5636
- }
5637
- onSelect(newSelected);
5638
- const input = (_a = containerRef.current) == null ? void 0 : _a.querySelector("input");
5639
- if (input) input.focus();
5640
- } else {
5641
- if (isSelected) {
5642
- selectedLabelsCacheRef.current.delete(option.value);
5643
- onSelect(null, option);
5644
- } else {
5645
- selectedLabelsCacheRef.current.set(
5646
- option.value,
5647
- option.label
5648
- );
5649
- onSelect(option.value, option);
5650
- }
5651
- setIsOpen(false);
5652
- if (isSearchControlled) {
5653
- onSearchChange == null ? void 0 : onSearchChange("");
5654
- } else {
5655
- setInternalSearchTerm("");
5656
- }
5657
- onClose == null ? void 0 : onClose();
5658
- }
5659
- };
5660
5798
  return /* @__PURE__ */ jsxs(
5661
5799
  "button",
5662
5800
  {
5801
+ ref: (el) => {
5802
+ optionsRefs.current[index] = el;
5803
+ },
5804
+ id: `option-${option.value}`,
5663
5805
  type: "button",
5664
- onClick: handleOptionClick,
5806
+ onClick: (e) => {
5807
+ e.preventDefault();
5808
+ e.stopPropagation();
5809
+ handleOptionSelect(option);
5810
+ },
5665
5811
  disabled: disabled || option.disabled,
5666
5812
  className: clsx(
5667
5813
  "ina-select-dropdown__option",
5668
5814
  !multiple && isSelected && "ina-select-dropdown__option--selected-single",
5669
5815
  multiple && isSelected && "ina-select-dropdown__option--selected-multiple",
5670
- (disabled || option.disabled) && "ina-select-dropdown__option--disabled"
5816
+ (disabled || option.disabled) && "ina-select-dropdown__option--disabled",
5817
+ index === focusedIndex && "ina-select-dropdown__option--focused"
5671
5818
  ),
5672
5819
  children: [
5673
5820
  /* @__PURE__ */ jsx("div", { className: "ina-select-dropdown__option-content", children: labelContent }),
@@ -5678,15 +5825,6 @@ const SelectDropdown = ({
5678
5825
  );
5679
5826
  }),
5680
5827
  filteredOptions.length === 0 && !loading && /* @__PURE__ */ jsx("div", { className: "ina-select-dropdown__empty", children: "No results" }),
5681
- hasMore && !loading && filteredOptions.length > 0 && onLoadMore && !disabled && /* @__PURE__ */ jsx("div", { className: "ina-select-dropdown__load-more", children: /* @__PURE__ */ jsx(
5682
- "button",
5683
- {
5684
- type: "button",
5685
- onClick: handleLoadMoreClick,
5686
- className: "ina-select-dropdown__load-more-button",
5687
- children: "Tampilkan Lebih Banyak"
5688
- }
5689
- ) }),
5690
5828
  loading && /* @__PURE__ */ jsxs("div", { className: "ina-select-dropdown__loading", children: [
5691
5829
  /* @__PURE__ */ jsx("div", { className: "ina-select-dropdown__loading-spinner", children: /* @__PURE__ */ jsx(IconLoader2, { size: 20 }) }),
5692
5830
  /* @__PURE__ */ jsx("span", { className: "ina-select-dropdown__loading-text", children: "Loading..." })