@ttoss/ui 5.10.8 → 5.11.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 CHANGED
@@ -89,7 +89,7 @@ export const customTheme: Theme = {
89
89
  - `ActionButton` - Action-specific buttons
90
90
  - `IconButton` - Icon-only buttons
91
91
  - `CloseButton` - Close/dismiss buttons
92
- - `Input` - Text input fields
92
+ - `Input` - Text input fields with icon support
93
93
  - `InputNumber` - Numeric input fields
94
94
  - `InputPassword` - Password input with reveal
95
95
  - `Textarea` - Multi-line text input
@@ -100,6 +100,115 @@ export const customTheme: Theme = {
100
100
  - `Slider` - Range slider controls
101
101
  - `SegmentedControl` - Multi-option selector
102
102
 
103
+ #### Input Component Features
104
+
105
+ The `Input` component supports leading and trailing icons with tooltips:
106
+
107
+ ```tsx
108
+ import { Input } from '@ttoss/ui';
109
+
110
+ // Simplified syntax - icon as string
111
+ <Input
112
+ placeholder="Search..."
113
+ leadingIcon="ant-design:search-outlined"
114
+ trailingIcon="ant-design:info-circle-outlined"
115
+ />
116
+
117
+ // Full syntax with tooltip and click handler
118
+ <Input
119
+ placeholder="Search..."
120
+ leadingIcon={{
121
+ icon: 'ant-design:search-outlined',
122
+ onClick: () => console.log('Search clicked'),
123
+ tooltip: 'Click to search'
124
+ }}
125
+ trailingIcon={{
126
+ icon: 'ant-design:info-circle-outlined',
127
+ tooltip: 'Additional information',
128
+ tooltipProps: { place: 'right' }
129
+ }}
130
+ />
131
+
132
+ // SVG icons from @iconify
133
+ import searchIcon from '@iconify/icons-mdi/search';
134
+
135
+ <Input
136
+ placeholder="Email"
137
+ leadingIcon={searchIcon}
138
+ />
139
+ ```
140
+
141
+ **Testing Input Icons:**
142
+
143
+ Use `data-testid` to identify icons in tests. The Input component provides test IDs for icon containers, and each icon has its own `data-testid="iconify-icon"`:
144
+
145
+ ```tsx
146
+ import { render, screen } from '@testing-library/react';
147
+
148
+ test('should render input with icons', () => {
149
+ render(
150
+ <Input placeholder="Search" leadingIcon="search" trailingIcon="info" />
151
+ );
152
+
153
+ // Get icon containers (for clicking and tooltip checks)
154
+ const leadingIconContainer = screen.getByTestId('input-leading-icon');
155
+ const trailingIconContainer = screen.getByTestId('input-trailing-icon');
156
+
157
+ expect(leadingIconContainer).toBeInTheDocument();
158
+ expect(trailingIconContainer).toBeInTheDocument();
159
+
160
+ // Get the actual icon elements (for checking icon properties)
161
+ const iconElement = leadingIconContainer.querySelector(
162
+ '[data-testid="iconify-icon"]'
163
+ );
164
+ expect(iconElement).toHaveAttribute('icon', 'search');
165
+ });
166
+
167
+ // Test icon clicks (click on container, where onClick is attached)
168
+ test('should call onClick when icon is clicked', async () => {
169
+ const handleClick = jest.fn();
170
+
171
+ render(
172
+ <Input
173
+ placeholder="Search"
174
+ leadingIcon={{ icon: 'search', onClick: handleClick }}
175
+ />
176
+ );
177
+
178
+ const leadingIcon = screen.getByTestId('input-leading-icon');
179
+ await userEvent.click(leadingIcon);
180
+ expect(handleClick).toHaveBeenCalled();
181
+ });
182
+
183
+ // Test tooltips (check container for tooltip attributes)
184
+ test('should render tooltip', () => {
185
+ render(
186
+ <Input
187
+ placeholder="Search"
188
+ leadingIcon={{ icon: 'search', tooltip: 'Search here' }}
189
+ />
190
+ );
191
+
192
+ const iconContainer = screen.getByTestId('input-leading-icon');
193
+ expect(iconContainer).toHaveAttribute(
194
+ 'data-tooltip-id',
195
+ 'input-leading-icon-tooltip'
196
+ );
197
+ });
198
+
199
+ // Alternative: Query all icons and differentiate by position
200
+ test('should render both icons using iconify-icon testid', () => {
201
+ render(<Input leadingIcon="search" trailingIcon="info" />);
202
+
203
+ const icons = screen.getAllByTestId('iconify-icon');
204
+ expect(icons).toHaveLength(2);
205
+ expect(icons[0]).toHaveAttribute('icon', 'search'); // leading
206
+ expect(icons[1]).toHaveAttribute('icon', 'info'); // trailing
207
+ });
208
+ ```
209
+
210
+ ````
211
+
103
212
  ### Feedback & Status
104
213
 
105
214
  - `Badge` - Status indicators and labels
@@ -134,7 +243,7 @@ export const AppStyles = () => (
134
243
  }}
135
244
  />
136
245
  );
