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/README.md +461 -4
- package/dist/Select/Select.d.ts +28 -0
- package/dist/Select/Select.d.ts.map +1 -0
- package/dist/Select/index.d.ts +3 -0
- package/dist/Select/index.d.ts.map +1 -0
- package/dist/Tooltip/Tooltip.d.ts +1 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/index.cjs +228 -3
- package/dist/index.css +404 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +228 -4
- package/package.json +4 -4
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,qBAAqB,CAAA;AAC5B,OAAO,mBAAmB,CAAA;AAC1B,OAAO,iBAAiB,CAAA;AACxB,OAAO,eAAe,CAAA;AACtB,OAAO,iBAAiB,CAAA;AACxB,OAAO,mBAAmB,CAAA;AAC1B,OAAO,+BAA+B,CAAA;AACtC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,yBAAyB,CAAA;AAChC,OAAO,iBAAiB,CAAA;AACxB,OAAO,iBAAiB,CAAA;AACxB,OAAO,6BAA6B,CAAA;AACpC,OAAO,yCAAyC,CAAA;AAChD,OAAO,uBAAuB,CAAA;AAC9B,OAAO,mBAAmB,CAAA;AAC1B,OAAO,uBAAuB,CAAA;AAC9B,OAAO,mBAAmB,CAAA;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC3C,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACnF,OAAO,EACL,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAGvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACxE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC5F,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
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",
|
|
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 = "
|
|
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.
|
|
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/
|
|
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/
|
|
51
|
+
"url": "https://github.com/ankit-kaushal/Frontend-UI-Library/issues"
|
|
52
52
|
},
|
|
53
|
-
"homepage": "https://github.com/
|
|
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"
|