infinity-ui-elements 1.8.64 → 1.9.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,IAAI,EACJ,iBAAiB,EACjB,OAAO,EACP,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,IAAI,EACJ,iBAAiB,EACjB,OAAO,EACP,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC"}
package/dist/index.esm.js CHANGED
@@ -953,7 +953,7 @@ const alertTextVariants = cva("", {
953
953
  intent: "info",
954
954
  },
955
955
  });
956
- const getDefaultIcon = (intent, emphasis) => {
956
+ const getDefaultIcon$1 = (intent, emphasis) => {
957
957
  const iconSize = 16;
958
958
  switch (emphasis) {
959
959
  case "intense":
@@ -1001,7 +1001,7 @@ const getActionLink = (actionButtonText, onActionLinkClick, emphasis, intent) =>
1001
1001
  return (jsx(Link, { type: "action", color: intent, size: "small", onClick: onActionLinkClick, children: actionButtonText }));
1002
1002
  };
1003
1003
  const Alert = React.forwardRef(({ className, emphasis = "subtle", intent = "info", title, children, isFullWidth = false, onClose, icon, actionButtonText, onActionButtonClick, actionLinkText, onActionLinkClick, ...props }, ref) => {
1004
- const displayIcon = icon ?? getDefaultIcon(intent, emphasis);
1004
+ const displayIcon = icon ?? getDefaultIcon$1(intent, emphasis);
1005
1005
  const actionButton = getActionButton(actionButtonText, onActionButtonClick, emphasis, intent);
1006
1006
  const actionLink = getActionLink(actionLinkText, onActionLinkClick, emphasis, intent);
1007
1007
  const hasActions = actionButton || actionLink;
@@ -4846,6 +4846,339 @@ const TextArea = React.forwardRef(({ label, helperText, errorText, successText,
4846
4846
  });
4847
4847
  TextArea.displayName = "TextArea";
4848
4848
 
4849
+ const toastVariants = cva("relative flex items-center gap-3 p-4 rounded-large shadow-lg min-w-[360px] max-w-[480px] transition-all", {
4850
+ variants: {
4851
+ type: {
4852
+ information: "",
4853
+ promotional: "bg-surface-fill-neutral-intense",
4854
+ },
4855
+ intent: {
4856
+ neutral: "",
4857
+ positive: "",
4858
+ negative: "",
4859
+ notice: "",
4860
+ info: "",
4861
+ },
4862
+ },
4863
+ compoundVariants: [
4864
+ // Information type with different intents
4865
+ {
4866
+ type: "information",
4867
+ intent: "neutral",
4868
+ class: "bg-feedback-fill-neutral-intense",
4869
+ },
4870
+ {
4871
+ type: "information",
4872
+ intent: "positive",
4873
+ class: "bg-feedback-fill-positive-intense",
4874
+ },
4875
+ {
4876
+ type: "information",
4877
+ intent: "negative",
4878
+ class: "bg-feedback-fill-negative-intense",
4879
+ },
4880
+ {
4881
+ type: "information",
4882
+ intent: "notice",
4883
+ class: "bg-feedback-fill-notice-intense",
4884
+ },
4885
+ {
4886
+ type: "information",
4887
+ intent: "info",
4888
+ class: "bg-feedback-fill-info-intense",
4889
+ },
4890
+ ],
4891
+ defaultVariants: {
4892
+ type: "information",
4893
+ intent: "neutral",
4894
+ },
4895
+ });
4896
+ const toastIconVariants = cva("flex-shrink-0 flex items-center justify-center", {
4897
+ variants: {
4898
+ type: {
4899
+ information: "text-white",
4900
+ promotional: "text-action-ink-neutral-normal",
4901
+ },
4902
+ },
4903
+ defaultVariants: {
4904
+ type: "information",
4905
+ },
4906
+ });
4907
+ const toastTextVariants = cva("text-body-small-regular", {
4908
+ variants: {
4909
+ type: {
4910
+ information: "text-white",
4911
+ promotional: "text-surface-ink-neutral-normal",
4912
+ },
4913
+ },
4914
+ defaultVariants: {
4915
+ type: "information",
4916
+ },
4917
+ });
4918
+ const toastLinkVariants = cva("text-body-small-medium cursor-pointer hover:underline", {
4919
+ variants: {
4920
+ type: {
4921
+ information: "text-white",
4922
+ promotional: "text-action-ink-primary-normal hover:text-action-ink-primary-subtle",
4923
+ },
4924
+ },
4925
+ defaultVariants: {
4926
+ type: "information",
4927
+ },
4928
+ });
4929
+ const toastCloseButtonVariants = cva("flex-shrink-0 cursor-pointer hover:opacity-75 transition-opacity", {
4930
+ variants: {
4931
+ type: {
4932
+ information: "text-white",
4933
+ promotional: "text-action-ink-neutral-subtle",
4934
+ },
4935
+ },
4936
+ defaultVariants: {
4937
+ type: "information",
4938
+ },
4939
+ });
4940
+ const getDefaultIcon = (type, intent) => {
4941
+ const iconSize = 16;
4942
+ if (type === "promotional") {
4943
+ return jsx(Icon, { name: "info", size: iconSize, "aria-hidden": "true" });
4944
+ }
4945
+ // Information type icons based on intent
4946
+ switch (intent) {
4947
+ case "positive":
4948
+ return jsx(Icon, { name: "check", size: iconSize, "aria-hidden": "true" });
4949
+ case "negative":
4950
+ return jsx(Icon, { name: "exclamation", size: iconSize, "aria-hidden": "true" });
4951
+ case "notice":
4952
+ return jsx(Icon, { name: "info", size: iconSize, "aria-hidden": "true" });
4953
+ case "info":
4954
+ return jsx(Icon, { name: "info", size: iconSize, "aria-hidden": "true" });
4955
+ case "neutral":
4956
+ default:
4957
+ return jsx(Icon, { name: "check", size: iconSize, "aria-hidden": "true" });
4958
+ }
4959
+ };
4960
+ const Toast = React.forwardRef(({ className, type = "information", intent = "neutral", icon, message, heading, description, linkText, onLinkClick, buttonText, onButtonClick, onClose, duration = 5000, isVisible = true, ...props }, ref) => {
4961
+ const [visible, setVisible] = React.useState(isVisible);
4962
+ const timerRef = React.useRef(null);
4963
+ React.useEffect(() => {
4964
+ setVisible(isVisible);
4965
+ }, [isVisible]);
4966
+ React.useEffect(() => {
4967
+ // Auto-dismiss only for information type
4968
+ if (type === "information" && visible && duration > 0) {
4969
+ timerRef.current = window.setTimeout(() => {
4970
+ setVisible(false);
4971
+ onClose?.();
4972
+ }, duration);
4973
+ }
4974
+ return () => {
4975
+ if (timerRef.current) {
4976
+ window.clearTimeout(timerRef.current);
4977
+ }
4978
+ };
4979
+ }, [type, visible, duration, onClose]);
4980
+ const handleClose = () => {
4981
+ setVisible(false);
4982
+ onClose?.();
4983
+ };
4984
+ const displayIcon = icon ?? getDefaultIcon(type, intent);
4985
+ if (!visible) {
4986
+ return null;
4987
+ }
4988
+ // Promotional type layout
4989
+ if (type === "promotional") {
4990
+ return (jsxs("div", { ref: ref, className: cn(toastVariants({ type, intent }), "flex-row items-start gap-3", className), role: "alert", ...props, children: [jsx("div", { className: "py-1", children: jsx("div", { className: cn(toastIconVariants({ type }), "h-5 w-5 shrink-0"), children: displayIcon }) }), jsxs("div", { className: "flex flex-col gap-3", children: [jsxs("div", { className: "flex flex-row items-center justify-between", children: [jsx("div", { className: "flex-1 min-w-0", children: heading && (jsx("div", { className: "text-body-small-semibold text-surface-ink-neutral-normal", children: heading })) }), onClose && (jsx("div", { className: cn(toastCloseButtonVariants({ type }), "h-5 w-5"), onClick: handleClose, role: "button", "aria-label": "Close toast", children: jsx(Icon, { name: "close", size: 16 }) }))] }), description && (jsx("div", { className: "text-body-small-regular text-surface-ink-neutral-subtle", children: description })), buttonText && (jsx("div", { children: jsx(Button, { variant: "secondary", color: "primary", size: "xsmall", onClick: onButtonClick, children: buttonText }) }))] })] }));
4991
+ }
4992
+ // Information type layout
4993
+ return (jsxs("div", { ref: ref, className: cn(toastVariants({ type, intent }), className), role: "alert", ...props, children: [jsx("div", { className: cn(toastIconVariants({ type }), "h-5 w-5 shrink-0"), children: displayIcon }), jsx("div", { className: cn(toastTextVariants({ type }), "flex-1 min-w-0"), children: message }), linkText && (jsx("div", { className: cn(toastLinkVariants({ type }), "shrink-0"), onClick: onLinkClick, role: "button", tabIndex: 0, onKeyDown: (e) => {
4994
+ if (e.key === "Enter" || e.key === " ") {
4995
+ e.preventDefault();
4996
+ onLinkClick?.();
4997
+ }
4998
+ }, children: linkText })), onClose && (jsx("div", { className: cn(toastCloseButtonVariants({ type }), "h-5 w-5"), onClick: handleClose, role: "button", "aria-label": "Close toast", tabIndex: 0, onKeyDown: (e) => {
4999
+ if (e.key === "Enter" || e.key === " ") {
5000
+ e.preventDefault();
5001
+ handleClose();
5002
+ }
5003
+ }, children: jsx(Icon, { name: "close", size: 16 }) }))] }));
5004
+ });
5005
+ Toast.displayName = "Toast";
5006
+
5007
+ const ToastContext = React.createContext(undefined);
5008
+ const positionClasses = {
5009
+ "top-left": "top-4 left-4",
5010
+ "top-center": "top-4 left-1/2 -translate-x-1/2",
5011
+ "top-right": "top-4 right-4",
5012
+ "bottom-left": "bottom-4 left-4",
5013
+ "bottom-center": "bottom-4 left-1/2 -translate-x-1/2",
5014
+ "bottom-right": "bottom-4 right-4",
5015
+ };
5016
+ const getDefaultPosition = (type) => {
5017
+ return type === "promotional" ? "bottom-right" : "bottom-center";
5018
+ };
5019
+ const getAnimationClasses = (position, isVisible) => {
5020
+ const isTop = position.startsWith("top");
5021
+ const isBottom = position.startsWith("bottom");
5022
+ if (!isVisible) {
5023
+ // Exit/hidden state - slide out
5024
+ if (isTop) {
5025
+ return "-translate-y-[120%] pointer-events-none";
5026
+ }
5027
+ if (isBottom) {
5028
+ return "translate-y-[120%] pointer-events-none";
5029
+ }
5030
+ // Fallback
5031
+ return "translate-y-[120%] pointer-events-none";
5032
+ }
5033
+ // Visible state - slide in
5034
+ return "translate-y-0";
5035
+ };
5036
+ const ToastProvider = ({ children, maxToasts = 5, defaultDuration = 5000, }) => {
5037
+ const [toasts, setToasts] = React.useState([]);
5038
+ const toastCounter = React.useRef(0);
5039
+ const generateId = () => {
5040
+ toastCounter.current += 1;
5041
+ return `toast-${Date.now()}-${toastCounter.current}`;
5042
+ };
5043
+ const showToast = React.useCallback((options) => {
5044
+ const id = options.id || generateId();
5045
+ const toastType = options.type || "information";
5046
+ const newToast = {
5047
+ ...options,
5048
+ id,
5049
+ isVisible: false, // Start hidden to trigger entry animation
5050
+ type: toastType,
5051
+ position: options.position || getDefaultPosition(toastType),
5052
+ duration: options.duration ??
5053
+ (toastType === "promotional" ? 0 : defaultDuration),
5054
+ };
5055
+ setToasts((prevToasts) => {
5056
+ const filtered = prevToasts.filter((t) => t.id !== id);
5057
+ const updated = [...filtered, newToast];
5058
+ // Keep only the most recent maxToasts
5059
+ return updated.slice(-maxToasts);
5060
+ });
5061
+ // Trigger entry animation after DOM update
5062
+ // Use setTimeout to ensure the initial hidden state is rendered first
5063
+ setTimeout(() => {
5064
+ setToasts((prevToasts) => prevToasts.map((toast) => toast.id === id ? { ...toast, isVisible: true } : toast));
5065
+ }, 10);
5066
+ return id;
5067
+ }, [maxToasts, defaultDuration]);
5068
+ const dismiss = React.useCallback((id) => {
5069
+ setToasts((prevToasts) => prevToasts.map((toast) => toast.id === id ? { ...toast, isVisible: false } : toast));
5070
+ // Remove toast after animation completes (500ms animation + 50ms buffer)
5071
+ setTimeout(() => {
5072
+ setToasts((prevToasts) => prevToasts.filter((toast) => toast.id !== id));
5073
+ }, 550);
5074
+ }, []);
5075
+ const dismissAll = React.useCallback(() => {
5076
+ setToasts((prevToasts) => prevToasts.map((toast) => ({ ...toast, isVisible: false })));
5077
+ // Remove all toasts after animation completes (500ms animation + 50ms buffer)
5078
+ setTimeout(() => {
5079
+ setToasts([]);
5080
+ }, 550);
5081
+ }, []);
5082
+ const success = React.useCallback((message, options) => {
5083
+ return showToast({
5084
+ type: "information",
5085
+ intent: "positive",
5086
+ message,
5087
+ ...options,
5088
+ });
5089
+ }, [showToast]);
5090
+ const error = React.useCallback((message, options) => {
5091
+ return showToast({
5092
+ type: "information",
5093
+ intent: "negative",
5094
+ message,
5095
+ ...options,
5096
+ });
5097
+ }, [showToast]);
5098
+ const warning = React.useCallback((message, options) => {
5099
+ return showToast({
5100
+ type: "information",
5101
+ intent: "notice",
5102
+ message,
5103
+ ...options,
5104
+ });
5105
+ }, [showToast]);
5106
+ const info = React.useCallback((message, options) => {
5107
+ return showToast({
5108
+ type: "information",
5109
+ intent: "info",
5110
+ message,
5111
+ ...options,
5112
+ });
5113
+ }, [showToast]);
5114
+ const promotional = React.useCallback((heading, description, options) => {
5115
+ return showToast({
5116
+ type: "promotional",
5117
+ heading,
5118
+ description,
5119
+ ...options,
5120
+ });
5121
+ }, [showToast]);
5122
+ const contextValue = React.useMemo(() => ({
5123
+ showToast,
5124
+ success,
5125
+ error,
5126
+ warning,
5127
+ info,
5128
+ promotional,
5129
+ dismiss,
5130
+ dismissAll,
5131
+ }), [showToast, success, error, warning, info, promotional, dismiss, dismissAll]);
5132
+ // Group toasts by position
5133
+ const toastsByPosition = React.useMemo(() => {
5134
+ const grouped = {};
5135
+ toasts.forEach((toast) => {
5136
+ const pos = toast.position || getDefaultPosition(toast.type);
5137
+ if (!grouped[pos]) {
5138
+ grouped[pos] = [];
5139
+ }
5140
+ grouped[pos].push(toast);
5141
+ });
5142
+ return grouped;
5143
+ }, [toasts]);
5144
+ return (jsxs(ToastContext.Provider, { value: contextValue, children: [children, Object.keys(toastsByPosition).map((position) => {
5145
+ const positionToasts = toastsByPosition[position];
5146
+ if (!positionToasts)
5147
+ return null;
5148
+ return (jsx("div", { className: `fixed z-50 flex flex-col gap-3 ${positionClasses[position]}`, "aria-live": "polite", "aria-atomic": "false", children: positionToasts.map((toast) => {
5149
+ const toastPosition = toast.position || getDefaultPosition(toast.type);
5150
+ const animationClasses = getAnimationClasses(toastPosition, toast.isVisible);
5151
+ return (jsx("div", { className: cn("will-change-transform transition-transform duration-200 ease-out", animationClasses), children: jsx(Toast, { ...toast, isVisible: toast.isVisible, onClose: () => {
5152
+ toast.onClose?.();
5153
+ dismiss(toast.id);
5154
+ } }) }, toast.id));
5155
+ }) }, position));
5156
+ })] }));
5157
+ };
5158
+ /**
5159
+ * Hook to access toast functionality
5160
+ *
5161
+ * @example
5162
+ * ```tsx
5163
+ * function MyComponent() {
5164
+ * const toast = useToast();
5165
+ *
5166
+ * return (
5167
+ * <button onClick={() => toast.success("Saved successfully!")}>
5168
+ * Save
5169
+ * </button>
5170
+ * );
5171
+ * }
5172
+ * ```
5173
+ */
5174
+ const useToast = () => {
5175
+ const context = React.useContext(ToastContext);
5176
+ if (!context) {
5177
+ throw new Error("useToast must be used within a ToastProvider");
5178
+ }
5179
+ return context;
5180
+ };
5181
+
4849
5182
  const uploadBoxVariants = cva("relative flex flex-col items-center justify-center border-2 border-dashed rounded-large transition-all font-display", {
4850
5183
  variants: {
4851
5184
  size: {
@@ -5197,5 +5530,5 @@ const UploadBox = React.forwardRef(({ label, helperText, errorText, successText,
5197
5530
  });
5198
5531
  UploadBox.displayName = "UploadBox";
5199
5532
 
5200
- 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, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants, uploadBoxVariants };
5533
+ 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, RadioGroup, SearchableDropdown, Select, SelectTextField, SidePanel, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Toast, ToastProvider, Tooltip, UploadBox, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, datePickerVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectTriggerVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants, uploadBoxVariants, useToast };
5201
5534
  //# sourceMappingURL=index.esm.js.map