meticulous-ui 3.5.2 → 3.5.4

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
@@ -58,29 +58,29 @@ import blue from 'meticulous-ui/colors/blue';
58
58
 
59
59
  ## 📦 Components
60
60
 
61
- | Component | Description |
62
- | --------------- | -------------------------------------------------------------------------------------- |
63
- | `Pagination` | Fully responsive pagination component |
64
- | `Toast` | Push 4 types of notifications on screen |
65
- | `Timer` | Renders analog / digital clock with alarm |
66
- | `OtpInput` | Gives inputs to enter and edit OTP |
67
- | `VideoPlayer` | Renders video with keyboard shortcuts |
68
- | `Image` | Renders image with shimmer, lower resolution |
69
- | `Input` | Renders input box to let user enter input |
70
- | `Checkbox` | Renders checkbox to let user give boolean value |
71
- | `RadioGroup` | Renders radio options in a group to let user select |
72
- | `FileUploader` | Renders a button type input from where user can upload |
73
- | `Textarea` | Renders textarea box to let user enter description |
74
- | `Dropdown` | Renders dropdown to select from options |
75
- | `SelectBox` | Renders selectbox to select multiple values from options |
76
- | `Spinner` | Renders a spinner to show the loading state |
77
- | `Loader` | Renders a loader with dots to show the loading state |
78
- | `PageLoader` | Renders a loader with line at the top of page |
79
- | `Button` | Renders a button to click & take an action |
80
- | `Shimmer` | Animated skeleton loading placeholder |
81
- | `Carousel` | Carousel providing slider between components displaying slides |
82
- | `Modal` | Accessible dialog overlay with title, body, footer, and Escape/overlay-click dismissal |
83
- | `RootComponent` | This is the required wrapper for any app that uses meticulous-ui |
61
+ | Component | Description |
62
+ | --------------- | ---------------------------------------------------------------------------------------------------------------- |
63
+ | `Pagination` | Fully responsive pagination component |
64
+ | `Toast` | Push 4 types of notifications on screen |
65
+ | `Timer` | Renders analog / digital clock with alarm |
66
+ | `OtpInput` | Gives inputs to enter and edit OTP |
67
+ | `VideoPlayer` | Renders video with keyboard shortcuts |
68
+ | `Image` | Renders image with shimmer, lower resolution |
69
+ | `Input` | Renders input box to let user enter input |
70
+ | `Checkbox` | Renders checkbox to let user give boolean value |
71
+ | `RadioGroup` | Renders radio options in a group to let user select |
72
+ | `FileUploader` | Renders a button type input from where user can upload |
73
+ | `Textarea` | Renders textarea box to let user enter description |
74
+ | `Dropdown` | Renders dropdown to select from options |
75
+ | `SelectBox` | Renders selectbox to select multiple values from options |
76
+ | `Spinner` | Renders a spinner to show the loading state |
77
+ | `Loader` | Renders a loader with dots to show the loading state |
78
+ | `PageLoader` | Renders a loader with line at the top of page |
79
+ | `Button` | Renders a button to click & take an action |
80
+ | `Shimmer` | Animated skeleton loading placeholder |
81
+ | `Carousel` | Carousel providing slider between components displaying slides |
82
+ | `Modal` | Accessible dialog overlay with title, body, footer, Escape/overlay-click dismissal, and mobile bottom-sheet mode |
83
+ | `RootComponent` | This is the required wrapper for any app that uses meticulous-ui |
84
84
 
85
85
  ## 📦 Icon Components
86
86
 
@@ -1,56 +1,52 @@
1
- import { jsx as o } from "react/jsx-runtime";
1
+ import { jsxs as D, jsx as o } from "react/jsx-runtime";
2
2
  import { useRef as v } from "react";
3
- import x from "../Spinner/Spinner.js";
3
+ import L from "../Spinner/Spinner.js";
4
4
  import I from "../../colors/colorMap.js";
5
5
  import { blue as f } from "../../colors/blue.js";
6
6
  import { ButtonWrapper as K, SpinnerWrapper as R, Content as B, ButtonContainer as E } from "./styles.js";
7
- import L from "../Ripple/Ripple.js";
8
- import S from "../../colors/white.js";
7
+ import S from "../Ripple/Ripple.js";
8
+ import j from "../../colors/white.js";
9
9
  import k from "../../colors/grey.js";
10
10
  import { MEDIUM as z, SIZE as M } from "./constants.js";
