uiplex 1.0.0 → 1.0.1

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.d.ts CHANGED
@@ -8,6 +8,7 @@ import './Modal/Modal.css';
8
8
  import './FormControl/FormControl.css';
9
9
  import './Input/Input.css';
10
10
  import './Textarea/Textarea.css';
11
+ import './Select/Select.css';
11
12
  import './Link/Link.css';
12
13
  import './Grid/Grid.css';
13
14
  import './IconButton/IconButton.css';
@@ -36,6 +37,8 @@ export { Input } from './Input';
36
37
  export type { InputProps } from './Input';
37
38
  export { Textarea } from './Textarea';
38
39
  export type { TextareaProps } from './Textarea';
40
+ export { Select } from './Select';
41
+ export type { SelectProps, SelectOption } from './Select';
39
42
  export { Grid } from './Grid';
40
43
  export type { GridProps } from './Grid';
41
44
  export { Link } from './Link';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import './index.css';
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import React, { useRef, useEffect, createContext, useContext, useState, useCallback, useMemo } from 'react';
4
+ import { createPortal } from 'react-dom';
4
5
 
5
6
  const Button = ({ children, variant = "primary", size = "md", colorScheme = "", disabled = false, loading = false, leftIcon, rightIcon, onClick, className = "", style, ...props }) => {
6
7
  const buttonClasses = [
@@ -387,6 +388,225 @@ const Textarea = ({ size = "md", variant = "outline", isInvalid, isDisabled, isR
387
388
  return (jsx("textarea", { id: textareaId, className: textareaClasses, disabled: disabled, readOnly: isReadOnly, "aria-invalid": invalid, "aria-describedby": invalid && formControl.id ? `${formControl.id}-error` : undefined, style: style, ...props }));
388
389
  };
389
390
 
391
+ const Select = ({ size = "md", variant = "outline", isInvalid, isDisabled, isReadOnly, options = [], placeholder = "Select...", value: controlledValue, defaultValue, onChange, mode = "single", searchable = false, allowClear = false, width, className = "", style, id, }) => {
392
+ const formControl = useFormControlContext();
393
+ const invalid = isInvalid ?? formControl.isInvalid ?? false;
394
+ const disabled = isDisabled ?? formControl.isDisabled ?? false;
395
+ const selectId = id || formControl.id;
396
+ const [isOpen, setIsOpen] = useState(false);
397
+ const [searchTerm, setSearchTerm] = useState("");
398
+ const [internalValue, setInternalValue] = useState(defaultValue || (mode === "multiple" ? [] : ""));
399
+ const [dropdownPosition, setDropdownPosition] = useState(null);
400
+ const isControlled = controlledValue !== undefined;
401
+ const value = isControlled ? controlledValue : internalValue;
402
+ const selectRef = useRef(null);
403
+ const dropdownRef = useRef(null);
404
+ const inputRef = useRef(null);
405
+ const triggerRef = useRef(null);
406
+ const clickFromTriggerRef = useRef(false);
407
+ // Close dropdown on outside click
408
+ useEffect(() => {
409
+ if (!isOpen)
410
+ return;
411
+ const handleClickOutside = (event) => {
412
+ const target = event.target;
413
+ // If click originated from trigger, ignore it
414
+ if (clickFromTriggerRef.current) {
415
+ return;
416
+ }
417
+ // Check if refs are available
418
+ if (!selectRef.current || !dropdownRef.current) {
419
+ return;
420
+ }
421
+ // Check if click is inside select trigger or dropdown
422
+ const clickedInsideSelect = selectRef.current.contains(target);
423
+ const clickedInsideDropdown = dropdownRef.current.contains(target);
424
+ // Close if clicked outside both
425
+ if (!clickedInsideSelect && !clickedInsideDropdown) {
426
+ setIsOpen(false);
427
+ setSearchTerm("");
428
+ setDropdownPosition(null);
429
+ }
430
+ };
431
+ // Use mousedown in capture phase for more reliable detection
432
+ // This prevents the double-click issue
433
+ document.addEventListener("mousedown", handleClickOutside, true);
434
+ document.addEventListener("touchstart", handleClickOutside, true);
435
+ return () => {
436
+ document.removeEventListener("mousedown", handleClickOutside, true);
437
+ document.removeEventListener("touchstart", handleClickOutside, true);
438
+ };
439
+ }, [isOpen]);
440
+ // Calculate and update dropdown position
441
+ const updateDropdownPosition = useCallback(() => {
442
+ if (!triggerRef.current)
443
+ return;
444
+ const rect = triggerRef.current.getBoundingClientRect();
445
+ setDropdownPosition({
446
+ top: rect.bottom + 4,
447
+ left: rect.left,
448
+ width: rect.width,
449
+ });
450
+ }, []);
451
+ // Calculate dropdown position when it opens
452
+ useEffect(() => {
453
+ if (isOpen) {
454
+ updateDropdownPosition();
455
+ }
456
+ else {
457
+ setDropdownPosition(null);
458
+ }
459
+ }, [isOpen, updateDropdownPosition]);
460
+ // Update position on scroll/resize
461
+ useEffect(() => {
462
+ if (!isOpen)
463
+ return;
464
+ // Update position immediately
465
+ updateDropdownPosition();
466
+ // Listen to scroll events on all scrollable containers
467
+ const handleScroll = () => {
468
+ updateDropdownPosition();
469
+ };
470
+ const handleResize = () => {
471
+ updateDropdownPosition();
472
+ };
473
+ // Add listeners to window and all scrollable parents
474
+ window.addEventListener("scroll", handleScroll, true);
475
+ window.addEventListener("resize", handleResize);
476
+ // Also listen to scroll on the document
477
+ document.addEventListener("scroll", handleScroll, true);
478
+ return () => {
479
+ window.removeEventListener("scroll", handleScroll, true);
480
+ window.removeEventListener("resize", handleResize);
481
+ document.removeEventListener("scroll", handleScroll, true);
482
+ };
483
+ }, [isOpen, updateDropdownPosition]);
484
+ // Focus search input when dropdown opens
485
+ useEffect(() => {
486
+ if (isOpen && searchable && inputRef.current) {
487
+ inputRef.current.focus();
488
+ }
489
+ }, [isOpen, searchable]);
490
+ // Filter options based on search term
491
+ const filteredOptions = searchable
492
+ ? options.filter((option) => option.label.toLowerCase().includes(searchTerm.toLowerCase()))
493
+ : options;
494
+ // Get selected option(s)
495
+ const getSelectedOptions = useCallback(() => {
496
+ if (mode === "multiple") {
497
+ const values = Array.isArray(value) ? value : [];
498
+ return options.filter((opt) => values.includes(opt.value));
499
+ }
500
+ else {
501
+ return options.find((opt) => opt.value === value);
502
+ }
503
+ }, [value, options, mode]);
504
+ const selectedOptions = getSelectedOptions();
505
+ const displayValue = mode === "multiple"
506
+ ? Array.isArray(selectedOptions) && selectedOptions.length > 0
507
+ ? `${selectedOptions.length} selected`
508
+ : placeholder
509
+ : selectedOptions && !Array.isArray(selectedOptions)
510
+ ? selectedOptions.label
511
+ : placeholder;
512
+ const handleToggle = (e) => {
513
+ if (disabled || isReadOnly)
514
+ return;
515
+ e.stopPropagation();
516
+ // Set flag to prevent outside click handler from firing
517
+ clickFromTriggerRef.current = true;
518
+ setIsOpen((prev) => {
519
+ const newIsOpen = !prev;
520
+ if (newIsOpen) {
521
+ setSearchTerm("");
522
+ }
523
+ // Reset flag after state update
524
+ setTimeout(() => {
525
+ clickFromTriggerRef.current = false;
526
+ }, 100);
527
+ return newIsOpen;
528
+ });
529
+ };
530
+ const handleSelect = (optionValue) => {
531
+ if (mode === "multiple") {
532
+ const currentValues = Array.isArray(value) ? value : [];
533
+ const newValues = currentValues.includes(optionValue)
534
+ ? currentValues.filter((v) => v !== optionValue)
535
+ : [...currentValues, optionValue];
536
+ if (!isControlled) {
537
+ setInternalValue(newValues);
538
+ }
539
+ onChange?.(newValues);
540
+ }
541
+ else {
542
+ if (!isControlled) {
543
+ setInternalValue(optionValue);
544
+ }
545
+ onChange?.(optionValue);
546
+ setIsOpen(false);
547
+ }
548
+ };
549
+ const handleClear = (e) => {
550
+ e.stopPropagation();
551
+ const newValue = mode === "multiple" ? [] : "";
552
+ if (!isControlled) {
553
+ setInternalValue(newValue);
554
+ }
555
+ onChange?.(newValue);
556
+ };
557
+ const isSelected = (optionValue) => {
558
+ if (mode === "multiple") {
559
+ return Array.isArray(value) && value.includes(optionValue);
560
+ }
561
+ return value === optionValue;
562
+ };
563
+ const hasValue = mode === "multiple"
564
+ ? Array.isArray(value) && value.length > 0
565
+ : value !== "" && value !== undefined && value !== null;
566
+ const selectClasses = [
567
+ "ui-select",
568
+ `ui-select--${size}`,
569
+ `ui-select--${variant}`,
570
+ invalid && "ui-select--invalid",
571
+ disabled && "ui-select--disabled",
572
+ isReadOnly && "ui-select--readonly",
573
+ isOpen && "ui-select--open",
574
+ className,
575
+ ]
576
+ .filter(Boolean)
577
+ .join(" ");
578
+ const wrapperStyle = {
579
+ ...style,
580
+ ...(width && {
581
+ width: typeof width === "number" ? `${width}px` : width,
582
+ }),
583
+ };
584
+ return (jsxs("div", { ref: selectRef, className: "ui-select-wrapper", style: wrapperStyle, children: [jsxs("div", { ref: triggerRef, id: selectId, className: selectClasses, onClick: handleToggle, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-invalid": invalid, "aria-describedby": invalid && formControl.id ? `${formControl.id}-error` : undefined, role: "combobox", tabIndex: disabled || isReadOnly ? -1 : 0, children: [jsx("div", { className: "ui-select__value", children: mode === "multiple" && hasValue && Array.isArray(selectedOptions) && selectedOptions.length > 0 ? (jsxs("div", { className: "ui-select__tags", children: [selectedOptions.slice(0, 2).map((option) => (jsxs("span", { className: "ui-select__tag", children: [option.label, jsx("button", { type: "button", className: "ui-select__tag-close", onClick: (e) => {
585
+ e.stopPropagation();
586
+ handleSelect(option.value);
587
+ }, "aria-label": `Remove ${option.label}`, children: "\u00D7" })] }, option.value))), selectedOptions.length > 2 && (jsxs("span", { className: "ui-select__tag-more", children: ["+", selectedOptions.length - 2] }))] })) : (jsx("span", { className: `ui-select__text ${!hasValue ? "ui-select__text--placeholder" : ""}`, children: displayValue })) }), jsxs("div", { className: "ui-select__actions", children: [allowClear && hasValue && !disabled && !isReadOnly && (jsx("button", { type: "button", className: "ui-select__clear", onClick: handleClear, "aria-label": "Clear selection", children: "\u00D7" })), jsx("span", { className: "ui-select__arrow", "aria-hidden": "true", children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M4 6L8 10L12 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), isOpen &&
588
+ dropdownPosition &&
589
+ typeof window !== "undefined" &&
590
+ createPortal(jsxs("div", { ref: dropdownRef, className: "ui-select-dropdown", role: "listbox", style: {
591
+ position: "fixed",
592
+ top: `${dropdownPosition.top}px`,
593
+ left: `${dropdownPosition.left}px`,
594
+ width: `${dropdownPosition.width}px`,
595
+ }, onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), children: [searchable && (jsx("div", { className: "ui-select-dropdown__search", children: jsx("input", { ref: inputRef, type: "text", className: "ui-select-dropdown__search-input", placeholder: "Search...", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), onClick: (e) => e.stopPropagation(), onKeyDown: (e) => {
596
+ if (e.key === "Escape") {
597
+ setIsOpen(false);
598
+ }
599
+ } }) })), jsx("div", { className: "ui-select-dropdown__options", children: filteredOptions.length === 0 ? (jsx("div", { className: "ui-select-dropdown__empty", children: "No options found" })) : (filteredOptions.map((option) => {
600
+ const selected = isSelected(option.value);
601
+ return (jsxs("div", { className: `ui-select-dropdown__option ${selected ? "ui-select-dropdown__option--selected" : ""} ${option.disabled ? "ui-select-dropdown__option--disabled" : ""}`, onClick: (e) => {
602
+ e.stopPropagation();
603
+ if (!option.disabled) {
604
+ handleSelect(option.value);
605
+ }
606
+ }, role: "option", "aria-selected": selected, children: [mode === "multiple" && (jsx("span", { className: "ui-select-dropdown__checkbox", children: selected ? "✓" : "" })), jsx("span", { className: "ui-select-dropdown__option-label", children: option.label })] }, option.value));
607
+ })) })] }), document.body)] }));
608
+ };
609
+
390
610
  const normalizeValue = (value) => {
391
611
  if (value === undefined)
392
612
  return undefined;
@@ -518,7 +738,7 @@ const useOutsideClick = ({ handler, refs, enabled = true, }) => {
518
738
  }, [handler, refs, enabled]);
