@neoptocom/neopto-ui 0.9.5 → 0.9.7

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
@@ -166,10 +166,12 @@ function Card({
166
166
  transition: "background-color 0.3s ease, color 0.3s ease",
167
167
  ...style
168
168
  };
169
+ const hasPadding = className && /\b(p-|px-|py-|pt-|pb-|pl-|pr-)\d/.test(className);
170
+ const cardClasses = `${!hasPadding ? "p-6" : ""} ${className || ""}`.trim();
169
171
  return /* @__PURE__ */ jsxRuntime.jsxs(
170
172
  "div",
171
173
  {
172
- className: className || "p-6",
174
+ className: cardClasses,
173
175
  style: mergedStyle,
174
176
  ...props,
175
177
  children: [
@@ -258,7 +260,6 @@ function useIsomorphicLayoutEffect(effect, deps) {
258
260
  function Modal({
259
261
  open,
260
262
  onClose,
261
- title,
262
263
  closeOnBackdrop = true,
263
264
  children,
264
265
  className = "",
@@ -299,24 +300,22 @@ function Modal({
299
300
  return () => window.removeEventListener("keydown", onKey);
300
301
  }, [open, onClose]);
301
302
  if (!mounted) return null;
303
+ const hasMaxWidth = className?.includes("max-w-");
304
+ const modalClasses = `w-full ${!hasMaxWidth ? "max-w-lg" : ""} ${className || ""}`.trim();
302
305
  const modal = /* @__PURE__ */ jsxRuntime.jsx("div", { className: isDark ? "dark" : "", children: /* @__PURE__ */ jsxRuntime.jsx(
303
306
  BackgroundBlur,
304
307
  {
305
308
  open,
306
309
  onClose: closeOnBackdrop ? onClose : void 0,
307
310
  zIndex,
308
- children: /* @__PURE__ */ jsxRuntime.jsxs(
311
+ children: /* @__PURE__ */ jsxRuntime.jsx(
309
312
  Card,
310
313
  {
311
- className: `w-full ${className || "max-w-lg"}`,
314
+ className: modalClasses,
312
315
  role: "dialog",
313
316
  "aria-modal": "true",
314
- "aria-labelledby": title ? "modal-title" : void 0,
315
317
  showDecorations,
316
- children: [
317
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { id: "modal-title", className: "mb-4 text-xl font-semibold", children: title }),
318
- /* @__PURE__ */ jsxRuntime.jsx("div", { children })
319
- ]
318
+ children
320
319
  }
321
320
  )
322
321
  }
package/dist/index.d.cts CHANGED
@@ -60,8 +60,6 @@ type ModalProps = {
60
60
  onClose?: () => void;
61
61
  /** Modal content */
62
62
  children?: React.ReactNode;
63
- /** Optional title (rendered as heading) */
64
- title?: string;
65
63
  /** When true, closes when the backdrop is clicked (default: true) */
66
64
  closeOnBackdrop?: boolean;
67
65
  /** Custom className for the Card */
@@ -71,7 +69,7 @@ type ModalProps = {
71
69
  /** Show decorative elements on the Card (default: true) */
72
70
  showDecorations?: boolean;
73
71
  };
74
- declare function Modal({ open, onClose, title, closeOnBackdrop, children, className, zIndex, showDecorations, }: ModalProps): React.ReactPortal | null;
72
+ declare function Modal({ open, onClose, closeOnBackdrop, children, className, zIndex, showDecorations, }: ModalProps): React.ReactPortal | null;
75
73
 
76
74
  type TypoVariant = "display-lg" | "display-md" | "display-sm" | "headline-lg" | "headline-md" | "headline-sm" | "title-lg" | "title-md" | "title-sm" | "label-lg" | "label-md" | "label-sm" | "body-lg" | "body-md" | "body-sm" | "button";
77
75
  type TypoWeight = "normal" | "medium" | "semibold" | "bold";
package/dist/index.d.ts CHANGED
@@ -60,8 +60,6 @@ type ModalProps = {
60
60
  onClose?: () => void;
61
61
  /** Modal content */
62
62
  children?: React.ReactNode;
63
- /** Optional title (rendered as heading) */
64
- title?: string;
65
63
  /** When true, closes when the backdrop is clicked (default: true) */
66
64
  closeOnBackdrop?: boolean;
67
65
  /** Custom className for the Card */
@@ -71,7 +69,7 @@ type ModalProps = {
71
69
  /** Show decorative elements on the Card (default: true) */
72
70
  showDecorations?: boolean;
73
71
  };
74
- declare function Modal({ open, onClose, title, closeOnBackdrop, children, className, zIndex, showDecorations, }: ModalProps): React.ReactPortal | null;
72
+ declare function Modal({ open, onClose, closeOnBackdrop, children, className, zIndex, showDecorations, }: ModalProps): React.ReactPortal | null;
75
73
 
76
74
  type TypoVariant = "display-lg" | "display-md" | "display-sm" | "headline-lg" | "headline-md" | "headline-sm" | "title-lg" | "title-md" | "title-sm" | "label-lg" | "label-md" | "label-sm" | "body-lg" | "body-md" | "body-sm" | "button";
77
75
  type TypoWeight = "normal" | "medium" | "semibold" | "bold";
package/dist/index.js CHANGED
@@ -145,10 +145,12 @@ function Card({
145
145
  transition: "background-color 0.3s ease, color 0.3s ease",
146
146
  ...style
147
147
  };
148
+ const hasPadding = className && /\b(p-|px-|py-|pt-|pb-|pl-|pr-)\d/.test(className);
149
+ const cardClasses = `${!hasPadding ? "p-6" : ""} ${className || ""}`.trim();
148
150
  return /* @__PURE__ */ jsxs(
149
151
  "div",
150
152
  {
151
- className: className || "p-6",
153
+ className: cardClasses,
152
154
  style: mergedStyle,
153
155
  ...props,
154
156
  children: [
@@ -237,7 +239,6 @@ function useIsomorphicLayoutEffect(effect, deps) {
237
239
  function Modal({
238
240
  open,
239
241
  onClose,
240
- title,
241
242
  closeOnBackdrop = true,
242
243
  children,
243
244
  className = "",
@@ -278,24 +279,22 @@ function Modal({
278
279
  return () => window.removeEventListener("keydown", onKey);
279
280
  }, [open, onClose]);
280
281
  if (!mounted) return null;
282
+ const hasMaxWidth = className?.includes("max-w-");
283
+ const modalClasses = `w-full ${!hasMaxWidth ? "max-w-lg" : ""} ${className || ""}`.trim();
281
284
  const modal = /* @__PURE__ */ jsx("div", { className: isDark ? "dark" : "", children: /* @__PURE__ */ jsx(
282
285
  BackgroundBlur,
283
286
  {
284
287
  open,
285
288
  onClose: closeOnBackdrop ? onClose : void 0,
286
289
  zIndex,
287
- children: /* @__PURE__ */ jsxs(
290
+ children: /* @__PURE__ */ jsx(
288
291
  Card,
289
292
  {
290
- className: `w-full ${className || "max-w-lg"}`,
293
+ className: modalClasses,
291
294
  role: "dialog",
292
295
  "aria-modal": "true",
293
- "aria-labelledby": title ? "modal-title" : void 0,
294
296
  showDecorations,
295
- children: [
296
- title && /* @__PURE__ */ jsx("h2", { id: "modal-title", className: "mb-4 text-xl font-semibold", children: title }),
297
- /* @__PURE__ */ jsx("div", { children })
298
- ]
297
+ children
299
298
  }
300
299
  )
301
300
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoptocom/neopto-ui",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
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": [
@@ -29,9 +29,13 @@ export function Card({
29
29
  ...style,
30
30
  };
31
31
 
32
+ // Smart class merging: only add default padding if not provided
33
+ const hasPadding = className && /\b(p-|px-|py-|pt-|pb-|pl-|pr-)\d/.test(className);
34
+ const cardClasses = `${!hasPadding ? "p-6" : ""} ${className || ""}`.trim();
35
+
32
36
  return (
33
37
  <div
34
- className={className || "p-6"}
38
+ className={cardClasses}
35
39
  style={mergedStyle}
36
40
  {...props}
37
41
  >
@@ -10,8 +10,6 @@ export type ModalProps = {
10
10
  onClose?: () => void;
11
11
  /** Modal content */
12
12
  children?: React.ReactNode;
13
- /** Optional title (rendered as heading) */
14
- title?: string;
15
13
  /** When true, closes when the backdrop is clicked (default: true) */
16
14
  closeOnBackdrop?: boolean;
17
15
  /** Custom className for the Card */
@@ -30,7 +28,6 @@ function useIsomorphicLayoutEffect(effect: React.EffectCallback, deps?: React.De
30
28
  export function Modal({
31
29
  open,
32
30
  onClose,
33
- title,
34
31
  closeOnBackdrop = true,
35
32
  children,
36
33
  className = "",
@@ -85,6 +82,10 @@ export function Modal({
85
82
 
86
83
  if (!mounted) return null;
87
84
 
85
+ // Smart class merging: only add defaults if not provided
86
+ const hasMaxWidth = className?.includes("max-w-");
87
+ const modalClasses = `w-full ${!hasMaxWidth ? "max-w-lg" : ""} ${className || ""}`.trim();
88
+
88
89
  const modal = (
89
90
  <div className={isDark ? "dark" : ""}>
90
91
  <BackgroundBlur
@@ -93,18 +94,12 @@ export function Modal({
93
94
  zIndex={zIndex}
94
95
  >
95
96
  <Card
96
- className={`w-full ${className || "max-w-lg"}`}
97
+ className={modalClasses}
97
98
  role="dialog"
98
99
  aria-modal="true"
99
- aria-labelledby={title ? "modal-title" : undefined}
100
100
  showDecorations={showDecorations}
101
101
  >
102
- {title && (
103
- <h2 id="modal-title" className="mb-4 text-xl font-semibold">
104
- {title}
105
- </h2>
106
- )}
107
- <div>{children}</div>
102
+ {children}
108
103
  </Card>
109
104
  </BackgroundBlur>
110
105
  </div>
@@ -42,27 +42,14 @@ export const Default: Story = {
42
42
  ),
43
43
  };
44
44
 
45
- export const WithTitle: Story = {
46
- args: { open: false },
47
- render: () => (
48
- <ModalDemo title="Modal Title">
49
- <Typo variant="body-md">
50
- This modal includes a title heading. You can still add any content you want below it.
51
- </Typo>
52
- <Typo variant="body-sm" className="mt-4 text-[var(--muted-fg)]">
53
- Try clicking the backdrop to close, or press ESC.
54
- </Typo>
55
- </ModalDemo>
56
- ),
57
- };
58
45
 
59
46
  export const NoBackdropClose: Story = {
60
47
  args: { open: false },
61
48
  render: () => (
62
49
  <ModalDemo
63
- title="Important Notice"
64
50
  closeOnBackdrop={false}
65
51
  >
52
+ <Typo variant="headline-md" bold="semibold" className="mb-4">Important Notice</Typo>
66
53
  <Typo variant="body-md">
67
54
  This modal cannot be closed by clicking the backdrop.
68
55
  </Typo>
@@ -80,9 +67,9 @@ export const CustomStyling: Story = {
80
67
  args: { open: false },
81
68
  render: () => (
82
69
  <ModalDemo
83
- title="Large Modal"
84
70
  className="max-w-2xl p-12"
85
71
  >
72
+ <Typo variant="headline-md" bold="semibold" className="mb-4">Large Modal</Typo>
86
73
  <Typo variant="body-md">
87
74
  This modal has custom styling with a larger max-width and more padding.
88
75
  </Typo>
@@ -119,9 +106,9 @@ export const FormModal: Story = {
119
106
  <Modal
120
107
  open={open}
121
108
  onClose={() => setOpen(false)}
122
- title="Contact Form"
123
109
  >
124
110
  <form onSubmit={handleSubmit}>
111
+ <Typo variant="headline-md" bold="semibold" className="mb-4">Contact Form</Typo>
125
112
  <div className="space-y-4">
126
113
  <div>
127
114
  <label className="block mb-2 text-sm font-medium">Name</label>
@@ -181,9 +168,9 @@ export const ConfirmationDialog: Story = {
181
168
  <Modal
182
169
  open={open}
183
170
  onClose={() => setOpen(false)}
184
- title="Confirm Deletion"
185
171
  closeOnBackdrop={false}
186
172
  >
173
+ <Typo variant="headline-md" bold="semibold" className="mb-4">Confirm Deletion</Typo>
187
174
  <Typo variant="body-md">
188
175
  Are you sure you want to delete this item? This action cannot be undone.
189
176
  </Typo>
@@ -242,7 +229,8 @@ export const WithCardDecorations: Story = {
242
229
  );
243
230
 
244
231
  return (
245
- <ModalDemo title="Card with Decorative Elements">
232
+ <ModalDemo>
233
+ <Typo variant="headline-md" bold="semibold" className="mb-4">Card with Decorative Elements</Typo>
246
234
  <div className="space-y-4">
247
235
  <Typo variant="body-md">
248
236
  The Card component now includes decorative SVG elements from your Figma design: