@youngonesworks/ui 0.1.103 → 0.1.105

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.js CHANGED
@@ -3,17 +3,16 @@
3
3
 
4
4
  import * as React$1 from "react";
5
5
  import React, { Fragment, cloneElement, createRef, forwardRef, isValidElement, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
6
- import { IconAlertCircle, IconAlertTriangle, IconArrowNarrowLeft, IconBold, IconCalendar, IconCheck, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp, IconCircleCheck, IconClearFormatting, IconEyeCheck, IconEyeOff, IconFilter, IconHeart, IconHeartFilled, IconItalic, IconList, IconListNumbers, IconMessageDots, IconSelector, IconUnderline, IconX } from "@tabler/icons-react";
6
+ import { IconAlertCircle, IconAlertTriangle, IconArrowNarrowLeft, IconBold, IconCalendar, IconCheck, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp, IconCircleCheck, IconClearFormatting, IconDotsVertical, IconEyeCheck, IconEyeOff, IconFilter, IconHeart, IconHeartFilled, IconItalic, IconList, IconListNumbers, IconMessageDots, IconSearch, IconSelector, IconUnderline, IconX } from "@tabler/icons-react";
7
7
  import clsx from "clsx";
8
8
  import { twMerge } from "tailwind-merge";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
- import { Tooltip as Tooltip$1 } from "react-tooltip";
10
+ import { FloatingArrow, FloatingFocusManager, FloatingPortal, arrow, autoUpdate, flip, offset, shift, useClick, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole } from "@floating-ui/react";
11
11
  import { DayPicker, useDayPicker } from "react-day-picker";
12
12
  import { addMonths, format, setMonth } from "date-fns";
13
13
  import { enGB, fr, nl, nlBE } from "date-fns/locale";
14
- import { FloatingArrow, arrow, autoUpdate, flip, offset, shift, useClick, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole } from "@floating-ui/react";
15
14
  import { createPortal } from "react-dom";
16
- import ReactSelect, { components } from "react-select";
15
+ import { Tooltip as Tooltip$1 } from "react-tooltip";
17
16
  import { Placeholder } from "@tiptap/extension-placeholder";
18
17
  import { Underline } from "@tiptap/extension-underline";
19
18
  import { EditorContent, useEditor } from "@tiptap/react";
@@ -93,6 +92,113 @@ const AccordionWrapper = ({ children, className }) => /* @__PURE__ */ jsx("div",
93
92
  children
94
93
  });
95
94
 
95
+ //#endregion
96
+ //#region src/hooks/useMergeRefs.ts
97
+ function useMergeRefs(...refs) {
98
+ return useCallback((value) => {
99
+ refs.forEach((ref) => {
100
+ if (typeof ref === "function") {
101
+ ref(value);
102
+ } else if (ref) {
103
+ ref.current = value;
104
+ }
105
+ });
106
+ }, [refs]);
107
+ }
108
+
109
+ //#endregion
110
+ //#region src/components/tooltip/index.tsx
111
+ const sizeClasses = {
112
+ xs: "max-w-xs",
113
+ sm: "max-w-sm",
114
+ md: "max-w-md",
115
+ lg: "max-w-lg"
116
+ };
117
+ const Tooltip = ({ content, children, passedOpen = false, size = "md", variant = "default" }) => {
118
+ const [isOpen, setIsOpen] = useState(passedOpen);
119
+ const arrowRef = useRef(null);
120
+ const { refs, floatingStyles, context } = useFloating({
121
+ open: isOpen,
122
+ onOpenChange: setIsOpen,
123
+ placement: "top",
124
+ middleware: [
125
+ variant === "default" ? offset(20) : offset(25),
126
+ flip(),
127
+ shift(),
128
+ arrow({ element: arrowRef })
129
+ ],
130
+ whileElementsMounted: autoUpdate
131
+ });
132
+ const hover = useHover(context, { move: false });
133
+ const focus = useFocus(context);
134
+ const dismiss = useDismiss(context);
135
+ const role = useRole(context, { role: "tooltip" });
136
+ const { getReferenceProps, getFloatingProps } = useInteractions([
137
+ hover,
138
+ focus,
139
+ dismiss,
140
+ role
141
+ ]);
142
+ const childRef = children.ref;
143
+ const mergedRef = useMergeRefs(refs.setReference, childRef);
144
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [isValidElement(children) && cloneElement(children, getReferenceProps({
145
+ ...children.props,
146
+ ...getReferenceProps(),
147
+ ref: mergedRef
148
+ })), isOpen && /* @__PURE__ */ jsx("div", {
149
+ ref: refs.setFloating,
150
+ style: floatingStyles,
151
+ ...getFloatingProps(),
152
+ className: "z-70 drop-shadow-xl",
153
+ "data-testid": "tooltip",
154
+ "data-component": "tooltip",
155
+ children: variant === "default" ? /* @__PURE__ */ jsxs("div", {
156
+ "data-testid": "tooltip-container",
157
+ className: "w-full rounded bg-gray-800 pt-[3px] text-white",
158
+ children: [/* @__PURE__ */ jsx("div", {
159
+ "data-testid": "tooltip-content",
160
+ className: `${sizeClasses[size]} px-2 py-1 text-sm font-normal`,
161
+ children: content
162
+ }), /* @__PURE__ */ jsx(FloatingArrow, {
163
+ ref: arrowRef,
164
+ context,
165
+ width: 10,
166
+ height: 6,
167
+ tipRadius: 1,
168
+ "data-testid": "tooltip-arrow",
169
+ className: "fill-gray-800 drop-shadow-xl"
170
+ })]
171
+ }) : /* @__PURE__ */ jsxs("div", {
172
+ "data-testid": "tooltip-container",
173
+ className: "bg-linear-gradient-x pt-[3px]",
174
+ children: [/* @__PURE__ */ jsx("div", {
175
+ "data-testid": "tooltip-content",
176
+ className: `${sizeClasses[size]} overflow-hidden bg-white p-5 px-2 py-1 text-start text-sm font-normal`,
177
+ children: /* @__PURE__ */ jsx("p", { children: content })
178
+ }), size === "md" ? /* @__PURE__ */ jsx(FloatingArrow, {
179
+ ref: arrowRef,
180
+ context,
181
+ width: 25,
182
+ height: 17,
183
+ tipRadius: 1,
184
+ fill: "white",
185
+ className: "drop-shadow-xl",
186
+ "data-testid": "tooltip-arrow"
187
+ }) : /* @__PURE__ */ jsx(FloatingArrow, {
188
+ ref: arrowRef,
189
+ context,
190
+ width: 10,
191
+ height: 6,
192
+ tipRadius: 1,
193
+ fill: "white",
194
+ className: "drop-shadow-xl",
195
+ "data-testid": "tooltip-arrow"
196
+ })]
197
+ })
198
+ })] });
199
+ };
200
+ Tooltip.displayName = "Tooltip";
201
+
96
202
  //#endregion