137
- ```
246
+ ````
138
247
 
139
248
  #### Animations
140
249
 
package/dist/esm/index.js CHANGED
@@ -387,39 +387,66 @@ var InfiniteLinearProgress = /* @__PURE__ */__name(() => {
387
387
  import { Icon as Icon4 } from "@ttoss/react-icons";
388
388
  import * as React7 from "react";
389
389
  import { Input as InputUI } from "theme-ui";
390
- var Input = /* @__PURE__ */React7.forwardRef(({
390
+ var isInputIconConfig = /* @__PURE__ */__name(icon => {
391
+ return icon !== void 0 && typeof icon === "object" && "icon" in icon && (typeof icon.icon === "string" || typeof icon.icon === "object" && "body" in icon.icon);
392
+ }, "isInputIconConfig");
393
+ var normalizeIcon = /* @__PURE__ */__name(icon => {
394
+ if (!icon) {
395
+ return void 0;
396
+ }
397
+ if (isInputIconConfig(icon)) {
398
+ return icon;
399
+ }
400
+ return {
401
+ icon
402
+ };
403
+ }, "normalizeIcon");
404
+ var Input = /* @__PURE__ */__name(({
391
405
  leadingIcon,
392
406
  trailingIcon: trailingIconProp,
393
- onLeadingIconClick,
394
- onTrailingIconClick,
395
407
  className,
396
408
  sx,
397
409
  ...inputProps
398
- }, ref) => {
399
- const trailingIcon = inputProps["aria-invalid"] ? "warning-alt" : trailingIconProp;
400
- const isWarning = !inputProps["aria-invalid"] && trailingIcon === "warning-alt";
410
+ }) => {
411
+ const normalizedLeadingIcon = normalizeIcon(leadingIcon);
412
+ const normalizedTrailingIconProp = normalizeIcon(trailingIconProp);
413
+ const ariaInvalid = inputProps["aria-invalid"];
414
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true";
415
+ const trailingIcon = isInvalid ? {
416
+ ...normalizedTrailingIconProp,
417
+ icon: "warning-alt"
418
+ } : normalizedTrailingIconProp;
419
+ const isWarning = !isInvalid && trailingIcon?.icon === "warning-alt";
420
+ const wrapperClassName = [className, isWarning && "is-warning"].filter(Boolean).join(" ");
421
+ const id = React7.useId();
422
+ const leadingTooltipId = `${id}-leading-tooltip`;
423
+ const trailingTooltipId = `${id}-trailing-tooltip`;
401
424
  return /* @__PURE__ */React7.createElement(Flex, {
402
- className: `${className} ${isWarning ? "is-warning" : ""}`,
425
+ className: wrapperClassName,
403
426
  sx: {
404
427
  ...sx,
405
428
  position: "relative",
406
429
  padding: 0,
407
430
  border: "none"
408
431
  }
409
- }, leadingIcon && /* @__PURE__ */React7.createElement(Text, {
432
+ }, normalizedLeadingIcon && /* @__PURE__ */React7.createElement(React7.Fragment, null, /* @__PURE__ */React7.createElement(Text, {
433
+ "data-testid": "input-leading-icon",
434
+ "data-tooltip-id": normalizedLeadingIcon.tooltip ? leadingTooltipId : void 0,
410
435
  sx: {
411
436
  position: "absolute",
412
437
  alignSelf: "center",
413
438
  left: "1rem",
414
- cursor: onLeadingIconClick ? "pointer" : "default"
439
+ cursor: normalizedLeadingIcon.onClick ? "pointer" : "default"
415
440
  },
416
- onClick: onLeadingIconClick,
441
+ onClick: normalizedLeadingIcon.onClick,
417
442
  variant: "leading-icon"
418
443
  }, /* @__PURE__ */React7.createElement(Icon4, {
419
444
  inline: true,
420
- icon: leadingIcon
421
- })), /* @__PURE__ */React7.createElement(InputUI, {
422
- ref,
445
+ icon: normalizedLeadingIcon.icon
446
+ })), normalizedLeadingIcon.tooltip && /* @__PURE__ */React7.createElement(Tooltip, {
447
+ id: leadingTooltipId,
448
+ ...normalizedLeadingIcon.tooltipProps
449
+ }, normalizedLeadingIcon.tooltip)), /* @__PURE__ */React7.createElement(InputUI, {
423
450
  sx: {
424
451
  fontFamily: "body",
425
452
  paddingY: "3",
@@ -431,23 +458,27 @@ var Input = /* @__PURE__ */React7.forwardRef(({
431
458
  },
432
459
  className,
433
460
  ...inputProps
434
- }), trailingIcon && /* @__PURE__ */React7.createElement(Text, {
461
+ }), trailingIcon && /* @__PURE__ */React7.createElement(React7.Fragment, null, /* @__PURE__ */React7.createElement(Text, {
462
+ "data-testid": "input-trailing-icon",
463
+ "data-tooltip-id": trailingIcon.tooltip ? trailingTooltipId : void 0,
435
464
  sx: {
436
465
  position: "absolute",
437
466
  right: "1rem",
438
467
  alignSelf: "center",
439
468
  color: isWarning ? "feedback.text.caution.default" : void 0,
440
- cursor: onTrailingIconClick ? "pointer" : "default",
469
+ cursor: trailingIcon.onClick ? "pointer" : "default",
441
470
  fontSize: "xl"
442
471
  },
443
472
  variant: "trailing-icon",
444
- onClick: onTrailingIconClick
473
+ onClick: trailingIcon.onClick
445
474
  }, /* @__PURE__ */React7.createElement(Icon4, {
446
475
  inline: true,
447
- icon: trailingIcon
448
- })));
449
- });
450
- Input.displayName = "Input";
476
+ icon: trailingIcon.icon
477
+ })), trailingIcon.tooltip && /* @__PURE__ */React7.createElement(Tooltip, {
478
+ id: trailingTooltipId,
479
+ ...trailingIcon.tooltipProps
480
+ }, trailingIcon.tooltip)));
481
+ }, "Input");
451
482
 
452
483
  // src/components/InputNumber.tsx
453
484
  import { Icon as Icon5 } from "@ttoss/react-icons";
@@ -570,13 +601,13 @@ var InputNumber = /* @__PURE__ */React8.forwardRef(({
570
601
  });
571
602
  InputNumber.displayName = "InputNumber";
572
603
 
573
- // src/components/InputPassword/InputPassword.tsx
574
- import * as React10 from "react";
575
-
576
- // src/components/InputPassword/useHidePassInput.ts
604
+ // src/components/InputPassword.tsx
577
605
  import * as React9 from "react";
578
- var useHidePassInput = /* @__PURE__ */__name((defaultValue = true) => {
579
- const [hidePass, setHidePass] = React9.useState(Boolean(defaultValue));
606
+ var InputPassword = /* @__PURE__ */__name(({
607
+ showPasswordByDefault = false,
608
+ ...inputPasswordProps
609
+ }) => {
610
+ const [hidePass, setHidePass] = React9.useState(Boolean(!showPasswordByDefault));
580
611
  const {
581
612
  icon,
582
613
  inputType
@@ -591,37 +622,93 @@ var useHidePassInput = /* @__PURE__ */__name((defaultValue = true) => {
591
622
  return !prev;
592
623
  });
593
624
  }, "handleClick");
594
- return {
595
- handleClick,
596
- icon,
597
- inputType
598
- };
599
- }, "useHidePassInput");
600
-
601
- // src/components/InputPassword/InputPassword.tsx
602
- var InputPassword = /* @__PURE__ */React10.forwardRef(({
603
- showPasswordByDefault,
604
- ...inputPasswordProps
605
- }, ref) => {
606
- const {
607
- handleClick,
608
- icon,
609
- inputType
610
- } = useHidePassInput(!showPasswordByDefault);
611
- return /* @__PURE__ */React10.createElement(Input, {
612
- ref,
625
+ return /* @__PURE__ */React9.createElement(Input, {
613
626
  ...inputPasswordProps,
614
- trailingIcon: icon,
615
- onTrailingIconClick: handleClick,
627
+ trailingIcon: {
628
+ icon,
629
+ onClick: handleClick
630
+ },
616
631
  type: inputType
617
632
  });
618
- });
619
- InputPassword.displayName = "InputPassword";
633
+ }, "InputPassword");
620
634
 
621
635
  // src/components/Label.tsx
622
636
  import { Icon as Icon6 } from "@ttoss/react-icons";
623
- import * as React11 from "react";
637
+ import * as React10 from "react";
624
638
  import { Label as LabelUi } from "theme-ui";
639
+
640
+ // src/components/Tooltip.tsx
641
+ import { Tooltip as TooltipReact } from "react-tooltip";
642
+ var Tooltip = /* @__PURE__ */__name(({
643
+ variant = "info",
644
+ sx,
645
+ ...props
646
+ }) => {
647
+ const className = `tooltip-component tooltip-${variant}`;
648
+ const getVariantStyles = /* @__PURE__ */__name(variantType => {
649
+ const variants = {
650
+ info: {
651
+ backgroundColor: "input.background.secondary.default",
652
+ color: "feedback.text.secondary.default",
653
+ borderColor: "feedback.border.secondary.default"
654
+ },
655
+ success: {
656
+ backgroundColor: "feedback.background.positive.default",
657
+ color: "feedback.text.positive.default",
658
+ borderColor: "feedback.border.positive.default"
659
+ },
660
+ warning: {
661
+ backgroundColor: "feedback.background.caution.default",
662
+ color: "feedback.text.caution.default",
663
+ borderColor: "feedback.border.caution.default"
664
+ },
665
+ error: {
666
+ backgroundColor: "feedback.background.negative.default",
667
+ color: "feedback.text.negative.default",
668
+ borderColor: "feedback.border.negative.default"
669
+ }
670
+ };
671
+ return variants[variantType] || variants.info;
672
+ }, "getVariantStyles");
673
+ return /* @__PURE__ */React.createElement(Box, {
674
+ sx: /* @__PURE__ */__name(({
675
+ fonts
676
+ }) => {
677
+ const variantStyles = getVariantStyles(variant);
678
+ return {
679
+ ".example-arrow": {
680
+ display: "none"
681
+ },
682
+ ".tooltip-component": {
683
+ fontFamily: fonts?.body,
684
+ paddingY: "2",
685
+ paddingX: "3",
686
+ border: "sm",
687
+ borderRadius: "xl",
688
+ zIndex: "tooltip",
689
+ opacity: "1",
690
+ lineHeight: "shorter",
691
+ letterSpacing: "wide",
692
+ a: {
693
+ color: "feedback.text.secondary.default",
694
+ fontFamily: "body",
695
+ textDecorationLine: "underline",
696
+ lineHeight: "normal"
697
+ },
698
+ ...variantStyles,
699
+ ...sx
700
+ },
701
+ [`&.tooltip-${variant}`]: variantStyles
702
+ };
703
+ }, "sx")
704
+ }, /* @__PURE__ */React.createElement(TooltipReact, {
705
+ className,
706
+ ...props,
707
+ classNameArrow: "example-arrow"
708
+ }, props.children));
709
+ }, "Tooltip");
710
+
711
+ // src/components/Label.tsx
625
712
  var TOOLTIP_LABEL = "tooltip";
626
713
  var Label = /* @__PURE__ */__name(({
627
714
  children,
@@ -629,10 +716,9 @@ var Label = /* @__PURE__ */__name(({
629
716
  sx,
630
717
  ...props
631
718
  }) => {
632
- const id = React11.useId();
719
+ const id = React10.useId();
633
720
  const tooltipId = `${id}-tooltip`;
634
- return /* @__PURE__ */React11.createElement(LabelUi, {
635
- "data-tooltip-id": tooltipId,
721
+ return /* @__PURE__ */React10.createElement(LabelUi, {
636
722
  sx: {
637
723
  alignItems: "center",
638
724
  fontSize: "sm",
@@ -642,39 +728,31 @@ var Label = /* @__PURE__ */__name(({
642
728
  ...sx
643
729
  },
644
730
  ...props
645
- }, children, tooltip && /* @__PURE__ */React11.createElement(Text, {
731
+ }, children, tooltip && /* @__PURE__ */React10.createElement(Text, {
732
+ "data-tooltip-id": tooltipId,
646
733
  sx: {
647
734
  color: "currentcolor",
648
- cursor: "pointer"
735
+ cursor: "pointer",
736
+ marginLeft: "1"
649
737
  },
650
738
  "aria-label": TOOLTIP_LABEL
651
- }, tooltip.icon ? /* @__PURE__ */React11.createElement(Icon6, {
652
- inline: true,
653
- icon: tooltip.icon
654
- }) : /* @__PURE__ */React11.createElement(Icon6, {
655
- inline: true,
656
- icon: "fluent:info-24-regular"
657
- }), /* @__PURE__ */React11.createElement(Tooltip, {
658
- id: tooltipId,
659
- openOnClick: tooltip.openOnClick,
660
- clickable: tooltip.clickable,
661
- place: tooltip.place,
662
- hidden: tooltip.hidden,
663
- variant: tooltip.variant,
664
- setIsOpen: tooltip.setIsOpen,
665
- isOpen: tooltip.isOpen
666
- }, tooltip.render)));
739
+ }, /* @__PURE__ */React10.createElement(Icon6, {
740
+ icon: "info"
741
+ }), /* @__PURE__ */React10.createElement(Tooltip, {
742
+ ...tooltip,
743
+ id: tooltipId
744
+ })));
667
745
  }, "Label");
668
746
 
669
747
  // src/components/Link.tsx
670
- import * as React12 from "react";
748
+ import * as React11 from "react";
671
749
  import { Link as LinkUi } from "theme-ui";
672
- var Link = /* @__PURE__ */React12.forwardRef(({
750
+ var Link = /* @__PURE__ */React11.forwardRef(({
673
751
  quiet,
674
752
  className,
675
753
  ...props
676
754
  }, ref) => {
677
- return /* @__PURE__ */React12.createElement(LinkUi, {
755
+ return /* @__PURE__ */React11.createElement(LinkUi, {
678
756
  className: `${quiet ? "quiet" : ""} ${className ?? ""}`,
679
757
  ...props,
680
758
  ref
@@ -689,7 +767,7 @@ import { Paragraph } from "theme-ui";
689
767
  import { Radio } from "theme-ui";
690
768
 
691
769
  // src/components/SegmentedControl.tsx
692
- import * as React13 from "react";
770
+ import * as React12 from "react";
693
771
  import { Box as Box3, Flex as Flex2 } from "theme-ui";
694
772
  var SegmentedControl = /* @__PURE__ */__name(({
695
773
  options,
@@ -701,8 +779,8 @@ var SegmentedControl = /* @__PURE__ */__name(({
701
779
  sx,
702
780
  ...rest
703
781
  }) => {
704
- const [internalValue, setInternalValue] = React13.useState(propValue || defaultValue);
705
- React13.useEffect(() => {
782
+ const [internalValue, setInternalValue] = React12.useState(propValue || defaultValue);
783
+ React12.useEffect(() => {
706
784
  if (propValue !== void 0) {
707
785
  setInternalValue(propValue);
708
786
  }
@@ -720,7 +798,7 @@ var SegmentedControl = /* @__PURE__ */__name(({
720
798
  } : option;
721
799
  });
722
800
  const currentValue = propValue !== void 0 ? propValue : internalValue;
723
- return /* @__PURE__ */React13.createElement(Flex2, {
801
+ return /* @__PURE__ */React12.createElement(Flex2, {
724
802
  className,
725
803
  sx: {
726
804
  width: "100%",
@@ -803,18 +881,18 @@ var SegmentedControl = /* @__PURE__ */__name(({
803
881
  ...sx
804
882
  },
805
883
  ...rest
806
- }, /* @__PURE__ */React13.createElement("div", {
884
+ }, /* @__PURE__ */React12.createElement("div", {
807
885
  className: "rc-segmented"
808
- }, /* @__PURE__ */React13.createElement(Flex2, {
886
+ }, /* @__PURE__ */React12.createElement(Flex2, {
809
887
  className: "rc-segmented-group custom-segmented-group"
810
888
  }, normalizedOptions.map((option, index) => {
811
889
  const isSelected = option.value === currentValue;
812
890
  const isLastItem = index === normalizedOptions.length - 1;
813
891
  const isItemDisabled = disabled || option.disabled;
814
892
  const showDivider = !isLastItem && option.value !== currentValue && normalizedOptions[index + 1].value !== currentValue;
815
- return /* @__PURE__ */React13.createElement(React13.Fragment, {
893
+ return /* @__PURE__ */React12.createElement(React12.Fragment, {
816
894
  key: `${index}-${option.value}`
817
- }, /* @__PURE__ */React13.createElement(Box3, {
895
+ }, /* @__PURE__ */React12.createElement(Box3, {
818
896
  as: "label",
819
897
  className: `rc-segmented-item ${isSelected ? "rc-segmented-item-selected" : ""} ${isItemDisabled ? "rc-segmented-item-disabled" : ""}`,
820
898
  onClick: /* @__PURE__ */__name(() => {
@@ -822,7 +900,7 @@ var SegmentedControl = /* @__PURE__ */__name(({
822
900
  handleChange(option.value);
823
901
  }
824
902
  }, "onClick")
825
- }, /* @__PURE__ */React13.createElement("input", {
903
+ }, /* @__PURE__ */React12.createElement("input", {
826
904
  type: "radio",
827
905
  value: option.value,
828
906
  checked: isSelected,
@@ -832,9 +910,9 @@ var SegmentedControl = /* @__PURE__ */__name(({
832
910
  handleChange(option.value);
833
911
  }
834
912
  }, "onChange")
835
- }), /* @__PURE__ */React13.createElement("div", {
913
+ }), /* @__PURE__ */React12.createElement("div", {
836
914
  className: "rc-segmented-item-label"
837
- }, option.label)), showDivider && /* @__PURE__ */React13.createElement(Box3, {
915
+ }, option.label)), showDivider && /* @__PURE__ */React12.createElement(Box3, {
838
916
  className: "segmented-divider",
839
917
  sx: {
840
918
  height: "60%",
@@ -845,7 +923,7 @@ var SegmentedControl = /* @__PURE__ */__name(({
845
923
  zIndex: 3
846
924
  }
847
925
  }));
848
- }), currentValue !== void 0 && /* @__PURE__ */React13.createElement("div", {
926
+ }), currentValue !== void 0 && /* @__PURE__ */React12.createElement("div", {
849
927
  className: "rc-segmented-thumb",
850
928
  style: {
851
929
  width: `${100 / normalizedOptions.length}%`,
@@ -858,7 +936,7 @@ var SegmentedControl = /* @__PURE__ */__name(({
858
936
 
859
937
  // src/components/Select.tsx
860
938
  import { Icon as Icon7 } from "@ttoss/react-icons";
861
- import * as React14 from "react";
939
+ import * as React13 from "react";
862
940
  import ReactSelect, { components } from "react-select";
863
941
  var Control = /* @__PURE__ */__name(props => {
864
942
  const isDisabled = props.selectProps.isDisabled;
@@ -878,7 +956,7 @@ var Control = /* @__PURE__ */__name(props => {
878
956
  }
879
957
  return "display.background.secondary.default";
880
958
  })();
881
- return /* @__PURE__ */React14.createElement(Box, {
959
+ return /* @__PURE__ */React13.createElement(Box, {
882
960
  sx: {
883
961
  ".react-select__control": {
884
962
  borderColor,
@@ -887,7 +965,7 @@ var Control = /* @__PURE__ */__name(props => {
887
965
  paddingY: "3"
888
966
  }
889
967
  }
890
- }, /* @__PURE__ */React14.createElement(components.Control, props));
968
+ }, /* @__PURE__ */React13.createElement(components.Control, props));
891
969
  }, "Control");
892
970
  var DropdownIndicator = /* @__PURE__ */__name(props => {
893
971
  const isDisabled = props.selectProps.isDisabled;
@@ -897,7 +975,7 @@ var DropdownIndicator = /* @__PURE__ */__name(props => {
897
975
  }
898
976
  return "text";
899
977
  })();
900
- return /* @__PURE__ */React14.createElement(Text, {
978
+ return /* @__PURE__ */React13.createElement(Text, {
901
979
  sx: {
902
980
  fontSize: "md",
903
981
  color,
@@ -905,14 +983,14 @@ var DropdownIndicator = /* @__PURE__ */__name(props => {
905
983
  display: "flex",
906
984
  alignItems: "center"
907
985
  }
908
- }, /* @__PURE__ */React14.createElement(Icon7, {
986
+ }, /* @__PURE__ */React13.createElement(Icon7, {
909
987
  icon: "picker-down"
910
988
  }));
911
989
  }, "DropdownIndicator");
912
990
  var IndicatorsContainer = /* @__PURE__ */__name(({
913
991
  children
914
992
  }) => {
915
- return /* @__PURE__ */React14.createElement(Box, {
993
+ return /* @__PURE__ */React13.createElement(Box, {
916
994
  sx: {
917
995
  marginLeft: "4",
918
996
  border: "none"
@@ -922,7 +1000,7 @@ var IndicatorsContainer = /* @__PURE__ */__name(({
922
1000
  var Placeholder = /* @__PURE__ */__name(({
923
1001
  children
924
1002
  }) => {
925
- return /* @__PURE__ */React14.createElement(Text, {
1003
+ return /* @__PURE__ */React13.createElement(Text, {
926
1004
  sx: {
927
1005
  color: "onMuted",
928
1006
  alignSelf: "center"
@@ -940,10 +1018,10 @@ var SelectContainer = /* @__PURE__ */__name(({
940
1018
  return (
941
1019
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
942
1020
  /* @__PURE__ */
943
- React14.createElement(Box, {
1021
+ React13.createElement(Box, {
944
1022
  sx,
945
1023
  css: css2
946
- }, /* @__PURE__ */React14.createElement(components.SelectContainer, props, children))
1024
+ }, /* @__PURE__ */React13.createElement(components.SelectContainer, props, children))
947
1025
  );
948
1026
  }, "SelectContainer");
949
1027
  var ValueContainer = /* @__PURE__ */__name(({
@@ -969,26 +1047,26 @@ var ValueContainer = /* @__PURE__ */__name(({
969
1047
  }
970
1048
  return leadingIcon || "search";
971
1049
  })();
972
- return /* @__PURE__ */React14.createElement(Flex, {
1050
+ return /* @__PURE__ */React13.createElement(Flex, {
973
1051
  sx: {
974
1052
  gap: "4",
975
1053
  flex: 1
976
1054
  }
977
- }, finalLeadingIcon && /* @__PURE__ */React14.createElement(Text, {
1055
+ }, finalLeadingIcon && /* @__PURE__ */React13.createElement(Text, {
978
1056
  sx: {
979
1057
  alignSelf: "center",
980
1058
  pointerEvents: "none",
981
1059
  lineHeight: 0,
982
1060
  fontSize: "md"
983
1061
  }
984
- }, /* @__PURE__ */React14.createElement(Icon7, {
1062
+ }, /* @__PURE__ */React13.createElement(Icon7, {
985
1063
  icon: finalLeadingIcon
986
- })), /* @__PURE__ */React14.createElement(Flex, {
1064
+ })), /* @__PURE__ */React13.createElement(Flex, {
987
1065
  sx: {
988
1066
  flex: 1,
989
1067
  alignItems: "center"
990
1068
  }
991
- }, children), (trailingIcon || hasError) && /* @__PURE__ */React14.createElement(Text, {
1069
+ }, children), (trailingIcon || hasError) && /* @__PURE__ */React13.createElement(Text, {
992
1070
  className: hasError ? "error-icon" : "",
993
1071
  sx: {
994
1072
  alignSelf: "center",
@@ -997,11 +1075,11 @@ var ValueContainer = /* @__PURE__ */__name(({
997
1075
  fontSize: "md",
998
1076
  color: trailingIconColor
999
1077
  }
1000
- }, /* @__PURE__ */React14.createElement(Icon7, {
1078
+ }, /* @__PURE__ */React13.createElement(Icon7, {
1001
1079
  icon: hasError ? "warning-alt" : trailingIcon
1002
1080
  })));
1003
1081
  }, "ValueContainer");
1004
- var Select = /* @__PURE__ */React14.forwardRef(({
1082
+ var Select = /* @__PURE__ */React13.forwardRef(({
1005
1083
  ...props
1006
1084
  }, ref) => {
1007
1085
  const value = props.options?.find(option => {
@@ -1010,7 +1088,7 @@ var Select = /* @__PURE__ */React14.forwardRef(({
1010
1088
  }
1011
1089
  return false;
1012
1090
  });
1013
- return /* @__PURE__ */React14.createElement(ReactSelect, {
1091
+ return /* @__PURE__ */React13.createElement(ReactSelect, {
1014
1092
  ref,
1015
1093
  /**
1016
1094
  * https://react-select.com/components
@@ -1092,7 +1170,7 @@ var Switch = /* @__PURE__ */__name(props => {
1092
1170
  }, "Switch");
1093
1171
 
1094
1172
  // src/components/Tag.tsx
1095
- import * as React15 from "react";
1173
+ import * as React14 from "react";
1096
1174
  var tagVariantMap = {
1097
1175
  positive: {
1098
1176
  bg: "feedback.background.positive.default",
@@ -1149,7 +1227,7 @@ var Tag = /* @__PURE__ */__name(({
1149
1227
  alignItems: "center"
1150
1228
  };
1151
1229
  if (Array.isArray(children)) {
1152
- return /* @__PURE__ */React15.createElement(Box, {
1230
+ return /* @__PURE__ */React14.createElement(Box, {
1153
1231
  as: "span",
1154
1232
  sx: {
1155
1233
  ml: 2,
@@ -1159,7 +1237,7 @@ var Tag = /* @__PURE__ */__name(({
1159
1237
  ...sx
1160
1238
  }
1161
1239
  }, children.map((child, i) => {
1162
- return /* @__PURE__ */React15.createElement(Box, {
1240
+ return /* @__PURE__ */React14.createElement(Box, {
1163
1241
  key: i,
1164
1242
  as: "span",
1165
1243
  sx: {
@@ -1173,7 +1251,7 @@ var Tag = /* @__PURE__ */__name(({
1173
1251
  }, child);
1174
1252
  }));
1175
1253
  }
1176
- return /* @__PURE__ */React15.createElement(Box, {
1254
+ return /* @__PURE__ */React14.createElement(Box, {
1177
1255
  as: "span",
1178
1256
  sx: {
1179
1257
  ...baseStyles,
@@ -1184,15 +1262,15 @@ var Tag = /* @__PURE__ */__name(({
1184
1262
 
1185
1263
  // src/components/Textarea.tsx
1186
1264
  import { Icon as Icon8 } from "@ttoss/react-icons";
1187
- import * as React16 from "react";
1265
+ import * as React15 from "react";
1188
1266
  import { Textarea as TextareaUI } from "theme-ui";
1189
- var Textarea = /* @__PURE__ */React16.forwardRef(({
1267
+ var Textarea = /* @__PURE__ */React15.forwardRef(({
1190
1268
  trailingIcon,
1191
1269
  className,
1192
1270
  sx,
1193
1271
  ...textareaProps
1194
1272
  }, ref) => {
1195
- return /* @__PURE__ */React16.createElement(Flex, {
1273
+ return /* @__PURE__ */React15.createElement(Flex, {
1196
1274
  className,
1197
1275
  sx: {
1198
1276
  ...sx,
@@ -1200,7 +1278,7 @@ var Textarea = /* @__PURE__ */React16.forwardRef(({
1200
1278
  padding: 0,
1201
1279
  border: "none"
1202
1280
  }
1203
- }, /* @__PURE__ */React16.createElement(TextareaUI, {
1281
+ }, /* @__PURE__ */React15.createElement(TextareaUI, {
1204
1282
  ref,
1205
1283
  sx: {
1206
1284
  fontFamily: "body",
@@ -1212,103 +1290,32 @@ var Textarea = /* @__PURE__ */React16.forwardRef(({
1212
1290
  },
1213
1291
  className,
1214
1292
  ...textareaProps
1215
- }), trailingIcon && /* @__PURE__ */React16.createElement(Text, {
1293
+ }), trailingIcon && /* @__PURE__ */React15.createElement(Text, {
1216
1294
  sx: {
1217
1295
  position: "absolute",
1218
1296
  right: "1.25rem",
1219
1297
  top: "0.75rem"
1220
1298
  }
1221
- }, /* @__PURE__ */React16.createElement(Icon8, {
1299
+ }, /* @__PURE__ */React15.createElement(Icon8, {
1222
1300
  inline: true,
1223
1301
  icon: trailingIcon
1224
1302
  })));
1225
1303
  });
1226
1304
  Textarea.displayName = "Textarea";
1227
1305
 
1228
- // src/components/Tooltip.tsx
1229
- import { Tooltip as TooltipReact } from "react-tooltip";
1230
- var Tooltip = /* @__PURE__ */__name(({
1231
- variant = "info",
1232
- sx,
1233
- ...props
1234
- }) => {
1235
- const className = `tooltip-component tooltip-${variant}`;
1236
- const getVariantStyles = /* @__PURE__ */__name(variantType => {
1237
- const variants = {
1238
- info: {
1239
- backgroundColor: "input.background.secondary.default",
1240
- color: "feedback.text.secondary.default",
1241
- borderColor: "feedback.border.secondary.default"
1242
- },
1243
- success: {
1244
- backgroundColor: "feedback.background.positive.default",
1245
- color: "feedback.text.positive.default",
1246
- borderColor: "feedback.border.positive.default"
1247
- },
1248
- warning: {
1249
- backgroundColor: "feedback.background.caution.default",
1250
- color: "feedback.text.caution.default",
1251
- borderColor: "feedback.border.caution.default"
1252
- },
1253
- error: {
1254
- backgroundColor: "feedback.background.negative.default",
1255
- color: "feedback.text.negative.default",
1256
- borderColor: "feedback.border.negative.default"
1257
- }
1258
- };
1259
- return variants[variantType] || variants.info;
1260
- }, "getVariantStyles");
1261
- return /* @__PURE__ */React.createElement(Box, {
1262
- sx: /* @__PURE__ */__name(({
1263
- fonts
1264
- }) => {
1265
- const variantStyles = getVariantStyles(variant);
1266
- return {
1267
- ".example-arrow": {
1268
- display: "none"
1269
- },
1270
- ".tooltip-component": {
1271
- fontFamily: fonts?.body,
1272
- paddingY: "2",
1273
- paddingX: "3",
1274
- border: "sm",
1275
- borderRadius: "xl",
1276
- zIndex: "tooltip",
1277
- opacity: "1",
1278
- lineHeight: "shorter",
1279
- letterSpacing: "wide",
1280
- a: {
1281
- color: "feedback.text.secondary.default",
1282
- fontFamily: "body",
1283
- textDecorationLine: "underline",
1284
- lineHeight: "normal"
1285
- },
1286
- ...variantStyles,
1287
- ...sx
1288
- },
1289
- [`&.tooltip-${variant}`]: variantStyles
1290
- };
1291
- }, "sx")
1292
- }, /* @__PURE__ */React.createElement(TooltipReact, {
1293
- className,
1294
- ...props,
1295
- classNameArrow: "example-arrow"
1296
- }, props.children));
1297
- }, "Tooltip");
1298
-
1299
1306
  // src/theme/ThemeProvider.tsx
1300
1307
  import { css, Global } from "@emotion/react";
1301
1308
  import { BruttalFonts, BruttalTheme } from "@ttoss/theme/Bruttal";
1302
- import * as React17 from "react";
1309
+ import * as React16 from "react";
1303
1310
  import { ThemeUIProvider } from "theme-ui";
1304
1311
  var ThemeProvider = /* @__PURE__ */__name(({
1305
1312
  children,
1306
1313
  theme = BruttalTheme,
1307
1314
  fonts = BruttalFonts
1308
1315
  }) => {
1309
- return /* @__PURE__ */React17.createElement(React17.Fragment, null, /* @__PURE__ */React17.createElement(ThemeUIProvider, {
1316
+ return /* @__PURE__ */React16.createElement(React16.Fragment, null, /* @__PURE__ */React16.createElement(ThemeUIProvider, {
1310
1317
  theme
1311
- }, /* @__PURE__ */React17.createElement(Global, {
1318
+ }, /* @__PURE__ */React16.createElement(Global, {
1312
1319
  styles: css`
