infinity-ui-elements 1.8.10 → 1.8.12

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.esm.js CHANGED
@@ -992,6 +992,68 @@ const Alert = React.forwardRef(({ className, emphasis = "subtle", intent = "info
992
992
  });
993
993
  Alert.displayName = "Alert";
994
994
 
995
+ /**
996
+ * Amount component that displays formatted currency amounts with decimal numbers in superscript.
997
+ *
998
+ * @example
999
+ * ```tsx
1000
+ * <Amount value={1234.56} currency="USD" />
1001
+ * // Renders: USD 1,234.<sup>56</sup>
1002
+ *
1003
+ * <Amount value={5000} currency="INR" />
1004
+ * // Renders: INR 5,000.<sup>00</sup>
1005
+ * ```
1006
+ */
1007
+ const Amount = React.forwardRef(({ value, currency, locale = "en-US", minimumFractionDigits = 2, maximumFractionDigits = 2, showCurrency = true, className, ...props }, ref) => {
1008
+ // Parse the formatted amount into parts
1009
+ const parts = React.useMemo(() => {
1010
+ // Always format as a number (not currency style) to get number formatting
1011
+ const formatter = new Intl.NumberFormat(locale, {
1012
+ minimumFractionDigits,
1013
+ maximumFractionDigits,
1014
+ });
1015
+ // Use formatToParts to get structured parts
1016
+ const formattedParts = formatter.formatToParts(value);
1017
+ let integerPart = "";
1018
+ let decimalPart = "";
1019
+ let decimalSeparator = ".";
1020
+ formattedParts.forEach((part) => {
1021
+ switch (part.type) {
1022
+ case "integer":
1023
+ integerPart += part.value;
1024
+ break;
1025
+ case "decimal":
1026
+ decimalSeparator = part.value;
1027
+ break;
1028
+ case "fraction":
1029
+ decimalPart = part.value;
1030
+ break;
1031
+ case "group":
1032
+ integerPart += part.value;
1033
+ break;
1034
+ }
1035
+ });
1036
+ // Use currency code as prefix if provided and showCurrency is true
1037
+ const currencyPrefix = currency && showCurrency ? `${currency} ` : "";
1038
+ return {
1039
+ currency: currencyPrefix,
1040
+ integer: integerPart,
1041
+ decimal: decimalPart,
1042
+ decimalSeparator: decimalSeparator,
1043
+ hasDecimal: decimalPart.length > 0,
1044
+ };
1045
+ }, [
1046
+ value,
1047
+ currency,
1048
+ locale,
1049
+ minimumFractionDigits,
1050
+ maximumFractionDigits,
1051
+ showCurrency,
1052
+ ]);
1053
+ return (jsxs("span", { ref: ref, className: cn("inline-flex items-baseline", className), ...props, children: [parts.currency && jsx("span", { children: parts.currency }), jsx("span", { className: "ml-[0.2em]", children: parts.integer }), parts.hasDecimal && (jsxs(Fragment, { children: [jsx("span", { className: "mx-[0.05em]", children: parts.decimalSeparator }), jsx("sup", { className: "text-[0.75em] leading-none", children: parts.decimal })] }))] }));
1054
+ });
1055
+ Amount.displayName = "Amount";
1056
+
995
1057
  // Helper function to get the text utility class name
996
1058
  function getTextClassName(variant = "body", size = "medium", weight = "regular", color = "default") {
997
1059
  // Build the base class name
@@ -3061,7 +3123,7 @@ const textFieldVariants = cva("relative flex items-center gap-2 border rounded-l
3061
3123
  isDisabled: false,
3062
3124
  },
3063
3125
  });