97
203
  //#region src/utils/enums.ts
98
204
  let ACTION_ICON_STYLE_VARIANT = /* @__PURE__ */ function(ACTION_ICON_STYLE_VARIANT$1) {
@@ -170,34 +276,35 @@ function formatIcon(icon, defaultFormatAttributes) {
170
276
 
171
277
  //#endregion
172
278
  //#region src/components/actionIcon/index.tsx
173
- const ActionIcon = forwardRef(({ title, disabled = false, styleVariant = "default", icon, type = "button", "data-testid": testId, iconSize = 20, strokeWidth = 1, onClick, className,...props }, ref) => {
279
+ const ActionIcon = ({ ref, title, disabled = false, styleVariant = "default", icon, type = "button", "data-testid": testId, iconSize = 20, strokeWidth = 1, onClick, className,...props }) => {
174
280
  const variantClassNames = clsx({
175
281
  "active:translate-y-[1px] content-center flex items-center justify-center rounded-[4px] border border-gray-200 hover:border-black text-black child:p-10 w-[36px] h-[36px] disabled:text-gray-500": styleVariant === ACTION_ICON_STYLE_VARIANT.DEFAULT,
176
282
  "active:translate-y-[1px] border-none content-center flex items-center justify-center rounded-[4px] border text-black child:p-10 w-[36px] h-[36px] disabled:text-gray-500": styleVariant === ACTION_ICON_STYLE_VARIANT.TRANSPARENT,
177
283
  "active:translate-y-[1px] content-center flex items-center justify-center rounded-[4px] child:p-10 w-[37px] h-[37px] text-black rounded-full bg-primary hover:bg-turquoise-700 disabled:turquoise-50 disabled:text-gray-800": styleVariant === ACTION_ICON_STYLE_VARIANT.ROUND,
178
284
  "w-7 h-7 active:translate-y-[1px] content-center flex items-center justify-center rounded-[4px] border border-gray-200 hover:border-black text-black hover:bg-gray-50 disabled:text-gray-500": styleVariant === ACTION_ICON_STYLE_VARIANT.SMALL
179
285
  });
180
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
181
- title,
182
- type,
183
- disabled,
184
- "data-testid": testId,
185
- "data-component": "ActionIcon",
186
- className: cn(variantClassNames, { "hover:bg-transparant cursor-not-allowed hover:border-gray-200": disabled }, className),
187
- onClick,
188
- ref,
189
- "data-tooltip-id": title,
190
- "data-tooltip-content": title,
191
- ...props,
192
- children: icon ? formatIcon(icon, {
193
- stroke: strokeWidth,
194
- size: iconSize
195
- }) : props.children
196
- }), /* @__PURE__ */ jsx(Tooltip$1, {
197
- id: title,
198
- className: "z-[99]"
199
- })] });
200
- });
286
+ return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(Tooltip, {
287
+ size: "sm",
288
+ content: title,
289
+ children: /* @__PURE__ */ jsx("button", {
290
+ title,
291
+ type,
292
+ disabled,
293
+ "data-testid": testId,
294
+ "data-component": "ActionIcon",
295
+ className: cn(variantClassNames, { "hover:bg-transparant cursor-not-allowed hover:border-gray-200": disabled }, className),
296
+ onClick,
297
+ ref,
298
+ "data-tooltip-id": title,
299
+ "data-tooltip-content": title,
300
+ ...props,
301
+ children: icon ? formatIcon(icon, {
302
+ stroke: strokeWidth,
303
+ size: iconSize
304
+ }) : props.children
305
+ })
306
+ }) });
307
+ };
201
308
  ActionIcon.displayName = "ActionIcon";