519
739
  };
520
740
 
521
- const Tooltip = ({ children, label, placement = "top", isOpen: controlledIsOpen, defaultIsOpen = false, closeOnClick = false, className = "", style, }) => {
741
+ const Tooltip = ({ children, label, placement = "top", isOpen: controlledIsOpen, defaultIsOpen = false, closeOnClick = false, width, className = "", style, }) => {
522
742
  const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen);
523
743
  const tooltipRef = useRef(null);
524
744
  const triggerRef = useRef(null);
@@ -554,7 +774,11 @@ const Tooltip = ({ children, label, placement = "top", isOpen: controlledIsOpen,
554
774
  onMouseLeave: handleMouseLeave,
555
775
  onClick: handleClick,
556
776
  });
557
- return (jsxs("div", { className: `ui-tooltip-wrapper ${className}`, style: style, children: [clonedChild, isOpen && (jsx("div", { ref: tooltipRef, className: `ui-tooltip ui-tooltip--${placement}`, role: "tooltip", children: label }))] }));
777
+ return (jsxs("div", { className: `ui-tooltip-wrapper ${className}`, style: style, children: [clonedChild, isOpen && (jsx("div", { ref: tooltipRef, className: `ui-tooltip ui-tooltip--${placement} ${width ? "ui-tooltip--wrappable" : ""}`, role: "tooltip", style: width
778
+ ? {
779
+ width: typeof width === "number" ? `${width}px` : width,
780
+ }
781
+ : undefined, children: label }))] }));
558
782
  };
559
783
 
560
784
  const PopoverContent = ({ children, className = "", }) => {
@@ -869,7 +1093,7 @@ const useTheme = () => {
869
1093
  }
870
1094
  return context;
871
1095
  };
872
- const ThemeProvider = ({ children, defaultTheme = "system", storageKey = "uilab-theme" }) => {
1096
+ const ThemeProvider = ({ children, defaultTheme = "system", storageKey = "uiplex-theme" }) => {
873
1097
  const [theme, setTheme] = useState(defaultTheme);
874
1098
  const [resolvedTheme, setResolvedTheme] = useState("light");
875
1099
  // Get system preference
@@ -1053,4 +1277,4 @@ const ThemeScript = ({ storageKey = "uiplex-theme", defaultTheme = "system" }) =
1053
1277
  } }));
1054
1278
  };
1055
1279
 
1056
- export { Box, Button, CircularProgress, CircularProgressLabel, Flex, FormControl, FormErrorMessage, FormLabel, Grid, IconButton, Input, Link, Loader, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Popover, PopoverBody, PopoverCloseButton, PopoverContent, PopoverFooter, PopoverHeader, Radio, RadioGroup, Text, Textarea, ThemeProvider, ThemeScript, ThemeToggle, ToastStatic as Toast, Toast as ToastComponent, ToastContainer, ToastContainerGlobal, Tooltip, useDisclosure, useOutsideClick, useTheme };
1280
+ export { Box, Button, CircularProgress, CircularProgressLabel, Flex, FormControl, FormErrorMessage, FormLabel, Grid, IconButton, Input, Link, Loader, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Popover, PopoverBody, PopoverCloseButton, PopoverContent, PopoverFooter, PopoverHeader, Radio, RadioGroup, Select, Text, Textarea, ThemeProvider, ThemeScript, ThemeToggle, ToastStatic as Toast, Toast as ToastComponent, ToastContainer, ToastContainerGlobal, Tooltip, useDisclosure, useOutsideClick, useTheme };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uiplex",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A modern React component library with TypeScript support, featuring Button, Loader, Radio components and a comprehensive theme system",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -44,13 +44,13 @@
44
44
  "license": "MIT",
45
45
  "repository": {
46
46
  "type": "git",
47
- "url": "https://github.com/uilab/Frontend-UI-Library.git",
47
+ "url": "https://github.com/ankit-kaushal/Frontend-UI-Library",
48
48
  "directory": "packages/ui"
49
49
  },
50
50
  "bugs": {
51
- "url": "https://github.com/uilab/Frontend-UI-Library/issues"
51
+ "url": "https://github.com/ankit-kaushal/Frontend-UI-Library/issues"
52
52
  },
53
- "homepage": "https://github.com/uilab/Frontend-UI-Library#readme",
53
+ "homepage": "https://github.com/ankit-kaushal/Frontend-UI-Library#readme",
54
54
  "peerDependencies": {
55
55
  "react": "^18.0.0",
56
56
  "react-dom": "^18.0.0"