11
- const P = ({ theme: t, children: n }) => /* @__PURE__ */ o(L, { rippleColor: t.m100, children: n }), Q = (t) => {
11
+ const P = ({ theme: t, children: i }) => /* @__PURE__ */ o(S, { rippleColor: t.m100, children: i }), T = (t) => {
12
12
  const {
13
- children: n,
14
- theme: i = f,
13
+ children: i,
14
+ theme: n = f,
15
15
  size: u = z,
16
16
  width: l,
17
17
  leftIcon: W,
18
- rightIcon: j,
19
- isLoading: r,
18
+ rightIcon: U,
19
+ isLoading: e,
20
20
  textColor: s,
21
21
  onKeyDown: w,
22
22
  ...C
23
- } = t || {}, d = v(0), $ = (e) => {
24
- if (e.key === "Enter" || e.key === " ") {
25
- const a = Date.now();
26
- if (a - d.current < 500) {
27
- e.preventDefault(), e.stopPropagation();
23
+ } = t || {}, d = v(0), $ = (r) => {
24
+ if (r.key === "Enter" || r.key === " ") {
25
+ const h = Date.now();
26
+ if (h - d.current < 500) {
27
+ r.preventDefault(), r.stopPropagation();
28
28
  return;
29
29
  }
30
- d.current = a;
30
+ d.current = h;
31
31
  }
32
- w?.(e);
33
- }, { m400: y, m500: g, m600: b } = I[i] ?? f, { height: m, width: c, font: D } = M[u] || {}, p = ["white", "yellow"].includes(i) ? k.m600 : S, h = /* @__PURE__ */ o(
32
+ w?.(r);
33
+ }, { m400: g, m500: y, m600: b } = I[n] ?? f, { height: m, width: c, font: x } = M[u] || {}, a = ["white", "yellow"].includes(n) ? k.m600 : j, p = /* @__PURE__ */ D(
34
34
  K,
35
35
  {
36
36
  type: "button",
37
37
  ...C,
38
38
  onKeyDown: $,
39
- $hoverColor: g,
39
+ $hoverColor: y,
40
40
  $activeColor: b,
41
- $selectedColor: y,
41
+ $selectedColor: g,
42
42
  $height: m,
43
43
  $width: l || c,
44
44
  disabled: t.disabled,
45
- $isLoading: r,
46
- children: r ? /* @__PURE__ */ o(R, { children: /* @__PURE__ */ o(x, { size: "small", color: s || p }) }) : /* @__PURE__ */ o(
47
- B,
48
- {
49
- $textColor: s || p,
50
- $font: D,
51
- children: n
52
- }
53
- )
45
+ $isLoading: e,
46
+ children: [
47
+ /* @__PURE__ */ o(R, { $isLoading: e, children: /* @__PURE__ */ o(L, { size: "small", color: s || a }) }),
48
+ /* @__PURE__ */ o(B, { $isLoading: e, $textColor: s || a, $font: x, children: i })
49
+ ]
54
50
  }
55
51
  );
56
52
  return /* @__PURE__ */ o(
@@ -59,11 +55,11 @@ const P = ({ theme: t, children: n }) => /* @__PURE__ */ o(L, { rippleColor: t.m
59
55
  $height: m,
60
56
  $width: l || c,
61
57
  disabled: t.disabled,
62
- $isLoading: r,
63
- children: r ? h : /* @__PURE__ */ o(P, { theme: i, children: h })
58
+ $isLoading: e,
59
+ children: e ? p : /* @__PURE__ */ o(P, { theme: n, children: p })
64
60
  }
65
61
  );
66
62
  };
67
63
  export {
68
- Q as default
64
+ T as default
69
65
  };
@@ -1,19 +1,21 @@
1
- import e, { css as n } from "styled-components";
1
+ import r, { css as n } from "styled-components";
2
2
  import i from "../../colors/grey.js";
3
- const d = e.button`
3
+ const d = r.button`
4
4
  height: ${({ $height: o }) => o}rem;
5
5
  width: ${({ $width: o }) => o}rem;
6
6
  border-radius: 0.96rem;
7
7
  border: none;
8
8
  padding: 0.96rem 0.64rem;
9
- background-color: ${({ $selectedColor: o, disabled: r }) => r ? i.m500 : o};
10
- cursor: ${({ disabled: o, $isLoading: r }) => o ? "not-allowed" : r ? "auto" : "pointer"};
9
+ position: relative;
10
+ overflow: hidden;
11
+ background-color: ${({ $selectedColor: o, disabled: e }) => e ? i.m500 : o};
12
+ cursor: ${({ disabled: o, $isLoading: e }) => o ? "not-allowed" : e ? "auto" : "pointer"};
11
13
 
12
14
  ${({ $isLoading: o }) => o && n`
13
15
  pointer-events: none;
14
16
  `};
15
17
 
16
- ${({ disabled: o, $isLoading: r }) => !(o || r) && n`
18
+ ${({ disabled: o, $isLoading: e }) => !(o || e) && n`
17
19
  &:hover {
18
20
  background-color: ${({ $hoverColor: t }) => t};
19
21
  }
@@ -26,20 +28,22 @@ const d = e.button`
26
28
  &:focus-visible {
27
29
  outline: none;
28
30
  }
29
- `, m = e.div`
31
+ `, c = r.div`
30
32
  font-size: ${({ $font: o }) => o}rem;
31
33
  font-weight: 500;
32
34
  max-width: 100%;
33
35
  overflow: hidden;
34
36
  color: ${({ $textColor: o }) => o};
35
- `, c = e.div`
37
+ opacity: ${({ $isLoading: o }) => o ? 0 : 1};
38
+ transition: opacity 0.3s ease;
39
+ `, m = r.div`
36
40
  height: ${({ $height: o }) => o}rem;
37
41
  width: ${({ $width: o }) => o}rem;
38
42
  display: inline-block;
39
43
  position: relative;
40
44
  border-radius: 0.96rem;
41
45
 
42
- ${({ disabled: o, $isLoading: r }) => !(o || r) && n`
46
+ ${({ disabled: o, $isLoading: e }) => !(o || e) && n`
43
47
  box-shadow: 0 0.4rem 1.5rem rgba(0, 0, 0, 0.2);
44
48
  transition:
45
49
  transform 0.2s,
@@ -51,15 +55,19 @@ const d = e.button`
51
55
  transform: translateY(-2px);
52
56
  }
53
57
  `};
54
- `, l = e.div`
55
- width: 100%;
58
+ `, p = r.div`
59
+ position: absolute;
60
+ inset: 0;
56
61
  display: flex;
57
- flex-direction: column;
58
62
  align-items: center;
63
+ justify-content: center;
64
+ opacity: ${({ $isLoading: o }) => o ? 1 : 0};
65
+ transition: opacity 0.3s ease;
66
+ pointer-events: none;
59
67
  `;
60
68
  export {
61
- c as ButtonContainer,
69
+ m as ButtonContainer,
62
70
  d as ButtonWrapper,
63
- m as Content,
64
- l as SpinnerWrapper
71
+ c as Content,
72
+ p as SpinnerWrapper
65
73
  };
@@ -1,12 +1,12 @@
1
1
  import { jsxs as I, jsx as r } from "react/jsx-runtime";
2
2
  import { useState as a, useRef as T, useEffect as C } from "react";
3
- import { Wrapper as ue, SlideArea as de, NavButton as K, SlideViewport as he, SlideTrack as fe, PauseButton as me, ProgressBar as pe, DotsWrapper as ve, Dot as ge } from "./styles.js";
4
- import we from "../Icons/ChevronLeft/ChevronLeft.js";
5
- import $e from "../Icons/ChevronRight/ChevronRight.js";
6
- const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height: 12, viewBox: "0 0 12 12", fill: "currentColor", "aria-hidden": "true", children: [
3
+ import { Wrapper as de, SlideArea as he, NavButton as K, SlideViewport as fe, SlideTrack as me, PauseButton as pe, ProgressBar as ve, DotsWrapper as ge, Dot as we } from "./styles.js";
4
+ import $e from "../Icons/ChevronLeft/ChevronLeft.js";
5
+ import Me from "../Icons/ChevronRight/ChevronRight.js";
6
+ const E = 50, O = 2e3, be = () => /* @__PURE__ */ I("svg", { width: 12, height: 12, viewBox: "0 0 12 12", fill: "currentColor", "aria-hidden": "true", children: [
7
7
  /* @__PURE__ */ r("rect", { x: "2", y: "1", width: "3", height: "10", rx: "1" }),
8
8
  /* @__PURE__ */ r("rect", { x: "7", y: "1", width: "3", height: "10", rx: "1" })
9
- ] }), be = () => /* @__PURE__ */ r("svg", { width: 12, height: 12, viewBox: "0 0 12 12", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ r("path", { d: "M2 1.5l9 4.5-9 4.5V1.5z" }) }), Xe = ({
9
+ ] }), xe = () => /* @__PURE__ */ r("svg", { width: 12, height: 12, viewBox: "0 0 12 12", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ r("path", { d: "M2 1.5l9 4.5-9 4.5V1.5z" }) }), ke = ({
10
10
  data: R,
11
11
  renderCarousel: N,
12
12
  visibleSlides: X = 1,
@@ -22,13 +22,14 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
22
22
  liveDragMobile: L = !0,
23
23
  showProgress: A = !1,
24
24
  defaultIndex: Y = 0,
25
- onSlideChange: G
25
+ onSlideChange: G,
26
+ ...J
26
27
  }) => {
27
- const [n, M] = a(Y), [B, d] = a(!0), [V, W] = a(!1), [h, f] = a(!1), [J, m] = a(0), [F, p] = a(!1), [y, _] = a(!1), c = T(null), o = T(null), l = T(null), z = T(null);
28
+ const [n, M] = a(Y), [B, d] = a(!0), [V, W] = a(!1), [h, f] = a(!1), [Q, m] = a(0), [F, p] = a(!1), [y, _] = a(!1), c = T(null), o = T(null), l = T(null), z = T(null);
28
29
  C(() => {
29
30
  const e = window.matchMedia("(max-width: 1024px)");
30
31
  _(e.matches);
31
- const t = (le) => _(le.matches);
32
+ const t = (ue) => _(ue.matches);
32
33
  return e.addEventListener("change", t), () => e.removeEventListener("change", t);
33
34
  }, []);
34
35
  const s = R.length - X, b = () => M((e) => u && e === 0 ? s : Math.max(e - 1, 0)), x = () => M((e) => u && e >= s ? 0 : Math.min(e + 1, s));
@@ -37,9 +38,9 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
37
38
  }, [n]);
38
39
  const H = () => {
39
40
  i && (clearTimeout(l.current), d(!0), l.current = setTimeout(() => d(!1), O));
40
- }, Q = () => {
41
- f(!0), i && (clearTimeout(l.current), d(!0));
42
41
  }, Z = () => {
42
+ f(!0), i && (clearTimeout(l.current), d(!0));
43
+ }, ee = () => {
43
44
  f(!1), i && (l.current = setTimeout(() => d(!1), O));
44
45
  };
45
46
  C(() => {
@@ -52,44 +53,45 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
52
53
  }, k * 1e3);
53
54
  return () => clearInterval(e);
54
55
  }, [g, k, h, s]);
55
- const S = (e) => u ? e : n === 0 && e > 0 || n === s && e < 0 ? e * 0.3 : e, ee = (e) => {
56
+ const S = (e) => u ? e : n === 0 && e > 0 || n === s && e < 0 ? e * 0.3 : e, te = (e) => {
56
57
  c.current = e.touches[0].clientX, L && y && p(!0), H();
57
- }, te = (e) => {
58
- !L || !y || c.current === null || m(S(e.touches[0].clientX - c.current));
59
58
  }, re = (e) => {
59
+ !L || !y || c.current === null || m(S(e.touches[0].clientX - c.current));
60
+ }, ne = (e) => {
60
61
  if (L && y && (p(!1), m(0)), c.current === null) return;
61
62
  const t = c.current - e.changedTouches[0].clientX;
62
63
  t > E ? x() : t < -E && b(), c.current = null;
63
- }, ne = (e) => {
64
- w && (o.current = e.clientX, $ && p(!0));
65
64
  }, se = (e) => {
66
- !w || !$ || o.current === null || m(S(e.clientX - o.current));
65
+ w && (o.current = e.clientX, $ && p(!0));
67
66
  }, ie = (e) => {
67
+ !w || !$ || o.current === null || m(S(e.clientX - o.current));
68
+ }, oe = (e) => {
68
69
  if (!w || o.current === null) return;
69
70
  $ && (p(!1), m(0));
70
71
  const t = o.current - e.clientX;
71
72
  t > E ? x() : t < -E && b(), o.current = null;
72
- }, oe = (e) => {
73
+ }, ae = (e) => {
73
74
  e.key === "ArrowLeft" ? (e.preventDefault(), b()) : e.key === "ArrowRight" && (e.preventDefault(), x());
74
- }, U = z.current?.clientWidth ?? 0, ae = U > 0 ? J / U * 100 : 0, ce = -(n * (100 / X)) + ae, j = v !== void 0 ? typeof v == "number" ? `${v}px` : v : void 0, D = s + 1;
75
+ }, U = z.current?.clientWidth ?? 0, ce = U > 0 ? Q / U * 100 : 0, le = -(n * (100 / X)) + ce, j = v !== void 0 ? typeof v == "number" ? `${v}px` : v : void 0, D = s + 1;
75
76
  return /* @__PURE__ */ I(
76
- ue,
77
+ de,
77
78
  {
78
79
  onClick: H,
79
- onMouseEnter: Q,
80
- onMouseLeave: Z,
81
- onMouseMove: se,
82
- onMouseUp: ie,
83
- onKeyDown: oe,
80
+ onMouseEnter: Z,
81
+ onMouseLeave: ee,
82
+ onMouseMove: ie,
83
+ onMouseUp: oe,
84
+ onKeyDown: ae,
84
85
  role: "region",
85
86
  "aria-label": "Carousel",
87
+ ...J,
86
88
  children: [
87
89
  /* @__PURE__ */ I(
88
- de,
90
+ he,
89
91
  {
90
- onTouchStart: ee,
91
- onTouchMove: te,
92
- onTouchEnd: re,
92
+ onTouchStart: te,
93
+ onTouchMove: re,
94
+ onTouchEnd: ne,
93
95
  children: [
94
96
  P && /* @__PURE__ */ r(
95
97
  K,
@@ -102,11 +104,11 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
102
104
  $visible: B,
103
105
  $arrowTop: j,
104
106
  $viewportFocused: V,
105
- children: /* @__PURE__ */ r(we, { size: 20, "aria-hidden": "true" })
107
+ children: /* @__PURE__ */ r($e, { size: 20, "aria-hidden": "true" })
106
108
  }
107
109
  ),
108
110
  /* @__PURE__ */ r(
109
- he,
111
+ fe,
110
112
  {
111
113
  ref: z,
112
114
  tabIndex: 0,
@@ -118,11 +120,11 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
118
120
  onBlur: () => {
119
121
  W(!1), f(!1);
120
122
  },
121
- onMouseDown: ne,
123
+ onMouseDown: se,
122
124
  onMouseLeave: (e) => {
123
125
  e.buttons !== 1 && ($ && F && (p(!1), m(0)), o.current = null);
124
126
  },
125
- children: /* @__PURE__ */ r(fe, { $translateX: ce, $visibleSlides: X, $dragging: F, children: R.map(N) })
127
+ children: /* @__PURE__ */ r(me, { $translateX: le, $visibleSlides: X, $dragging: F, children: R.map(N) })
126
128
  }
127
129
  ),
128
130
  P && /* @__PURE__ */ r(
@@ -136,15 +138,15 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
136
138
  $visible: B,
137
139
  $arrowTop: j,
138
140
  $viewportFocused: V,
139
- children: /* @__PURE__ */ r($e, { size: 20, "aria-hidden": "true" })
141
+ children: /* @__PURE__ */ r(Me, { size: 20, "aria-hidden": "true" })
140
142
  }
141
143
  ),
142
144
  g && /* @__PURE__ */ r(
143
- me,
145
+ pe,
144
146
  {
145
147
  onClick: () => f((e) => !e),
146
148
  "aria-label": h ? "Play slideshow" : "Pause slideshow",
147
- children: h ? /* @__PURE__ */ r(be, {}) : /* @__PURE__ */ r(Me, {})
149
+ children: h ? /* @__PURE__ */ r(xe, {}) : /* @__PURE__ */ r(be, {})
148
150
  }
149
151
  )
150
152
  ]
@@ -171,9 +173,9 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
171
173
  ]
172
174
  }
173
175
  ),
174
- g && A && /* @__PURE__ */ r(pe, { $duration: k, $paused: h }, n),
175
- !q && /* @__PURE__ */ r(ve, { children: Array.from({ length: D }).map((e, t) => /* @__PURE__ */ r(
176
- ge,
176
+ g && A && /* @__PURE__ */ r(ve, { $duration: k, $paused: h }, n),
177
+ !q && /* @__PURE__ */ r(ge, { children: Array.from({ length: D }).map((e, t) => /* @__PURE__ */ r(
178
+ we,
177
179
  {
178
180
  $active: t === n,
179
181
  onClick: () => M(t),
@@ -187,5 +189,5 @@ const E = 50, O = 2e3, Me = () => /* @__PURE__ */ I("svg", { width: 12, height:
187
189
  );
188
190
  };
189
191
  export {
190
- Xe as default
192
+ ke as default
191
193
  };
@@ -1,94 +1,88 @@
1
- import { jsx as o, jsxs as E } from "react/jsx-runtime";
2
- import { useRef as y } from "react";
3
- import { UploadBtnContainer as U, Wrapper as j, HiddenInput as M, PWrapper as W } from "./styles.js";
4
- import B from "../../../colors/white.js";
5
- import { blue as C } from "../../../colors/blue.js";
6
- import F from "../../../colors/grey.js";
7
- import H from "../../../colors/colorMap.js";
8
- import P from "../../Ripple/Ripple.js";
9
- import { SIZE as Z, MEDIUM as q } from "./constants.js";
10
- import A from "../../Icons/Link/Link.js";
11
- const G = ({ theme: t, children: l }) => /* @__PURE__ */ o(P, { rippleColor: t.m100, children: l }), b = ({
1
+ import { jsx as r, jsxs as d } from "react/jsx-runtime";
2
+ import { useRef as w } from "react";
3
+ import E from "../../Spinner/Spinner.js";
4
+ import { UploadBtnContainer as U, Wrapper as j, HiddenInput as M, SpinnerWrapper as S, ContentWrapper as B, PWrapper as F } from "./styles.js";
5
+ import H from "../../../colors/white.js";
6
+ import { blue as y } from "../../../colors/blue.js";
7
+ import P from "../../../colors/grey.js";
8
+ import Z from "../../../colors/colorMap.js";
9
+ import q from "../../Ripple/Ripple.js";
10
+ import { SIZE as A, MEDIUM as G } from "./constants.js";
11
+ import J from "../../Icons/Link/Link.js";
12
+ const L = ({ theme: t, children: l }) => /* @__PURE__ */ r(q, { rippleColor: t.m100, children: l }), tr = ({
12
13
  label: t,
13
14
  labelColor: l,
14
- theme: p = C,
15
- size: x = q,
16
- width: s,
17
- isLoading: e,
18
- disabled: r,
19
- prefixIcon: c = A,
20
- suffixIcon: m,
15
+ theme: c = y,
16
+ size: C = G,
17
+ width: x,
18
+ isLoading: o,
19
+ disabled: e,
20
+ prefixIcon: m = J,
21
+ suffixIcon: s,
21
22
  type: D = "file",
22
- accept: I,
23
- isMultiple: R,
24
- onChange: k,
25
- ...z
23
+ accept: z,
24
+ isMultiple: I,
25
+ onChange: R,
26
+ ...k
26
27
  }) => {
27
- const h = y(null), { m400: K, m500: g, m600: v } = H[p] ?? C, { height: u, width: $, font: n } = Z[x] || {}, f = l || ["white", "yellow"].includes(p) ? F.m600 : B, a = y(0), d = /* @__PURE__ */ E(
28
+ const f = w(null), { m400: K, m500: W, m600: g } = Z[c] ?? y, { height: h, width: v, font: n } = A[C] || {}, i = l || ["white", "yellow"].includes(c) ? P.m600 : H, a = w(0), $ = /* @__PURE__ */ d(
28
29
  j,
29
30
  {
30
31
  $selectedColor: K,
31
- $hoverColor: g,
32
- $height: u,
33
- $width: s || $,
34
- $activeColor: v,
35
- disabled: r,
36
- $isLoading: e,
32
+ $hoverColor: W,
33
+ $height: h,
34
+ $width: x || v,
35
+ $activeColor: g,
36
+ disabled: e,
37
+ $isLoading: o,
37
38
  tabIndex: 0,
38
- "aria-disabled": r,
39
- onKeyDown: (i) => {
40
- if (i.key === "Enter" || i.key === " ") {
41
- i.preventDefault();
42
- const w = Date.now();
43
- if (w - a.current < 500) {
44
- i.stopPropagation();
39
+ "aria-disabled": e,
40
+ onKeyDown: (p) => {
41
+ if (p.key === "Enter" || p.key === " ") {
42
+ p.preventDefault();
43
+ const u = Date.now();
44
+ if (u - a.current < 500) {
45
+ p.stopPropagation();
45
46
  return;
46
47
  }
47
- a.current = w, !r && !e && h.current?.click();
48
+ a.current = u, !e && !o && f.current?.click();
48
49
  }
49
50
  },
50
51
  children: [
51
- /* @__PURE__ */ o(
52
+ /* @__PURE__ */ r(
52
53
  M,
53
54
  {
54
- ref: h,
55
+ ref: f,
55
56
  type: D,
56
- accept: I,
57
- multiple: R,
58
- disabled: r,
59
- onChange: k,
57
+ accept: z,
58
+ multiple: I,
59
+ disabled: e,
60
+ onChange: R,
60
61
  tabIndex: -1
61
62
  }
62
63
  ),
63
- c && /* @__PURE__ */ o(c, { color: f, size: n + 19 }),
64
- /* @__PURE__ */ o(
65
- W,
66
- {
67
- color: f,
68
- size: `${n}rem`,
69
- $prefixIcon: !!c,
70
- $suffixIcon: !!m,
71
- $iconSize: n + 19,
72
- title: t,
73
- children: t
74
- }
75
- ),
76
- m && /* @__PURE__ */ o(m, { color: f, size: n + 19 })
64
+ /* @__PURE__ */ r(S, { $isLoading: o, children: /* @__PURE__ */ r(E, { size: "small", color: i }) }),
65
+ /* @__PURE__ */ d(B, { $isLoading: o, children: [
66
+ m && /* @__PURE__ */ r(m, { color: i, size: n + 19 }),
67
+ /* @__PURE__ */ r(
68
+ F,
69
+ {
70
+ color: i,
71
+ size: `${n}rem`,
72
+ $prefixIcon: !!m,
73
+ $suffixIcon: !!s,
74
+ $iconSize: n + 19,
75
+ title: t,
76
+ children: t
77
+ }
78
+ ),
79
+ s && /* @__PURE__ */ r(s, { color: i, size: n + 19 })
80
+ ] })
77
81
  ]
78
82
  }
79
83
  );
80
- return /* @__PURE__ */ o(
81
- U,
82
- {
83
- $height: u,
84
- $width: s || $,
85
- disabled: r,
86
- $isLoading: e,
87
- ...z,
88
- children: e || r ? d : /* @__PURE__ */ o(G, { theme: p, children: d })
89
- }
90
- );
84
+ return /* @__PURE__ */ r(U, { $height: h, disabled: e, $isLoading: o, ...k, children: o || e ? $ : /* @__PURE__ */ r(L, { theme: c, children: $ }) });
91
85
  };
92
86
  export {
93
- b as default
87
+ tr as default
94
88
  };
@@ -1,10 +1,8 @@
1
1
  import r, { css as i } from "styled-components";
2
2
  import n from "../../Typography/P/P.js";
3
3
  import a from "../../../colors/grey.js";
4
- const l = r.div`
4
+ const c = r.div`
5
5
  height: ${({ $height: e }) => e}rem;
6
- width: fit-content;
7
- max-width: ${({ $width: e }) => e}rem;
8
6
  display: inline-block;
9
7
  position: relative;
10
8
  border-radius: 0.96rem;
@@ -21,7 +19,7 @@ const l = r.div`
21
19
  transform: translateY(-2px);
22
20
  }
23
21
  `};
24
- `, c = r.label`
22
+ `, d = r.label`
25
23
  height: ${({ $height: e }) => `${e}rem`};
26
24
  width: ${({ $width: e }) => `${e}rem`};
27
25
  border-radius: 0.96rem;
@@ -31,6 +29,8 @@ const l = r.div`
31
29
  align-items: center;
32
30
  gap: 0.8rem;
33
31
  outline: none;
32
+ position: relative;
33
+ overflow: hidden;
34
34
  background-color: ${({ $selectedColor: e, disabled: o }) => o ? a.m500 : e};
35
35
  cursor: ${({ disabled: e, $isLoading: o }) => e ? "not-allowed" : o ? "auto" : "pointer"};
36
36
 
@@ -61,7 +61,24 @@ const l = r.div`
61
61
  $iconSize: o
62
62
  }) => e ? ` - ${o}px - 0.8rem` : ""}
63
63
  );
64
- `, h = r.input`
64
+ `, h = r.div`
65
+ position: absolute;
66
+ inset: 0;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ opacity: ${({ $isLoading: e }) => e ? 1 : 0};
71
+ transition: opacity 0.3s ease;
72
+ pointer-events: none;
73
+ `, $ = r.div`
74
+ display: flex;
75
+ align-items: center;
76
+ gap: 0.8rem;
77
+ flex: 1;
78
+ min-width: 0;
79
+ opacity: ${({ $isLoading: e }) => e ? 0 : 1};
80
+ transition: opacity 0.3s ease;
81
+ `, w = r.input`
65
82
  position: absolute;
66
83
  width: 1px;
67
84
  height: 1px;
@@ -73,8 +90,10 @@ const l = r.div`
73
90
  pointer-events: none;
74
91
  `;
75
92
  export {
76
- h as HiddenInput,
93
+ $ as ContentWrapper,
94
+ w as HiddenInput,
77
95
  m as PWrapper,
78
- l as UploadBtnContainer,
79
- c as Wrapper
96
+ h as SpinnerWrapper,
97
+ c as UploadBtnContainer,
98
+ d as Wrapper
80
99
  };
@@ -1,8 +1,8 @@
1
- import { jsx as e, jsxs as d } from "react/jsx-runtime";
2
- import { useCallback as m, useEffect as h } from "react";
3
- import { createPortal as f } from "react-dom";
4
- import { Overlay as k, ModalContainer as v, ModalHeader as w, ModalTitle as x, CloseButton as b, ModalBody as g, ModalFooter as p } from "./styles.js";
5
- const C = () => /* @__PURE__ */ d(
1
+ import { jsx as t, jsxs as m } from "react/jsx-runtime";
2
+ import { useState as w, useRef as s, useId as j, useEffect as f, useCallback as T, isValidElement as A } from "react";
3
+ import { createPortal as B } from "react-dom";
4
+ import { Overlay as D, ModalContainer as K, ModalHeader as q, ModalTitle as F, CloseButton as H, ModalBody as P, ModalFooter as U } from "./styles.js";
5
+ const M = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])', V = () => /* @__PURE__ */ m(
6
6
  "svg",
7
7
  {
8
8
  width: "18",
@@ -13,49 +13,79 @@ const C = () => /* @__PURE__ */ d(
13
13
  strokeWidth: "2.5",
14
14
  strokeLinecap: "round",
15
15
  strokeLinejoin: "round",
16
+ "aria-hidden": "true",
16
17
  children: [
17
- /* @__PURE__ */ e("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
18
- /* @__PURE__ */ e("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
18
+ /* @__PURE__ */ t("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
19
+ /* @__PURE__ */ t("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
19
20
  ]
20
21
  }
21
- ), T = ({
22
- isOpen: n,
23
- onClose: o,
24
- title: l,
25
- children: c,
26
- footer: a,
27
- footerAlign: u = "right",
28
- width: y,
29
- closeOnOverlayClick: s = !0,
30
- showCloseButton: i = !0
22
+ ), Q = ({
23
+ isOpen: r,
24
+ onClose: l,
25
+ title: n,
26
+ children: R,
27
+ footer: h,
28
+ footerAlign: p = "right",
29
+ width: I,
30
+ closeOnOverlayClick: L = !0,
31
+ showCloseButton: y = !0,
32
+ isFullOnMobile: b = !1,
33
+ ...S
31
34
  }) => {
32
- const t = m(
33
- (r) => {
34
- r.key === "Escape" && o?.();
35
+ const [v, g] = w(r), [$, i] = w(!1), c = s(null), o = s(null), k = s(null), a = j();
36
+ f(() => (r ? (clearTimeout(c.current), k.current = document.activeElement, g(!0), i(!1)) : (i(!0), c.current = setTimeout(() => {
37
+ i(!1), g(!1), k.current?.focus();
38
+ }, 220)), () => clearTimeout(c.current)), [r]), f(() => {
39
+ if (!r || !o.current) return;
40
+ (o.current.querySelectorAll(M)[0] ?? o.current).focus();
41
+ }, [r, v]);
42
+ const x = T((e) => {
43
+ if (e.key !== "Tab" || !o.current) return;
44
+ const d = [...o.current.querySelectorAll(M)];
45
+ if (!d.length) return;
46
+ const C = d[0], E = d[d.length - 1];
47
+ e.shiftKey ? document.activeElement === C && (e.preventDefault(), E.focus()) : document.activeElement === E && (e.preventDefault(), C.focus());
48
+ }, []), u = T(
49
+ (e) => {
50
+ e.key === "Escape" && l?.(), x(e);
35
51
  },
36
- [o]
52
+ [l, x]
37
53
  );
38
- return h(() => {
39
- if (!n) return;
40
- document.addEventListener("keydown", t);
41
- const r = document.body.style.overflow;
54
+ return f(() => {
55
+ if (!r) return;
56
+ document.addEventListener("keydown", u);
57
+ const e = document.body.style.overflow;
42
58
  return document.body.style.overflow = "hidden", () => {
43
- document.removeEventListener("keydown", t), document.body.style.overflow = r;
59
+ document.removeEventListener("keydown", u), document.body.style.overflow = e;
44
60
  };
45
- }, [n, t]), n ? f(
46
- /* @__PURE__ */ e(k, { role: "dialog", "aria-modal": "true", "aria-label": l, onClick: (r) => {
47
- s && r.target === r.currentTarget && o?.();
48
- }, children: /* @__PURE__ */ d(v, { $width: y, children: [
49
- (l || i) && /* @__PURE__ */ d(w, { children: [
50
- l && /* @__PURE__ */ e(x, { children: l }),
51
- i && /* @__PURE__ */ e(b, { onClick: o, "aria-label": "Close modal", children: /* @__PURE__ */ e(C, {}) })
52
- ] }),
53
- /* @__PURE__ */ e(g, { children: c }),
54
- a && /* @__PURE__ */ e(p, { $align: u, children: a })
55
- ] }) }),
61
+ }, [r, u]), v ? B(
62
+ /* @__PURE__ */ t(D, { onClick: (e) => {
63
+ L && e.target === e.currentTarget && l?.();
64
+ }, $fullOnMobile: b, children: /* @__PURE__ */ m(
65
+ K,
66
+ {
67
+ ref: o,
68
+ role: "dialog",
69
+ "aria-modal": "true",
70
+ "aria-labelledby": n ? a : void 0,
71
+ tabIndex: -1,
72
+ $width: I,
73
+ $fullOnMobile: b,
74
+ $isClosing: $,
75
+ ...S,
76
+ children: [
77
+ (n || y) && /* @__PURE__ */ m(q, { children: [
78
+ n && (A(n) ? /* @__PURE__ */ t("div", { id: a, children: n }) : /* @__PURE__ */ t(F, { id: a, children: n })),
79
+ y && /* @__PURE__ */ t(H, { onClick: l, "aria-label": "Close modal", children: /* @__PURE__ */ t(V, {}) })
80
+ ] }),
81
+ /* @__PURE__ */ t(P, { children: R }),
82
+ h && /* @__PURE__ */ t(U, { $align: p, children: h })
83
+ ]
84
+ }
85
+ ) }),
56
86
  document.body
57
87
  ) : null;
58
88
  };
59
89
  export {
60
- T as default
90
+ Q as default
61
91
  };
@@ -1,13 +1,22 @@
1
- import o, { css as r, keyframes as n } from "styled-components";
2
- import e from "../../colors/grey.js";
3
- import i from "../../colors/white.js";
4
- const s = n`
1
+ import e, { css as n, keyframes as r } from "styled-components";
2
+ import t from "../../colors/grey.js";
3
+ import a from "../../colors/white.js";
4
+ const s = r`
5
5
  from { opacity: 0; }
6
6
  to { opacity: 1; }
7
- `, a = n`
8
- from { opacity: 0; transform: translateY(1.5rem); }
9
- to { opacity: 1; transform: translateY(0); }
10
- `, m = o.div`
7
+ `, d = r`
8
+ from { opacity: 0; transform: scale(0.95); }
9
+ to { opacity: 1; transform: scale(1); }
10
+ `, m = r`
11
+ from { opacity: 1; transform: scale(1); }
12
+ to { opacity: 0; transform: scale(0.95); }
13
+ `, l = r`
14
+ from { transform: translateY(100%); }
15
+ to { transform: translateY(0); }
16
+ `, c = r`
17
+ from { transform: translateY(0); }
18
+ to { transform: translateY(100%); }
19
+ `, g = e.div`
11
20
  position: fixed;
12
21
  inset: 0;
13
22
  background-color: rgba(0, 0, 0, 0.5);
@@ -17,30 +26,49 @@ const s = n`
17
26
  z-index: 1000;
18
27
  animation: ${s} 0.2s ease;
19
28
  padding: 1rem;
20
- `, f = o.div`
21
- background-color: ${i};
29
+
30
+ ${({ $fullOnMobile: o }) => o && n`
31
+ @media (max-width: 640px) {
32
+ align-items: flex-end;
33
+ padding: 0;
34
+ }
35
+ `}
36
+ `, h = e.div`
37
+ background-color: ${a};
22
38
  border-radius: 1rem;
23
39
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.2);
24
40
  display: flex;
25
41
  flex-direction: column;
26
42
  max-height: 90vh;
27
- width: ${({ $width: t }) => t || "32rem"};
43
+ width: ${({ $width: o }) => o || "32rem"};
28
44
  max-width: 100%;
29
- animation: ${a} 0.25s ease;
30
- `, p = o.div`
45
+ animation: ${({ $isClosing: o }) => o ? m : d} 0.3s ease forwards;
46
+
47
+ ${({ $fullOnMobile: o, $isClosing: i }) => o && n`
48
+ @media (max-width: 640px) {
49
+ width: 100%;
50
+ max-width: 100%;
51
+ max-height: 95dvh;
52
+ border-bottom-left-radius: 0;
53
+ border-bottom-right-radius: 0;
54
+ animation: ${i ? c : l} 0.22s
55
+ cubic-bezier(0.32, 0.72, 0, 1) ${i ? "forwards" : ""};
56
+ }
57
+ `}
58
+ `, u = e.div`
31
59
  display: flex;
32
60
  align-items: center;
33
61
  justify-content: space-between;
34
62
  padding: 1.25rem 1.5rem;
35
- border-bottom: 1px solid ${e.m200};
63
+ border-bottom: 1px solid ${t.m200};
36
64
  flex-shrink: 0;
37
- `, g = o.h2`
65
+ `, b = e.h2`
38
66
  margin: 0;
39
67
  font-size: 2.4rem;
40
68
  font-weight: 600;
41
- color: ${e.m900};
69
+ color: ${t.m900};
42
70
  line-height: 1.4;
43
- `, x = o.button`
71
+ `, y = e.button`
44
72
  background: none;
45
73
  border: none;
46
74
  cursor: pointer;
@@ -48,7 +76,7 @@ const s = n`
48
76
  display: flex;
49
77
  align-items: center;
50
78
  justify-content: center;
51
- color: ${e.m500};
79
+ color: ${t.m500};
52
80
  border-radius: 0.5rem;
53
81
  transition:
54
82
  background-color 0.15s,
@@ -56,44 +84,44 @@ const s = n`
56
84
  flex-shrink: 0;
57
85
 
58
86
  &:hover {
59
- background-color: ${e.m100};
60
- color: ${e.m800};
87
+ background-color: ${t.m100};
88
+ color: ${t.m800};
61
89
  }
62
90
 
63
91
  &:focus-visible {
64
- outline: 2px solid ${e.m400};
92
+ outline: 2px solid ${t.m400};
65
93
  outline-offset: 2px;
66
94
  }
67
- `, u = o.div`
95
+ `, $ = e.div`
68
96
  padding: 1.5rem;
69
97
  overflow-y: auto;
70
98
  flex: 1;
71
- color: ${e.m700};
99
+ color: ${t.m700};
72
100
  font-size: 0.95rem;
73
101
  line-height: 1.6;
74
- `, y = o.div`
102
+ `, w = e.div`
75
103
  display: flex;
76
104
  align-items: center;
77
105
  justify-content: flex-end;
78
106
  gap: 0.75rem;
79
107
  padding: 1rem 1.5rem;
80
- border-top: 1px solid ${e.m200};
108
+ border-top: 1px solid ${t.m200};
81
109
  flex-shrink: 0;
82
110
 
83
- ${({ $align: t }) => t === "left" && r`
111
+ ${({ $align: o }) => o === "left" && n`
84
112
  justify-content: flex-start;
85
113
  `}
86
114
 
87
- ${({ $align: t }) => t === "center" && r`
115
+ ${({ $align: o }) => o === "center" && n`
88
116
  justify-content: center;
89
117
  `}
90
118
  `;
91
119
  export {
92
- x as CloseButton,
93
- u as ModalBody,
94
- f as ModalContainer,
95
- y as ModalFooter,
96
- p as ModalHeader,
97
- g as ModalTitle,
98
- m as Overlay
120
+ y as CloseButton,
121
+ $ as ModalBody,
122
+ h as ModalContainer,
123
+ w as ModalFooter,
124
+ u as ModalHeader,
125
+ b as ModalTitle,
126
+ g as Overlay
99
127
  };
package/index.d.ts CHANGED
@@ -119,13 +119,16 @@ export declare const ToastContainer: React.FC<ToastContainerProps>;
119
119
  export interface ModalProps {
120
120
  isOpen: boolean;
121
121
  onClose: () => void;
122
- title?: string;
122
+ /** String or any React element (e.g. heading + badge). Strings are wrapped in the default ModalTitle style; elements are rendered as-is. */
123
+ title?: React.ReactNode;
123
124
  children?: React.ReactNode;
124
125
  footer?: React.ReactNode;
125
126
  footerAlign?: 'left' | 'center' | 'right';
126
127
  width?: string | number;
127
128
  closeOnOverlayClick?: boolean;
128
129
  showCloseButton?: boolean;
130
+ /** On viewports ≤ 640 px the modal fills the screen width and slides up from the bottom. On desktop it behaves as a normal centered modal. */
131
+ isFullOnMobile?: boolean;
129
132
  }
130
133
 
131
134
  export declare const Modal: React.FC<ModalProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meticulous-ui",
3
- "version": "3.5.2",
3
+ "version": "3.5.4",
4
4
  "license": "ISC",
5
5
  "description": "A comprehensive React UI component library with a wide range of customizable components, icons, colors, and utilities for building modern web applications.",
6
6
  "types": "./index.d.ts",