@neoptocom/neopto-ui 0.8.0 → 0.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.
package/dist/index.cjs CHANGED
@@ -100,6 +100,53 @@ function AppBackground({
100
100
  )
101
101
  ] });
102
102
  }
103
+ function BackgroundBlur({
104
+ open,
105
+ children,
106
+ onClose,
107
+ zIndex = 40,
108
+ className = ""
109
+ }) {
110
+ const [shouldRender, setShouldRender] = React2.useState(false);
111
+ const [isVisible, setIsVisible] = React2.useState(false);
112
+ React2.useEffect(() => {
113
+ if (open) {
114
+ setShouldRender(true);
115
+ requestAnimationFrame(() => {
116
+ setIsVisible(true);
117
+ });
118
+ } else {
119
+ setIsVisible(false);
120
+ const timer = setTimeout(() => {
121
+ setShouldRender(false);
122
+ }, 500);
123
+ return () => clearTimeout(timer);
124
+ }
125
+ }, [open]);
126
+ if (!shouldRender) return null;
127
+ const handleBackdropClick = (e) => {
128
+ if (e.target === e.currentTarget && onClose) {
129
+ onClose();
130
+ }
131
+ };
132
+ return /* @__PURE__ */ jsxRuntime.jsx(
133
+ "div",
134
+ {
135
+ className: `fixed inset-0 flex items-center justify-center transition-opacity duration-500 ${className}`,
136
+ style: {
137
+ backgroundColor: "rgba(0, 0, 0, 0.10)",
138
+ backdropFilter: "blur(10px)",
139
+ WebkitBackdropFilter: "blur(10px)",
140
+ // Safari support
141
+ zIndex,
142
+ opacity: isVisible ? 1 : 0
143
+ },
144
+ onClick: handleBackdropClick,
145
+ role: "presentation",
146
+ children
147
+ }
148
+ );
149
+ }
103
150
  var Input = React2__namespace.forwardRef(
104
151
  ({ className, disabled, ...props }, ref) => {
105
152
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -891,6 +938,9 @@ function Chip({
891
938
  icon,
892
939
  className = "",
893
940
  label,
941
+ backgroundColor,
942
+ textColor,
943
+ style,
894
944
  ...props
895
945
  }) {
896
946
  const base = "inline-flex w-fit items-center justify-center gap-1 whitespace-nowrap overflow-hidden rounded-full h-6 px-2 text-xs font-semibold";
@@ -901,10 +951,25 @@ function Chip({
901
951
  light: "bg-[var(--muted)] text-[var(--fg)]",
902
952
  dark: "bg-[var(--surface)] text-[var(--fg)]"
903
953
  };
904
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [base, variantCls[variant], className].join(" "), ...props, children: [
905
- icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
906
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
907
- ] });
954
+ const hasCustomColors = backgroundColor || textColor;
955
+ const colorClasses = hasCustomColors ? "" : variantCls[variant];
956
+ const mergedStyle = {
957
+ ...style,
958
+ ...backgroundColor && { backgroundColor },
959
+ ...textColor && { color: textColor }
960
+ };
961
+ return /* @__PURE__ */ jsxRuntime.jsxs(
962
+ "div",
963
+ {
964
+ className: [base, colorClasses, className].join(" "),
965
+ style: mergedStyle,
966
+ ...props,
967
+ children: [
968
+ icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
969
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
970
+ ]
971
+ }
972
+ );
908
973
  }
909
974
  function Counter({
910
975
  value = 0,
@@ -1144,6 +1209,7 @@ exports.AppBackground = AppBackground;
1144
1209
  exports.Autocomplete = Autocomplete;
1145
1210
  exports.Avatar = Avatar;
1146
1211
  exports.AvatarGroup = AvatarGroup;
1212
+ exports.BackgroundBlur = BackgroundBlur;
1147
1213
  exports.Button = Button;
1148
1214
  exports.ChatButton = ChatButton_default;
1149
1215
  exports.Chip = Chip;
package/dist/index.d.cts CHANGED
@@ -26,6 +26,20 @@ type AppBackgroundProps = {
26
26
  };
27
27
  declare function AppBackground({ children, lightImage, darkImage, className, }: AppBackgroundProps): react_jsx_runtime.JSX.Element;
28
28
 
29
+ type BackgroundBlurProps = {
30
+ /** Whether the blur overlay is visible */
31
+ open: boolean;
32
+ /** Content to render on top of the blur (e.g., modal, drawer) */
33
+ children?: React.ReactNode;
34
+ /** Callback when the backdrop is clicked */
35
+ onClose?: () => void;
36
+ /** z-index for the overlay (default: 40) */
37
+ zIndex?: number;
38
+ /** Additional CSS classes */
39
+ className?: string;
40
+ };
41
+ declare function BackgroundBlur({ open, children, onClose, zIndex, className, }: BackgroundBlurProps): react_jsx_runtime.JSX.Element | null;
42
+
29
43
  type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>;
30
44
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
31
45
 
@@ -214,8 +228,12 @@ type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
214
228
  variant?: "warning" | "success" | "error" | "light" | "dark";
215
229
  icon?: string;
216
230
  label?: string;
231
+ /** Custom background color (overrides variant) */
232
+ backgroundColor?: string;
233
+ /** Custom text color (overrides variant) */
234
+ textColor?: string;
217
235
  };
218
- declare function Chip({ variant, icon, className, label, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
236
+ declare function Chip({ variant, icon, className, label, backgroundColor, textColor, style, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
219
237
 
220
238
  type CounterProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
221
239
  value?: number;
@@ -255,4 +273,4 @@ interface AnimatedBgRectangleProps {
255
273
  }
256
274
  declare const AnimatedBgRectangle: ({ colors, delay }: AnimatedBgRectangleProps) => react_jsx_runtime.JSX.Element;
257
275
 
258
- export { AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, ChatButton, type ChatButtonProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Skeleton, type SkeletonProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
276
+ export { AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Button, type ButtonProps, ChatButton, type ChatButtonProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Skeleton, type SkeletonProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
package/dist/index.d.ts CHANGED
@@ -26,6 +26,20 @@ type AppBackgroundProps = {
26
26
  };
27
27
  declare function AppBackground({ children, lightImage, darkImage, className, }: AppBackgroundProps): react_jsx_runtime.JSX.Element;
28
28
 
29
+ type BackgroundBlurProps = {
30
+ /** Whether the blur overlay is visible */
31
+ open: boolean;
32
+ /** Content to render on top of the blur (e.g., modal, drawer) */
33
+ children?: React.ReactNode;
34
+ /** Callback when the backdrop is clicked */
35
+ onClose?: () => void;
36
+ /** z-index for the overlay (default: 40) */
37
+ zIndex?: number;
38
+ /** Additional CSS classes */
39
+ className?: string;
40
+ };
41
+ declare function BackgroundBlur({ open, children, onClose, zIndex, className, }: BackgroundBlurProps): react_jsx_runtime.JSX.Element | null;
42
+
29
43
  type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'>;
30
44
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
31
45
 
@@ -214,8 +228,12 @@ type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
214
228
  variant?: "warning" | "success" | "error" | "light" | "dark";
215
229
  icon?: string;
216
230
  label?: string;
231
+ /** Custom background color (overrides variant) */
232
+ backgroundColor?: string;
233
+ /** Custom text color (overrides variant) */
234
+ textColor?: string;
217
235
  };
218
- declare function Chip({ variant, icon, className, label, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
236
+ declare function Chip({ variant, icon, className, label, backgroundColor, textColor, style, ...props }: ChipProps): react_jsx_runtime.JSX.Element;
219
237
 
220
238
  type CounterProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
221
239
  value?: number;
@@ -255,4 +273,4 @@ interface AnimatedBgRectangleProps {
255
273
  }
256
274
  declare const AnimatedBgRectangle: ({ colors, delay }: AnimatedBgRectangleProps) => react_jsx_runtime.JSX.Element;
257
275
 
258
- export { AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, ChatButton, type ChatButtonProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Skeleton, type SkeletonProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
276
+ export { AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Button, type ButtonProps, ChatButton, type ChatButtonProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Skeleton, type SkeletonProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React2 from 'react';
3
- import { useState, useMemo, useId, useRef, useCallback, useEffect } from 'react';
3
+ import { useState, useEffect, useMemo, useId, useRef, useCallback } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
 
6
6
  var __defProp = Object.defineProperty;
@@ -79,6 +79,53 @@ function AppBackground({
79
79
  )
80
80
  ] });
81
81
  }
82
+ function BackgroundBlur({
83
+ open,
84
+ children,
85
+ onClose,
86
+ zIndex = 40,
87
+ className = ""
88
+ }) {
89
+ const [shouldRender, setShouldRender] = useState(false);
90
+ const [isVisible, setIsVisible] = useState(false);
91
+ useEffect(() => {
92
+ if (open) {
93
+ setShouldRender(true);
94
+ requestAnimationFrame(() => {
95
+ setIsVisible(true);
96
+ });
97
+ } else {
98
+ setIsVisible(false);
99
+ const timer = setTimeout(() => {
100
+ setShouldRender(false);
101
+ }, 500);
102
+ return () => clearTimeout(timer);
103
+ }
104
+ }, [open]);
105
+ if (!shouldRender) return null;
106
+ const handleBackdropClick = (e) => {
107
+ if (e.target === e.currentTarget && onClose) {
108
+ onClose();
109
+ }
110
+ };
111
+ return /* @__PURE__ */ jsx(
112
+ "div",
113
+ {
114
+ className: `fixed inset-0 flex items-center justify-center transition-opacity duration-500 ${className}`,
115
+ style: {
116
+ backgroundColor: "rgba(0, 0, 0, 0.10)",
117
+ backdropFilter: "blur(10px)",
118
+ WebkitBackdropFilter: "blur(10px)",
119
+ // Safari support
120
+ zIndex,
121
+ opacity: isVisible ? 1 : 0
122
+ },
123
+ onClick: handleBackdropClick,
124
+ role: "presentation",
125
+ children
126
+ }
127
+ );
128
+ }
82
129
  var Input = React2.forwardRef(
83
130
  ({ className, disabled, ...props }, ref) => {
84
131
  return /* @__PURE__ */ jsx(
@@ -870,6 +917,9 @@ function Chip({
870
917
  icon,
871
918
  className = "",
872
919
  label,
920
+ backgroundColor,
921
+ textColor,
922
+ style,
873
923
  ...props
874
924
  }) {
875
925
  const base = "inline-flex w-fit items-center justify-center gap-1 whitespace-nowrap overflow-hidden rounded-full h-6 px-2 text-xs font-semibold";
@@ -880,10 +930,25 @@ function Chip({
880
930
  light: "bg-[var(--muted)] text-[var(--fg)]",
881
931
  dark: "bg-[var(--surface)] text-[var(--fg)]"
882
932
  };
883
- return /* @__PURE__ */ jsxs("div", { className: [base, variantCls[variant], className].join(" "), ...props, children: [
884
- icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
885
- /* @__PURE__ */ jsx("span", { children: label })
886
- ] });
933
+ const hasCustomColors = backgroundColor || textColor;
934
+ const colorClasses = hasCustomColors ? "" : variantCls[variant];
935
+ const mergedStyle = {
936
+ ...style,
937
+ ...backgroundColor && { backgroundColor },
938
+ ...textColor && { color: textColor }
939
+ };
940
+ return /* @__PURE__ */ jsxs(
941
+ "div",
942
+ {
943
+ className: [base, colorClasses, className].join(" "),
944
+ style: mergedStyle,
945
+ ...props,
946
+ children: [
947
+ icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm", className: "mr-0.5" }) : null,
948
+ /* @__PURE__ */ jsx("span", { children: label })
949
+ ]
950
+ }
951
+ );
887
952
  }
888
953
  function Counter({
889
954
  value = 0,
@@ -1117,4 +1182,4 @@ var ChatButton = ({
1117
1182
  };
1118
1183
  var ChatButton_default = ChatButton;
1119
1184
 
1120
- export { AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, Button, ChatButton_default as ChatButton, Chip, Counter, Icon, IconButton, Input, Modal, Search, Skeleton, Typo, assets_exports as assets };
1185
+ export { AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, BackgroundBlur, Button, ChatButton_default as ChatButton, Chip, Counter, Icon, IconButton, Input, Modal, Search, Skeleton, Typo, assets_exports as assets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoptocom/neopto-ui",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "private": false,
5
5
  "description": "A modern React component library built with Tailwind CSS v4 and TypeScript. Features dark mode, design tokens, and comprehensive Storybook documentation. Requires Tailwind v4+.",
6
6
  "keywords": [
@@ -0,0 +1,73 @@
1
+ import * as React from "react";
2
+ import { useEffect, useState } from "react";
3
+
4
+ export type BackgroundBlurProps = {
5
+ /** Whether the blur overlay is visible */
6
+ open: boolean;
7
+ /** Content to render on top of the blur (e.g., modal, drawer) */
8
+ children?: React.ReactNode;
9
+ /** Callback when the backdrop is clicked */
10
+ onClose?: () => void;
11
+ /** z-index for the overlay (default: 40) */
12
+ zIndex?: number;
13
+ /** Additional CSS classes */
14
+ className?: string;
15
+ };
16
+
17
+ export function BackgroundBlur({
18
+ open,
19
+ children,
20
+ onClose,
21
+ zIndex = 40,
22
+ className = "",
23
+ }: BackgroundBlurProps) {
24
+ const [shouldRender, setShouldRender] = useState(false);
25
+ const [isVisible, setIsVisible] = useState(false);
26
+
27
+ useEffect(() => {
28
+ if (open) {
29
+ // Mount the component
30
+ setShouldRender(true);
31
+ // Trigger fade-in on next frame
32
+ requestAnimationFrame(() => {
33
+ setIsVisible(true);
34
+ });
35
+ } else {
36
+ // Trigger fade-out
37
+ setIsVisible(false);
38
+ // Unmount after transition completes
39
+ const timer = setTimeout(() => {
40
+ setShouldRender(false);
41
+ }, 500); // Match transition duration
42
+ return () => clearTimeout(timer);
43
+ }
44
+ }, [open]);
45
+
46
+ // Don't render if not mounted
47
+ if (!shouldRender) return null;
48
+
49
+ const handleBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => {
50
+ // Only trigger onClose if clicking the backdrop itself, not children
51
+ if (e.target === e.currentTarget && onClose) {
52
+ onClose();
53
+ }
54
+ };
55
+
56
+ return (
57
+ <div
58
+ className={`fixed inset-0 flex items-center justify-center transition-opacity duration-500 ${className}`}
59
+ style={{
60
+ backgroundColor: "rgba(0, 0, 0, 0.10)",
61
+ backdropFilter: "blur(10px)",
62
+ WebkitBackdropFilter: "blur(10px)", // Safari support
63
+ zIndex,
64
+ opacity: isVisible ? 1 : 0,
65
+ }}
66
+ onClick={handleBackdropClick}
67
+ role="presentation"
68
+ >
69
+ {children}
70
+ </div>
71
+ );
72
+ }
73
+
@@ -5,6 +5,10 @@ export type ChipProps = React.HTMLAttributes<HTMLDivElement> & {
5
5
  variant?: "warning" | "success" | "error" | "light" | "dark";
6
6
  icon?: string;
7
7
  label?: string;
8
+ /** Custom background color (overrides variant) */
9
+ backgroundColor?: string;
10
+ /** Custom text color (overrides variant) */
11
+ textColor?: string;
8
12
  };
9
13
 
10
14
  export default function Chip({
@@ -12,13 +16,16 @@ export default function Chip({
12
16
  icon,
13
17
  className = "",
14
18
  label,
19
+ backgroundColor,
20
+ textColor,
21
+ style,
15
22
  ...props
16
23
  }: ChipProps) {
17
24
  const base =
18
25
  "inline-flex w-fit items-center justify-center gap-1 whitespace-nowrap overflow-hidden rounded-full h-6 px-2 " +
19
26
  "text-xs font-semibold";
20
27
 
21
- // Token-based backgrounds + readable text
28
+ // Token-based backgrounds + readable text (only used if no custom colors)
22
29
  const variantCls: Record<NonNullable<ChipProps["variant"]>, string> = {
23
30
  warning: "bg-[var(--warning)] text-white",
24
31
  success: "bg-[var(--success)] text-white",
@@ -27,8 +34,23 @@ export default function Chip({
27
34
  dark: "bg-[var(--surface)] text-[var(--fg)]"
28
35
  };
29
36
 
37
+ // Use custom colors if provided, otherwise use variant styles
38
+ const hasCustomColors = backgroundColor || textColor;
39
+ const colorClasses = hasCustomColors ? "" : variantCls[variant];
40
+
41
+ // Merge custom colors into style prop
42
+ const mergedStyle: React.CSSProperties = {
43
+ ...style,
44
+ ...(backgroundColor && { backgroundColor }),
45
+ ...(textColor && { color: textColor }),
46
+ };
47
+
30
48
  return (
31
- <div className={[base, variantCls[variant], className].join(" ")} {...props}>
49
+ <div
50
+ className={[base, colorClasses, className].join(" ")}
51
+ style={mergedStyle}
52
+ {...props}
53
+ >
32
54
  {icon ? <Icon name={icon} size="sm" className="mr-0.5" /> : null}
33
55
  <span>{label}</span>
34
56
  </div>
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export * as assets from "./assets";
3
3
 
4
4
  // Components
5
5
  export { AppBackground } from "./components/AppBackground";
6
+ export { BackgroundBlur } from "./components/BackgroundBlur";
6
7
  export * from "./components/Input";
7
8
  export * from "./components/Modal";
8
9
  export { default as Typo } from "./components/Typo";
@@ -20,6 +21,7 @@ export * from "./components/Chat";
20
21
 
21
22
  // Types
22
23
  export type { AppBackgroundProps } from "./components/AppBackground";
24
+ export type { BackgroundBlurProps } from "./components/BackgroundBlur";
23
25
  export type { InputProps } from "./components/Input";
24
26
  export type { ModalProps } from "./components/Modal";
25
27
  export type { TypoProps, TypoVariant, TypoWeight } from "./components/Typo";