3064
- const TextField = React.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, LinkComponent, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
3126
+ const TextField = React.forwardRef(({ label, helperText, errorText, successText, size = "medium", validationState = "none", isDisabled = false, isLoading = false, isRequired = false, isOptional = false, prefix, suffix, showClearButton = false, infoDescription, infoHeading, LinkComponent, linkText, linkHref, onLinkClick, onClear, containerClassName, labelClassName, inputClassName, className, value, onChange, ...props }, ref) => {
3065
3127
  const [internalValue, setInternalValue] = React.useState("");
3066
3128
  const inputValue = value !== undefined ? value : internalValue;
3067
3129
  const hasValue = inputValue && String(inputValue).length > 0;
@@ -3108,7 +3170,7 @@ const TextField = React.forwardRef(({ label, helperText, errorText, successText,
3108
3170
  size,
3109
3171
  validationState: currentValidationState,
3110
3172
  isDisabled,
3111
- }), className), children: [prefix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
3173
+ }), isLoading && "text-field-loading", className), children: [prefix && (jsx("span", { className: cn("shrink-0 flex items-center", isDisabled
3112
3174
  ? "text-surface-ink-neutral-disabled"
3113
3175
  : currentValidationState === "positive"
3114
3176
  ? "text-feedback-ink-positive-intense"
@@ -3131,7 +3193,7 @@ const defaultFilter = (item, query) => {
3131
3193
  return (item.label.toLowerCase().includes(searchQuery) ||
3132
3194
  (item.description?.toLowerCase().includes(searchQuery) ?? false));
3133
3195
  };
3134
- const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHeading, isLoading = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText, secondaryButtonText, onPrimaryClick, onSecondaryClick, dropdownWidth = "full", showChevron = false, emptyIcon, disableFooter = false, footerLayout = "horizontal", onSearchChange, onItemSelect, filterFunction = defaultFilter, searchValue: controlledSearchValue, defaultSearchValue = "", dropdownClassName, minSearchLength = 0, showOnFocus = true, showAddNew = false, containerClassName, ...textFieldProps }, ref) => {
3196
+ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHeading, isLoading = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText, secondaryButtonText, onPrimaryClick, onSecondaryClick, dropdownWidth = "full", showChevron = false, emptyIcon, disableFooter = false, footerLayout = "horizontal", onSearchChange, onItemSelect, filterFunction = defaultFilter, searchValue: controlledSearchValue, defaultSearchValue = "", dropdownClassName, minSearchLength = 0, showOnFocus = true, showAddNew = false, onAddNew, containerClassName, ...textFieldProps }, ref) => {
3135
3197
  const [uncontrolledSearchValue, setUncontrolledSearchValue] = React.useState(defaultSearchValue);
3136
3198
  const [isOpen, setIsOpen] = React.useState(false);
3137
3199
  const [focusedIndex, setFocusedIndex] = React.useState(-1);
@@ -3198,16 +3260,21 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
3198
3260
  }
3199
3261
  const addNewItem = {
3200
3262
  value: searchValue,
3201
- label: `+ Add ${searchValue}`,
3263
+ label: `+ Add "${searchValue}"`,
3202
3264
  variant: "primary",
3203
3265
  onClick: () => {
3204
- const newItem = {
3205
- value: searchValue,
3206
- label: searchValue,
3207
- };
3208
- onItemSelect?.(newItem);
3209
- if (controlledSearchValue === undefined) {
3210
- setUncontrolledSearchValue(searchValue);
3266
+ if (onAddNew) {
3267
+ onAddNew(searchValue);
3268
+ }
3269
+ else {
3270
+ const newItem = {
3271
+ value: searchValue,
3272
+ label: searchValue,
3273
+ };
3274
+ onItemSelect?.(newItem);
3275
+ if (controlledSearchValue === undefined) {
3276
+ setUncontrolledSearchValue(searchValue);
3277
+ }
3211
3278
  }
3212
3279
  setIsOpen(false);
3213
3280
  inputRef.current?.focus();
@@ -3219,6 +3286,7 @@ const SearchableDropdown = React.forwardRef(({ className, items = [], sectionHea
3219
3286
  searchValue,
3220
3287
  filteredItems,
3221
3288
  onItemSelect,
3289
+ onAddNew,
3222
3290
  controlledSearchValue,
3223
3291
  ]);
3224
3292
  // Reset focused index when items change
@@ -3945,5 +4013,5 @@ const TextArea = React.forwardRef(({ label, helperText, errorText, successText,
3945
4013
  });
3946
4014
  TextArea.displayName = "TextArea";
3947
4015
 
3948
- export { Alert, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
4016
+ export { Alert, Amount, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, DatePicker, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
3949
4017
  //# sourceMappingURL=index.esm.js.map