202
309
 
203
310
  //#endregion
@@ -1491,6 +1598,86 @@ const Island = ({ children, className, noShadow = false, noPadding = false,...pr
1491
1598
  });
1492
1599
  Island.displayName = "Island";
1493
1600
 
1601
+ //#endregion
1602
+ //#region src/components/kebabMenu/index.tsx
1603
+ const KebabMenu = ({ title, tooltip, content, disabled = false, styleVariant = "default" }) => {
1604
+ const [isOpen, setIsOpen] = useState(false);
1605
+ const menuRef = useRef(null);
1606
+ const defaultStyling = "text-black flex items-center justify-self-end gap-1 bg-transparent font-medium py-1 h-9 min-w-9 cursor-pointer px-0";
1607
+ const handleToggle = () => {
1608
+ if (!disabled) setIsOpen((prev) => !prev);
1609
+ };
1610
+ const handleItemClick = (onClick) => {
1611
+ if (!disabled) {
1612
+ onClick();
1613
+ setIsOpen(false);
1614
+ }
1615
+ };
1616
+ const handleClickOutside = (event) => {
1617
+ if (menuRef.current && !menuRef.current.contains(event.target)) setIsOpen(false);
1618
+ };
1619
+ useEffect(() => {
1620
+ document.addEventListener("mousedown", handleClickOutside);
1621
+ return () => {
1622
+ document.removeEventListener("mousedown", handleClickOutside);
1623
+ };
1624
+ }, []);
1625
+ const button = useMemo(() => /* @__PURE__ */ jsxs(UnstyledButton, {
1626
+ "aria-label": "Options Menu",
1627
+ className: cn(buttonVariants["secondary"], defaultStyling, {
1628
+ "md:pr-3.5 md:pl-5": title,
1629
+ "h-7 min-w-7": styleVariant === "small"
1630
+ }),
1631
+ disabled,
1632
+ onClick: handleToggle,
1633
+ children: [title && /* @__PURE__ */ jsx("span", {
1634
+ className: "hidden md:block",
1635
+ children: title
1636
+ }), /* @__PURE__ */ jsx(IconDotsVertical, {
1637
+ size: 20,
1638
+ stroke: 1,
1639
+ fill: "black"
1640
+ })]
1641
+ }), [
1642
+ title,
1643
+ styleVariant,
1644
+ disabled,
1645
+ handleToggle
1646
+ ]);
1647
+ return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs("div", {
1648
+ className: "relative",
1649
+ "data-component": "kebabMenu",
1650
+ "data-testid": "kebab-menu",
1651
+ ref: menuRef,
1652
+ "data-tooltip-id": title,
1653
+ "data-tooltip-content": title,
1654
+ children: [tooltip ? /* @__PURE__ */ jsx(Tooltip, {
1655
+ passedOpen: false,
1656
+ size: "sm",
1657
+ content: tooltip,
1658
+ children: button
1659
+ }) : button, isOpen && /* @__PURE__ */ jsx("div", {
1660
+ className: "absolute right-0 z-10 mt-2 w-auto min-w-[200px] rounded-md border-[0.0625rem] border-gray-200 bg-white p-1 shadow-md",
1661
+ children: content.map((c, index) => {
1662
+ const button$1 = /* @__PURE__ */ jsx(UnstyledButton, {
1663
+ onClick: () => handleItemClick(c.onClick),
1664
+ className: "w-full rounded-md px-4 py-2 text-left text-sm font-normal whitespace-nowrap hover:bg-gray-50",
1665
+ "aria-label": "Options Menu Item",
1666
+ disabled: c.disabled,
1667
+ children: c.title
1668
+ });
1669
+ return c.tooltip ? /* @__PURE__ */ jsx(Tooltip, {
1670
+ passedOpen: false,
1671
+ size: "sm",
1672
+ content: c.tooltip,
1673
+ children: button$1
1674
+ }, index) : /* @__PURE__ */ jsx(React.Fragment, { children: button$1 }, index);
1675
+ })
1676
+ })]
1677
+ }) });
1678
+ };
1679
+ KebabMenu.displayName = "KebabMenu";
1680
+
1494
1681
  //#endregion
1495
1682
  //#region src/components/label/index.tsx