1313
1320
  ${fonts.map(url => {
1314
1321
  return `@import url('${url}');`;
package/dist/index.d.ts CHANGED
@@ -2,10 +2,10 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { IconType } from '@ttoss/react-icons';
3
3
  import * as React from 'react';
4
4
  import * as theme_ui from 'theme-ui';
5
- import { ButtonProps as ButtonProps$1, BadgeProps as BadgeProps$1, CardProps, BoxProps, CheckboxProps as CheckboxProps$1, CloseProps, TextProps, IconButtonProps as IconButtonProps$1, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, FlexProps, SxProp, SwitchProps, ThemeUIStyleObject, TextareaProps as TextareaProps$1, Theme } from 'theme-ui';
5
+ import { ButtonProps as ButtonProps$1, BadgeProps as BadgeProps$1, CardProps, BoxProps, CheckboxProps as CheckboxProps$1, CloseProps, TextProps, IconButtonProps as IconButtonProps$1, SxProp, InputProps as InputProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, FlexProps, SwitchProps, ThemeUIStyleObject, TextareaProps as TextareaProps$1, Theme } from 'theme-ui';
6
6
  export { BaseStyles, Box, BoxProps, CardProps, ContainerProps, Divider, DividerProps, Flex, FlexProps, Global, Grid, GridProps, Heading, HeadingProps, Image, ImageProps, Progress as LinearProgress, ProgressProps as LinearProgressProps, Paragraph, ParagraphProps, Radio, RadioProps, Slider, SliderProps, Spinner, SpinnerProps, SwitchProps, SxProp, Text, TextProps, Theme, ThemeUIStyleObject } from 'theme-ui';
7
- import { Props } from 'react-select';
8
7
  import { ITooltip } from 'react-tooltip';
8
+ import { Props } from 'react-select';
9
9
  export { Keyframes, keyframes } from '@emotion/react';
10
10
  export { useBreakpointIndex, useResponsiveValue } from '@theme-ui/match-media';
11
11
 
@@ -61,13 +61,20 @@ declare const IconButton: (props: IconButtonProps) => react_jsx_runtime.JSX.Elem
61
61
 
62
62
  declare const InfiniteLinearProgress: () => react_jsx_runtime.JSX.Element;
63
63
 
64
+ type TooltipProps = ITooltip & SxProp;
65
+ declare const Tooltip: ({ variant, sx, ...props }: TooltipProps) => react_jsx_runtime.JSX.Element;
66
+
67
+ interface InputIconConfig {
68
+ icon: IconType;
69
+ onClick?: () => void;
70
+ tooltip?: string;
71
+ tooltipProps?: Omit<TooltipProps, 'children' | 'anchorSelect'>;
72
+ }
64
73
  interface InputProps extends InputProps$1 {
65
- leadingIcon?: IconType;
66
- onLeadingIconClick?: () => void;
67
- trailingIcon?: IconType;
68
- onTrailingIconClick?: () => void;
74
+ leadingIcon?: InputIconConfig | IconType;
75
+ trailingIcon?: InputIconConfig | IconType;
69
76
  }
70
- declare const Input: React.ForwardRefExoticComponent<Omit<InputProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
77
+ declare const Input: ({ leadingIcon, trailingIcon: trailingIconProp, className, sx, ...inputProps }: InputProps) => react_jsx_runtime.JSX.Element;
71
78
 
72
79
  type InputNumberProps = Omit<InputProps$1, 'type' | 'variant' | 'onChange'> & {
73
80
  onChange: (value: number) => void;
@@ -77,23 +84,13 @@ type InputNumberProps = Omit<InputProps$1, 'type' | 'variant' | 'onChange'> & {
77
84
  };
78
85
  declare const InputNumber: React.ForwardRefExoticComponent<Omit<InputNumberProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
79
86
 
80
- type InputPasswordProps = Omit<InputProps, 'trailingIcon' | 'onTrailingIconClick' | 'type'> & {
87
+ type InputPasswordProps = Omit<InputProps, 'trailingIcon' | 'type'> & {
81
88
  showPasswordByDefault?: boolean;
82
89
  };
83
- declare const InputPassword: React.ForwardRefExoticComponent<Omit<InputPasswordProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
90
+ declare const InputPassword: ({ showPasswordByDefault, ...inputPasswordProps }: InputPasswordProps) => react_jsx_runtime.JSX.Element;
84
91
 
85
92
  type LabelProps = LabelProps$1 & {
86
- tooltip?: {
87
- render: string | React.ReactNode;
88
- place: 'top' | 'right' | 'bottom' | 'left';
89
- openOnClick?: boolean;
90
- clickable?: boolean;
91
- variant?: 'dark' | 'light' | 'success' | 'warning' | 'error' | 'info';
92
- hidden?: boolean;
93
- setIsOpen?: (value: boolean) => void;
94
- isOpen?: boolean;
95
- icon?: string;
96
- };
93
+ tooltip?: TooltipProps;
97
94
  };
98
95
  declare const Label: ({ children, tooltip, sx, ...props }: LabelProps) => react_jsx_runtime.JSX.Element;
99
96
 
@@ -172,8 +169,6 @@ interface TextareaProps extends TextareaProps$1 {
172
169
  }
173
170
  declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
174
171
 
175
- declare const Tooltip: ({ variant, sx, ...props }: ITooltip & SxProp) => react_jsx_runtime.JSX.Element;
176
-
177
172
  type ThemeProviderProps = {
178
173
  children?: React.ReactNode;
179
174
  theme?: Theme;
@@ -186,4 +181,4 @@ declare const ThemeProvider: ({ children, theme, fonts, }: ThemeProviderProps) =
186
181
 
187
182
  declare const useTheme: () => theme_ui.ThemeUIContextValue;
188
183
 
189
- export { ActionButton, type ActionButtonProps, Badge, type BadgeProps, Button, type ButtonProps, Card, Checkbox, type CheckboxProps, CloseButton, type CloseButtonProps, Container, HelpText, type HelpTextProps, IconButton, type IconButtonProps, InfiniteLinearProgress, Input, InputNumber, type InputNumberProps, InputPassword, type InputPasswordProps, type InputProps, Label, type LabelProps, Link, type LinkProps, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectOptions, type SelectProps, Stack, type StackProps, Switch, Tag, type TagProps, Textarea, type TextareaProps, ThemeProvider, type ThemeProviderProps, Tooltip, useTheme };
184
+ export { ActionButton, type ActionButtonProps, Badge, type BadgeProps, Button, type ButtonProps, Card, Checkbox, type CheckboxProps, CloseButton, type CloseButtonProps, Container, HelpText, type HelpTextProps, IconButton, type IconButtonProps, InfiniteLinearProgress, Input, InputNumber, type InputNumberProps, InputPassword, type InputPasswordProps, type InputProps, Label, type LabelProps, Link, type LinkProps, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectOptions, type SelectProps, Stack, type StackProps, Switch, Tag, type TagProps, Textarea, type TextareaProps, ThemeProvider, type ThemeProviderProps, Tooltip, type TooltipProps, useTheme };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/ui",
3
- "version": "5.10.8",
3
+ "version": "5.11.1",
4
4
  "description": "Primitive layout, typographic, and other components for styling applications.",
5
5
  "license": "MIT",
6
6
  "author": "ttoss",
@@ -24,12 +24,12 @@
24
24
  ],
25
25
  "sideEffects": false,
26
26
  "dependencies": {
27
- "@theme-ui/match-media": "^0.17.1",
27
+ "@theme-ui/match-media": "^0.17.2",
28
28
  "rc-segmented": "^2.7.0",
29
- "react-select": "^5.9.0",
30
- "react-tooltip": "^5.28.0",
31
- "theme-ui": "^0.17.1",
32
- "@ttoss/theme": "^2.6.11"
29
+ "react-select": "^5.10.2",
30
+ "react-tooltip": "^5.30.0",
31
+ "theme-ui": "^0.17.2",
32
+ "@ttoss/theme": "^2.7.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@emotion/react": "^11",
@@ -45,8 +45,8 @@
45
45
  "react": "^19.2.0",
46
46
  "tsup": "^8.5.1",
47
47
  "@ttoss/config": "^1.35.12",
48
- "@ttoss/react-icons": "^0.5.3",
49
- "@ttoss/test-utils": "^3.0.4"
48
+ "@ttoss/test-utils": "^3.0.4",
49
+ "@ttoss/react-icons": "^0.5.3"
50
50
  },
51
51
  "keywords": [
52
52
  "React",