1496
1683
  const Label = ({ children, className,...props }) => /* @__PURE__ */ jsx("label", {
@@ -2131,183 +2318,289 @@ const SearchInput = ({ placeholder, value, onChange, className, rightSection,...
2131
2318
  ...props
2132
2319
  });
2133
2320
 
2321
+ //#endregion
2322
+ //#region src/hooks/useDebouncedValue.ts
2323
+ function useDebouncedValue(value, delay = 200) {
2324
+ const [debouncedValue, setDebouncedValue] = useState(value);
2325
+ useEffect(() => {
2326
+ const handler = setTimeout(() => setDebouncedValue(value), delay);
2327
+ return () => clearTimeout(handler);
2328
+ }, [value, delay]);
2329
+ return debouncedValue;
2330
+ }
2331
+
2134
2332
  //#endregion
2135
2333
  //#region src/components/select/index.tsx
2136
- const LANGUAGE_FLAGS = [
2137
- {
2138
- value: "nl-NL",
2139
- altValue: "nl_NL",
2140
- label: "nl"
2141
- },
2142
- {
2143
- value: "nl-BE",
2144
- altValue: "nl_BE",
2145
- label: "be"
2146
- },
2147
- {
2148
- value: "en-GB",
2149
- altValue: "en_GB",
2150
- label: "gb"
2151
- },
2152
- {
2153
- value: "fr-FR",
2154
- altValue: "fr_FR",
2155
- label: "fr"
2156
- }
2157
- ];
2158
- const selectStyles = {
2159
- singleValue: (provided) => ({
2160
- ...provided,
2161
- fontSize: "14px"
2162
- }),
2163
- placeholder: (provided) => ({
2164
- ...provided,
2165
- color: "#838383",
2166
- fontSize: "14px",
2167
- textWrap: "nowrap"
2168
- }),
2169
- dropdownIndicator: (provided) => ({
2170
- ...provided,
2171
- color: "black"
2172
- }),
2173
- option: (base, { isFocused, isSelected }) => ({
2174
- ...base,
2175
- color: "black",
2176
- marginLeft: "4px",
2177
- marginRight: "4px",
2178
- backgroundColor: isSelected ? "#f8f8f8" : isFocused ? "#f8f8f8" : "transparent",
2179
- width: "calc(100% - 8px)",
2180
- cursor: "pointer"
2181
- }),
2182
- menuList: (provided) => ({
2183
- ...provided,
2184
- fontSize: "14px"
2185
- })
2186
- };
2187
- const selectTheme = (theme) => ({
2188
- ...theme,
2189
- borderRadius: 4,
2190
- colors: {
2191
- ...theme.colors,
2192
- primary25: "#f8f8f8",
2193
- primary: "#f8f8f8"
2194
- }
2195
- });
2196
- const Select = forwardRef(({ options, placeholder, defaultValue, label, id, icon, error, className, labelClassNames, showLangFlags = false, hideErrorText = false, isClearable = true, fullWidth = true, width, isDisabled,...props }, ref) => {
2197
- const DropdownIndicator = (props$1) => /* @__PURE__ */ jsx(components.DropdownIndicator, {
2198
- ...props$1,
2199
- children: props$1.hasValue && isClearable ? /* @__PURE__ */ jsx(IconX, {
2200
- "data-testid": "icon-x",
2201
- className: "cursor-pointer",
2202
- size: 16,
2203
- color: "black",
2204
- onClick: () => props$1.clearValue()
2205
- }) : /* @__PURE__ */ jsx(IconSelector, {
2206
- size: 16,
2207
- color: "black"
2208
- })
2209
- });
2210
- const GroupHeading = ({ children }) => /* @__PURE__ */ jsxs("div", {
2211
- className: "flex items-stretch px-4 py-2 font-normal text-[#838383] capitalize",
2212
- children: [/* @__PURE__ */ jsx("span", {
2213
- className: "flex-nowrap whitespace-nowrap",
2214
- children
2215
- }), /* @__PURE__ */ jsx("span", {
2216
- className: "ml-2 flex w-full flex-1 items-center justify-center",
2217
- children: /* @__PURE__ */ jsx("span", { className: "h-px w-full bg-[#838383]" })
2218
- })]
2219
- });
2220
- const LanguageControl = ({ children,...props$1 }) => {
2221
- const getSelectedFlag = () => {
2222
- const selectValue = props$1.selectProps.value;
2223
- const findFlag = (value) => LANGUAGE_FLAGS.find((e) => e.value === value || e.altValue === value)?.label || "";
2224
- if (typeof selectValue === "string") return findFlag(selectValue);
2225
- if (typeof selectValue === "object" && selectValue !== null && "value" in selectValue) return findFlag(selectValue.value);
2226
- return null;
2227
- };
2228
- const selectedFlag = getSelectedFlag();
2229
- return /* @__PURE__ */ jsxs(components.Control, {
2230
- ...props$1,
2231
- children: [selectedFlag && /* @__PURE__ */ jsx("div", {
2232
- className: "flex h-[39px] items-center border-r border-gray-200 p-3",
2233
- children: /* @__PURE__ */ jsx("img", {
2234
- src: `/images/countries/${selectedFlag.toUpperCase()}_flag.svg`,
2235
- alt: "",
2236
- width: 24,
2237
- height: 24
2238
- })
2239
- }), children]
2240
- });
2241
- };
2242
- const NoOptionsMessage = (props$1) => /* @__PURE__ */ jsx(components.NoOptionsMessage, {
2243
- ...props$1,
2244
- children: "noOptionsMessage"
2245
- });
2246
- const SingleValue = ({ children,...props$1 }) => /* @__PURE__ */ jsx(components.SingleValue, {
2247
- ...props$1,
2248
- children: /* @__PURE__ */ jsxs("span", {
2249
- className: "flex items-center",
2250
- children: [icon && icon, /* @__PURE__ */ jsx("span", {
2251
- className: "mx-2",
2252
- children
2253
- })]
2254
- })
2334
+ function Select({ id, options, placeholder, label, errorText, hideError = false, isClearable = false, disabled = false, multiSelect = false, searchable = false, value, defaultValue, onValueChange, className, searchPlaceholder, noResultsText,...props }) {
2335
+ const innerRef = useRef(null);
2336
+ const buttonRef = useRef(null);
2337
+ const optionRefs = useRef([]);
2338
+ const mergedRef = useMergeRefs(innerRef, props.ref);
2339
+ const [internalValue, setInternalValue] = useState(defaultValue);
2340
+ const [open, setOpen] = useState(false);
2341
+ const [searchTerm, setSearchTerm] = useState("");
2342
+ const [focusedIndex, setFocusedIndex] = useState(-1);
2343
+ const debouncedSearch = useDebouncedValue(searchTerm);
2344
+ const isControlled = value !== undefined;
2345
+ const currentValue = isControlled ? value : internalValue;
2346
+ const selectedLabels = useMemo(() => {
2347
+ if (Array.isArray(currentValue)) {
2348
+ return options.filter((o) => currentValue.includes(o.value)).map((o) => o.label).join(", ");
2349
+ }
2350
+ return options.find((o) => o.value === currentValue)?.label;
2351
+ }, [currentValue, options]);
2352
+ const { refs, floatingStyles, context } = useFloating({
2353
+ open,
2354
+ onOpenChange: setOpen,
2355
+ middleware: [
2356
+ offset(4),
2357
+ flip(),
2358
+ shift()
2359
+ ],
2360
+ whileElementsMounted: autoUpdate,
2361
+ placement: "bottom-start"
2255
2362
  });
2363
+ const click = useClick(context);
2364
+ const dismiss = useDismiss(context);
2365
+ const role = useRole(context, { role: "combobox" });
2366
+ const { getReferenceProps, getFloatingProps } = useInteractions([
2367
+ click,
2368
+ dismiss,
2369
+ role
2370
+ ]);
2371
+ const handleSelect = useCallback((val) => {
2372
+ if (multiSelect) {
2373
+ const current = Array.isArray(currentValue) ? currentValue : [];
2374
+ const newValues = current.includes(val) ? current.filter((v) => v !== val) : [...current, val];
2375
+ if (!isControlled) setInternalValue(newValues);
2376
+ onValueChange?.(newValues);
2377
+ } else {
2378
+ if (!isControlled) setInternalValue(val);
2379
+ onValueChange?.(val);
2380
+ setOpen(false);
2381
+ buttonRef.current?.focus();
2382
+ }
2383
+ }, [
2384
+ multiSelect,
2385
+ currentValue,
2386
+ isControlled,
2387
+ onValueChange
2388
+ ]);
2389
+ const handleClear = useCallback((e) => {
2390
+ e.preventDefault();
2391
+ e.stopPropagation();
2392
+ if (!isControlled) setInternalValue(undefined);
2393
+ onValueChange?.(undefined);
2394
+ setSearchTerm("");
2395
+ }, [isControlled, onValueChange]);
2396
+ const showPlaceholder = !currentValue || Array.isArray(currentValue) && currentValue.length === 0;
2397
+ const filteredOptions = useMemo(() => {
2398
+ if (!debouncedSearch.trim()) return options;
2399
+ return options.filter((opt) => opt.label.toLowerCase().includes(debouncedSearch.toLowerCase()));
2400
+ }, [options, debouncedSearch]);
2401
+ const handleKeyDown = useCallback((event) => {
2402
+ if (disabled) return;
2403
+ if (!open) {
2404
+ if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
2405
+ event.preventDefault();
2406
+ setOpen(true);
2407
+ setTimeout(() => {
2408
+ setFocusedIndex(0);
2409
+ optionRefs.current[0]?.focus();
2410
+ }, 0);
2411
+ }
2412
+ return;
2413
+ }
2414
+ switch (event.key) {
2415
+ case "Escape":
2416
+ event.preventDefault();
2417
+ setOpen(false);
2418
+ setFocusedIndex(-1);
2419
+ buttonRef.current?.focus();
2420
+ break;
2421
+ case "ArrowDown":
2422
+ event.preventDefault();
2423
+ setFocusedIndex((prev) => {
2424
+ const next = prev < filteredOptions.length - 1 ? prev + 1 : 0;
2425
+ optionRefs.current[next]?.focus();
2426
+ return next;
2427
+ });
2428
+ break;
2429
+ case "ArrowUp":
2430
+ event.preventDefault();
2431
+ setFocusedIndex((prev) => {
2432
+ const next = prev > 0 ? prev - 1 : filteredOptions.length - 1;
2433
+ optionRefs.current[next]?.focus();
2434
+ return next;
2435
+ });
2436
+ break;
2437
+ case "Home":
2438
+ event.preventDefault();
2439
+ setFocusedIndex(0);
2440
+ optionRefs.current[0]?.focus();
2441
+ break;
2442
+ case "End":
2443
+ event.preventDefault();
2444
+ setFocusedIndex(filteredOptions.length - 1);
2445
+ optionRefs.current[filteredOptions.length - 1]?.focus();
2446
+ break;
2447
+ case "Enter":
2448
+ case " ":
2449
+ event.preventDefault();
2450
+ if (focusedIndex >= 0 && filteredOptions[focusedIndex]) {
2451
+ handleSelect(filteredOptions[focusedIndex].value);
2452
+ }
2453
+ break;
2454
+ }
2455
+ }, [
2456
+ open,
2457
+ filteredOptions,
2458
+ focusedIndex,
2459
+ handleSelect,
2460
+ disabled
2461
+ ]);
2462
+ useEffect(() => {
2463
+ if (!open) return;
2464
+ const listener = (e) => handleKeyDown(e);
2465
+ document.addEventListener("keydown", listener);
2466
+ return () => document.removeEventListener("keydown", listener);
2467
+ }, [open, handleKeyDown]);
2468
+ useEffect(() => {
2469
+ if (!open) setSearchTerm("");
2470
+ }, [open]);
2256
2471
  return /* @__PURE__ */ jsxs("div", {
2472
+ ref: mergedRef,
2473
+ ...props,
2257
2474
  "data-component": "Select",
2258
- "data-testid": "select-container",
2259
- ref,
2260
- className: clsx("m-0 grid gap-2 p-0", width ? width : fullWidth && "w-full", className),
2475
+ className: cn("grid gap-2 w-full", className),
2476
+ role: "group",
2477
+ "aria-labelledby": `${id}-label`,
2261
2478
  children: [
2262
- label && /* @__PURE__ */ jsx(Label, {
2263
- className: cn("leading-4", labelClassNames),
2264
- children: label
2479
+ label && /* @__PURE__ */ jsxs("div", {
2480
+ className: "leading-4",
2481
+ children: [/* @__PURE__ */ jsx(Label, {
2482
+ htmlFor: id,
2483
+ children: label
2484
+ }), /* @__PURE__ */ jsx("span", {
2485
+ id: `${id}-label`,
2486
+ className: "sr-only",
2487
+ children: label
2488
+ })]
2265
2489
  }),
2266
- /* @__PURE__ */ jsx(ReactSelect, {
2267
- "data-component": "select",
2268
- "data-testid": "select-input",
2269
- options,
2270
- menuPlacement: "auto",
2271
- isDisabled,
2272
- defaultValue,
2273
- placeholder,
2274
- isClearable: false,
2275
- menuPortalTarget: document?.body,
2276
- styles: {
2277
- ...selectStyles,
2278
- control: (base, state) => ({
2279
- ...base,
2280
- "&:hover": { borderColor: "#A8A8A8" },
2281
- height: "40px",
2282
- width: "100%",
2283
- backgroundColor: "#fbfbfb",
2284
- borderColor: error ? "red" : state.isFocused ? "#10d1bb" : "#cccccc",
2285
- cursor: "pointer"
2286
- }),
2287
- menuPortal: (base) => ({
2288
- ...base,
2289
- zIndex: 99999
2290
- })
2490
+ /* @__PURE__ */ jsxs("button", {
2491
+ id,
2492
+ type: "button",
2493
+ ref: (node) => {
2494
+ refs.setReference(node);
2495
+ buttonRef.current = node;
2291
2496
  },
2292
- theme: selectTheme,
2293
- components: {
2294
- IndicatorSeparator: () => null,
2295
- DropdownIndicator,
2296
- GroupHeading,
2297
- Control: showLangFlags ? LanguageControl : components.Control,
2298
- SingleValue,
2299
- NoOptionsMessage
2300
- },
2301
- ...props
2302
- }, id),
2303
- !hideErrorText && error && /* @__PURE__ */ jsx("small", {
2304
- className: "text-xs font-normal text-red-500",
2497
+ ...getReferenceProps(),
2498
+ disabled,
2499
+ className: cn("flex h-10 w-full items-center justify-between rounded-md border px-3 text-sm transition-colors bg-gray-20", "border-gray-200 hover:border-gray-300 focus:border-gray-300 outline-none", !hideError && errorText && "border-red-500 hover:border-red-500 focus:border-red-500", disabled && "opacity-50 cursor-not-allowed"),
2500
+ "aria-haspopup": "listbox",
2501
+ "aria-expanded": open,
2502
+ "aria-disabled": disabled,
2503
+ "aria-labelledby": `${id}-label`,
2504
+ "aria-controls": `${id}-listbox`,
2505
+ children: [/* @__PURE__ */ jsx("div", {
2506
+ className: "flex items-center gap-2 truncate text-black",
2507
+ children: showPlaceholder ? /* @__PURE__ */ jsx("span", {
2508
+ className: "text-gray-200",
2509
+ "aria-hidden": "true",
2510
+ children: placeholder
2511
+ }) : /* @__PURE__ */ jsx("span", {
2512
+ className: "truncate",
2513
+ children: selectedLabels
2514
+ })
2515
+ }), isClearable && !showPlaceholder ? /* @__PURE__ */ jsx(IconX, {
2516
+ size: 16,
2517
+ color: "black",
2518
+ className: "cursor-pointer",
2519
+ "data-testid": "clear-button",
2520
+ onPointerDown: handleClear,
2521
+ role: "button",
2522
+ "aria-label": "Clear selection"
2523
+ }) : /* @__PURE__ */ jsx(IconSelector, {
2524
+ size: 16,
2525
+ color: "black",
2526
+ "aria-hidden": "true"
2527
+ })]
2528
+ }),
2529
+ open && /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(FloatingFocusManager, {
2530
+ context,
2531
+ modal: false,
2532
+ children: /* @__PURE__ */ jsx("div", {
2533
+ ref: refs.setFloating,
2534
+ style: {
2535
+ ...floatingStyles,
2536
+ width: refs.reference.current?.offsetWidth ?? "auto"
2537
+ },
2538
+ ...getFloatingProps(),
2539
+ id: `${id}-listbox`,
2540
+ role: "listbox",
2541
+ "aria-labelledby": `${id}-label`,
2542
+ className: cn("z-[99999] mt-2 rounded-md border border-gray-200 bg-white shadow-md", "overflow-hidden animate-in fade-in"),
2543
+ children: /* @__PURE__ */ jsxs("div", {
2544
+ className: "p-1 text-sm max-h-[250px] overflow-auto",
2545
+ children: [searchable && /* @__PURE__ */ jsxs("div", {
2546
+ className: "flex items-center gap-2 px-2 py-1 border-b border-gray-100 sticky top-0 bg-white",
2547
+ role: "search",
2548
+ children: [/* @__PURE__ */ jsx(IconSearch, {
2549
+ size: 14,
2550
+ className: "text-gray-400",
2551
+ "aria-hidden": "true"
2552
+ }), /* @__PURE__ */ jsx("input", {
2553
+ type: "text",
2554
+ autoFocus: true,
2555
+ value: searchTerm,
2556
+ onChange: (e) => setSearchTerm(e.target.value),
2557
+ placeholder: searchPlaceholder,
2558
+ className: "w-full text-sm outline-none bg-transparent placeholder-gray-300",
2559
+ "aria-label": "Search options"
2560
+ })]
2561
+ }), /* @__PURE__ */ jsx("div", {
2562
+ className: "mt-1 pr-2",
2563
+ children: filteredOptions.length ? filteredOptions.map((opt, index) => {
2564
+ const isSelected = Array.isArray(currentValue) ? currentValue.includes(opt.value) : currentValue === opt.value;
2565
+ return /* @__PURE__ */ jsxs("button", {
2566
+ ref: (el) => optionRefs.current[index] = el,
2567
+ type: "button",
2568
+ onClick: () => handleSelect(opt.value),
2569
+ role: "option",
2570
+ "aria-selected": isSelected,
2571
+ tabIndex: -1,
2572
+ className: cn("relative flex w-full items-center gap-2 rounded px-3 py-2 text-sm text-black select-none", "hover:bg-gray-50 mx-1 my-[2px]", isSelected && "bg-gray-50", focusedIndex === index && "bg-gray-50 ring-1 ring-primary"),
2573
+ children: [multiSelect && /* @__PURE__ */ jsx("span", {
2574
+ className: cn("flex h-4 w-4 items-center justify-center rounded-sm border", isSelected ? "border-light-blue bg-light-blue" : "border-gray-400 bg-white"),
2575
+ "aria-hidden": "true",
2576
+ children: isSelected && /* @__PURE__ */ jsx(IconCheck, {
2577
+ size: 12,
2578
+ color: "white",
2579
+ stroke: 2,
2580
+ className: "pointer-events-none"
2581
+ })
2582
+ }), /* @__PURE__ */ jsx("span", {
2583
+ className: "flex-1 text-left",
2584
+ children: opt.label
2585
+ })]
2586
+ }, opt.value);
2587
+ }) : /* @__PURE__ */ jsx("div", {
2588
+ className: "px-3 py-2 text-gray-400",
2589
+ role: "status",
2590
+ children: noResultsText
2591
+ })
2592
+ })]
2593
+ })
2594
+ })
2595
+ }) }),
2596
+ !hideError && errorText && /* @__PURE__ */ jsx("span", {
2597
+ className: "text-xs text-red-500",
2305
2598
  role: "alert",
2306
- children: error
2599
+ children: errorText
2307
2600
  })
2308
2601
  ]
2309
2602
  });
2310
- });
2603
+ }
2311
2604
  Select.displayName = "Select";
2312
2605
 
2313
2606
  //#endregion
@@ -2712,97 +3005,6 @@ const Toggle = ({ onClick, value, disabled = false }) => {
2712
3005
  });
2713
3006
  };
2714
3007
 
2715
- //#endregion
2716
- //#region src/components/tooltip/index.tsx
2717
- const sizeClasses = {
2718
- xs: "max-w-xs",
2719
- sm: "max-w-sm",
2720
- md: "max-w-md",
2721
- lg: "max-w-lg"
2722
- };
2723
- const Tooltip = ({ content, children, passedOpen = false, size = "md", variant = "default" }) => {
2724
- const [isOpen, setIsOpen] = useState(passedOpen);
2725
- const arrowRef = useRef(null);
2726
- const { refs, floatingStyles, context } = useFloating({
2727
- open: isOpen,
2728
- onOpenChange: setIsOpen,
2729
- placement: "top",
2730
- middleware: [
2731
- variant === "default" ? offset(20) : offset(25),
2732
- flip(),
2733
- shift(),
2734
- arrow({ element: arrowRef })
2735
- ],
2736
- whileElementsMounted: autoUpdate
2737
- });
2738
- const hover = useHover(context, { move: false });
2739
- const focus = useFocus(context);
2740
- const dismiss = useDismiss(context);
2741
- const role = useRole(context, { role: "tooltip" });
2742
- const { getReferenceProps, getFloatingProps } = useInteractions([
2743
- hover,
2744
- focus,
2745
- dismiss,
2746
- role
2747
- ]);
2748
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [isValidElement(children) && cloneElement(children, getReferenceProps({
2749
- ref: refs.setReference,
2750
- ...children.props,
2751
- ...getReferenceProps()
2752
- })), isOpen && /* @__PURE__ */ jsx("div", {
2753
- ref: refs.setFloating,
2754
- style: floatingStyles,
2755
- ...getFloatingProps(),
2756
- className: "z-70 drop-shadow-xl",
2757
- "data-testid": "tooltip",
2758
- "data-component": "tooltip",
2759
- children: variant === "default" ? /* @__PURE__ */ jsxs("div", {
2760
- "data-testid": "tooltip-container",
2761
- className: "w-full rounded bg-gray-800 pt-[3px] text-white",
2762
- children: [/* @__PURE__ */ jsx("div", {
2763
- "data-testid": "tooltip-content",
2764
- className: `${sizeClasses[size]} px-2 py-1 text-sm font-normal`,
2765
- children: content
2766
- }), /* @__PURE__ */ jsx(FloatingArrow, {
2767
- ref: arrowRef,
2768
- context,
2769
- width: 10,
2770
- height: 6,
2771
- tipRadius: 1,
2772
- "data-testid": "tooltip-arrow",
2773
- className: "fill-gray-800 drop-shadow-xl"
2774
- })]
2775
- }) : /* @__PURE__ */ jsxs("div", {
2776
- "data-testid": "tooltip-container",
2777
- className: "bg-linear-gradient-x pt-[3px]",
2778
- children: [/* @__PURE__ */ jsx("div", {
2779
- "data-testid": "tooltip-content",
2780
- className: `${sizeClasses[size]} overflow-hidden bg-white p-5 px-2 py-1 text-start text-sm font-normal`,
2781
- children: /* @__PURE__ */ jsx("p", { children: content })
2782
- }), size === "md" ? /* @__PURE__ */ jsx(FloatingArrow, {
2783
- ref: arrowRef,
2784
- context,
2785
- width: 25,
2786
- height: 17,
2787
- tipRadius: 1,
2788
- fill: "white",
2789
- className: "drop-shadow-xl",
2790
- "data-testid": "tooltip-arrow"
2791
- }) : /* @__PURE__ */ jsx(FloatingArrow, {
2792
- ref: arrowRef,
2793
- context,
2794
- width: 10,
2795
- height: 6,
2796
- tipRadius: 1,
2797
- fill: "white",
2798
- className: "drop-shadow-xl",
2799
- "data-testid": "tooltip-arrow"
2800
- })]
2801
- })
2802
- })] });
2803
- };
2804
- Tooltip.displayName = "Tooltip";
2805
-
2806
3008
  //#endregion
2807
3009
  //#region src/components/truncatedText/index.tsx
2808
3010
  const TruncatedText = ({ text, limit = 20 }) => {
@@ -3151,5 +3353,5 @@ const setCSSVariable = (variable, value) => {
3151
3353
  };
3152
3354
 
3153
3355
  //#endregion
3154
- export { AccordionItem, AccordionWrapper, ActionIcon, Alert, AppleAppButtonIcon, AutoCompleteInput, Avatar, AvatarIndicator, Badge, BigBadge, BreadCrumb, Button, CSS_VARIABLE_KEYS, Checkbox, DatePickerInput, Divider, FavouriteButton, Filters, GoogleAppButtonIcon, HR, HamburgerMenuButton, Island, Label, Loader, LogoBlack, Modal, NavButtons, NumberField, NumberedStepper, PageUnavailable, PasswordInput, Popover, ProfileMenu, ProgressBar, RadioButton, Rating, RegionSelector, Reviews, ScrollToTop, SearchInput, Select, SettingsCard, Skeleton, SkillPill, Stepper, StickyMobileButtonWrapper, Table, TableCell, TableHeader, TableHeaderItem, TableHeaderRow, TableRow, TabsBadge, TabsWrapper, TextInput, Textarea, ThemeIcon, TimeInput, Toggle, Tooltip, TruncatedText, UnorderedList, UnorderedListItem, UnstyledButton, WysiwygEditor, buttonVariants, getCSSVariable, setCSSVariable };
3356
+ export { AccordionItem, AccordionWrapper, ActionIcon, Alert, AppleAppButtonIcon, AutoCompleteInput, Avatar, AvatarIndicator, Badge, BigBadge, BreadCrumb, Button, CSS_VARIABLE_KEYS, Checkbox, DatePickerInput, Divider, FavouriteButton, Filters, GoogleAppButtonIcon, HR, HamburgerMenuButton, Island, KebabMenu, Label, Loader, LogoBlack, Modal, NavButtons, NumberField, NumberedStepper, PageUnavailable, PasswordInput, Popover, ProfileMenu, ProgressBar, RadioButton, Rating, RegionSelector, Reviews, ScrollToTop, SearchInput, Select, SettingsCard, Skeleton, SkillPill, Stepper, StickyMobileButtonWrapper, Table, TableCell, TableHeader, TableHeaderItem, TableHeaderRow, TableRow, TabsBadge, TabsWrapper, TextInput, Textarea, ThemeIcon, TimeInput, Toggle, Tooltip, TruncatedText, UnorderedList, UnorderedListItem, UnstyledButton, WysiwygEditor, buttonVariants, getCSSVariable, setCSSVariable };
3155
3357
  //# sourceMappingURL=index.js.map