meticulous-ui 2.0.5 → 2.1.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,87 +1,196 @@
1
- import { j as o } from "../../_virtual/jsx-runtime.js";
2
- import { useState as g, useRef as b, useEffect as F, useLayoutEffect as k, createElement as B } from "react";
3
- import L from "../../node_modules/lodash-es/get.js";
4
- import d from "../../colors/grey.js";
5
- import P from "../MenuItem/MenuItem.js";
6
- import M from "../../colors/index.js";
7
- import V from "../../colors/blue.js";
8
- import H from "../Spinner/Spinner.js";
9
- import { DropdownWrapper as I, Box as q, PWrapper as A, ChevronDownWrapper as G, OptionWrapper as J, SpinnerWrapper as K } from "./styles.js";
10
- const N = (t) => {
11
- if (typeof t != "string") return t;
12
- if (t.endsWith("px"))
13
- return parseFloat(t);
14
- if (t.endsWith("rem")) {
15
- const p = parseFloat(t), r = parseFloat(getComputedStyle(document.documentElement).fontSize);
16
- return p * r;
1
+ import { j as r } from "../../_virtual/jsx-runtime.js";
2
+ import { useState as C, useRef as S, useMemo as L, useEffect as d, useLayoutEffect as M, useCallback as ee, createElement as te } from "react";
3
+ import ne from "../../node_modules/lodash-es/get.js";
4
+ import I from "../../colors/grey.js";
5
+ import re from "../MenuItem/MenuItem.js";
6
+ import oe from "../../colors/index.js";
7
+ import se from "../../colors/blue.js";
8
+ import F from "../Spinner/Spinner.js";
9
+ import { DropdownWrapper as ie, Box as ce, PWrapper as le, ChevronDownWrapper as fe, OptionWrapper as ue, SearchContainer as ae, SearchIcon as pe, SearchInput as de, OptionsList as me, LoadMoreSentinel as he, SpinnerWrapper as xe } from "./styles.js";
10
+ const be = (o) => {
11
+ if (typeof o != "string") return o;
12
+ if (o.endsWith("px")) return parseFloat(o);
13
+ if (o.endsWith("rem")) {
14
+ const E = parseFloat(o), i = parseFloat(getComputedStyle(document.documentElement).fontSize);
15
+ return E * i;
17
16
  }
18
- return parseFloat(t);
19
- }, oe = ({
20
- options: t,
21
- onChange: p,
22
- value: r,
23
- width: n = "20rem",
24
- menuHeight: m = "20rem",
25
- placeholder: $,
26
- theme: j = "blue",
27
- isLoading: a,
28
- isDisabled: w,
29
- loaderColor: C
17
+ return parseFloat(o);
18
+ }, ve = ({
19
+ options: o,
20
+ onChange: E,
21
+ value: i,
22
+ width: m = "20rem",
23
+ menuHeight: O = "20rem",
24
+ placeholder: P,
25
+ theme: A = "blue",
26
+ isLoading: $,
27
+ isDisabled: v,
28
+ loaderColor: y,
29
+ searchable: h = !1,
30
+ onLoadMore: l,
31
+ hasMore: x = !1,
32
+ isLoadingMore: a = !1
30
33
  }) => {
31
- const [s, l] = g(!1), [O, u] = g("bottom"), i = b(null), h = b(null), S = () => {
32
- l((e) => !e);
33
- }, E = (e) => {
34
- e !== r && (p(e), l(!1));
35
- };
36
- F(() => {
37
- const e = (c) => {
38
- i.current && !i.current.contains(c.target) && l(!1);
34
+ const [n, j] = C(!1), [B, H] = C("bottom"), [b, D] = C(""), [f, p] = C(-1), g = S(null), w = S(null), k = S(null), R = S(null), V = S(!0), K = () => j((e) => !e), z = (e) => {
35
+ e !== i && (E(e), j(!1));
36
+ }, c = L(() => {
37
+ if (!h || !b.trim()) return o;
38
+ const e = b.toLowerCase();
39
+ return o.filter(({ label: t }) => t.toLowerCase().includes(e));
40
+ }, [o, b, h]);
41
+ d(() => {
42
+ if (n) {
43
+ const e = c.findIndex((t) => t.value === i);
44
+ if (e !== -1 && !c[e].disabled)
45
+ p(e);
46
+ else {
47
+ const t = c.findIndex((s) => !s.disabled);
48
+ p(t);
49
+ }
50
+ } else
51
+ D(""), p(-1);
52
+ }, [n, b, c, i]), d(() => {
53
+ if (n && f !== -1 && w.current) {
54
+ const e = w.current.children[f];
55
+ e && e.scrollIntoView({
56
+ block: "nearest",
57
+ behavior: "auto"
58
+ });
59
+ }
60
+ }, [f, n]), d(() => {
61
+ n && h && k.current && k.current.focus();
62
+ }, [n, h]), d(() => {
63
+ n || (V.current = !0);
64
+ }, [n]), d(() => {
65
+ const e = (t) => {
66
+ g.current && !g.current.contains(t.target) && j(!1);
39
67
  };
40
68
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
41
- }, []), k(() => {
42
- if (s && h.current && i.current) {
43
- const e = i.current.getBoundingClientRect(), c = window.innerHeight, f = N(m), x = c - e.bottom;
44
- x < f + 8 && e.top > x ? u("top") : u("bottom");
69
+ }, []), M(() => {
70
+ if (n && w.current && g.current) {
71
+ const e = g.current.getBoundingClientRect(), t = window.innerHeight, s = be(O), u = t - e.bottom;
72
+ H(
73
+ u < s + 8 && e.top > u ? "top" : "bottom"
74
+ );
75
+ }
76
+ }, [n, O]);
77
+ const Q = (e) => {
78
+ let t = e + 1;
79
+ for (; t < c.length; ) {
80
+ if (!c[t].disabled) return t;
81
+ t++;
82
+ }
83
+ return e;
84
+ }, q = (e) => {
85
+ let t = e - 1;
86
+ for (; t >= 0; ) {
87
+ if (!c[t].disabled) return t;
88
+ t--;
45
89
  }
46
- }, [s, m]);
90
+ return e;
91
+ }, N = (e) => {
92
+ if (n)
93
+ switch (e.key) {
94
+ case "ArrowDown":
95
+ e.preventDefault();
96
+ const t = Q(f);
97
+ t === f && x && !a && l?.(), p(t);
98
+ break;
99
+ case "ArrowUp":
100
+ e.preventDefault(), p((u) => q(u));
101
+ break;
102
+ case "Enter":
103
+ e.preventDefault();
104
+ const s = c[f];
105
+ s && !s.disabled && z(s.value);
106
+ break;
107
+ case "Escape":
108
+ j(!1);
109
+ break;
110
+ }
111
+ }, W = ee(() => {
112
+ x && !a && l && l();
113
+ }, [x, a, l]);
114
+ d(() => {
115
+ const e = R.current;
116
+ if (!e || !l || !x) return;
117
+ const t = new IntersectionObserver(
118
+ ([s]) => {
119
+ s.isIntersecting && !a && W();
120
+ },
121
+ {
122
+ root: w.current,
123
+ // Observe relative to the scrollable container
124
+ threshold: 0.1,
125
+ rootMargin: "20px"
126
+ // Start loading 20px before the user even hits the bottom
127
+ }
128
+ );
129
+ return t.observe(e), () => t.disconnect();
130
+ }, [W, l, x, a]);
47
131
  const {
48
- m50: W,
49
- m100: R,
50
- m200: y,
51
- m500: z
52
- } = L(M, j, V), D = ({ value: e, label: c, disabled: f }) => /* @__PURE__ */ B(
53
- P,
132
+ m50: U,
133
+ m100: G,
134
+ m200: J,
135
+ m500: T
136
+ } = ne(oe, A, se), X = (e, t) => () => !e && p(t), Y = ({ value: e, label: t, disabled: s }, u) => /* @__PURE__ */ te(
137
+ re,
54
138
  {
55
139
  value: e,
56
- label: c,
57
- isDisabled: f,
58
- onSelect: E,
59
- isSelected: e === r,
140
+ label: t,
141
+ isDisabled: s,
142
+ onSelect: z,
143
+ onMouseEnter: X(s, u),
144
+ isSelected: e === i,
145
+ isHighlighted: u === f,
60
146
  key: e,
61
- width: n,
62
- selectedColor: y,
63
- hoverColor: W,
64
- activeColor: R
147
+ width: m,
148
+ selectedColor: J,
149
+ hoverColor: U,
150
+ activeColor: G
65
151
  }
66
- );
67
- return /* @__PURE__ */ o.jsxs(
68
- I,
152
+ ), Z = (e) => {
153
+ D(e.target.value);
154
+ }, _ = (e) => {
155
+ e.stopPropagation();
156
+ };
157
+ return /* @__PURE__ */ r.jsxs(
158
+ ie,
69
159
  {
70
- ref: i,
71
- $width: n,
72
- $isLoading: a,
73
- $isDisabled: w,
160
+ ref: g,
161
+ $width: m,
162
+ tabIndex: v ? -1 : 0,
163
+ onKeyDown: N,
164
+ $isLoading: $,
165
+ $isDisabled: v,
74
166
  children: [
75
- /* @__PURE__ */ o.jsxs(q, { $width: n, onClick: S, $isOpen: s, $border: z, children: [
76
- /* @__PURE__ */ o.jsx(A, { $width: n, color: r ? d.m700 : d.m500, size: "1.2rem", children: r ? t.find(({ value: e }) => r === e)?.label : $ }),
77
- /* @__PURE__ */ o.jsx(G, { color: d.m500, size: 22, $isOpen: s })
167
+ /* @__PURE__ */ r.jsxs(ce, { $width: m, onClick: K, $isOpen: n, $border: T, children: [
168
+ /* @__PURE__ */ r.jsx(le, { $width: m, color: i ? I.m700 : I.m500, size: "1.2rem", children: i ? o.find(({ value: e }) => i === e)?.label : P }),
169
+ /* @__PURE__ */ r.jsx(fe, { color: I.m500, size: 22, $isOpen: n })
170
+ ] }),
171
+ /* @__PURE__ */ r.jsxs(ue, { $isOpen: n, $width: m, $height: O, $top: B === "top", children: [
172
+ h && /* @__PURE__ */ r.jsxs(ae, { onClick: _, children: [
173
+ /* @__PURE__ */ r.jsx(pe, { size: 18, color: I.m800 }),
174
+ /* @__PURE__ */ r.jsx(
175
+ de,
176
+ {
177
+ ref: k,
178
+ value: b,
179
+ onChange: Z,
180
+ placeholder: "Search..."
181
+ }
182
+ )
183
+ ] }),
184
+ /* @__PURE__ */ r.jsxs(me, { ref: w, children: [
185
+ c.map(Y),
186
+ l && /* @__PURE__ */ r.jsx(he, { ref: R, children: a && /* @__PURE__ */ r.jsx(F, { size: "small", color: y }) })
187
+ ] })
78
188
  ] }),
79
- /* @__PURE__ */ o.jsx(J, { $isOpen: s, $width: n, $height: m, $top: O === "top", children: /* @__PURE__ */ o.jsx("div", { ref: h, children: t.map(D) }) }),
80
- a && /* @__PURE__ */ o.jsx(K, { children: /* @__PURE__ */ o.jsx(H, { size: "small", color: C }) })
189
+ $ && /* @__PURE__ */ r.jsx(xe, { children: /* @__PURE__ */ r.jsx(F, { size: "small", color: y }) })
81
190
  ]
82
191
  }
83
192
  );
84
193
  };
85
194
  export {
86
- oe as default
195
+ ve as default
87
196
  };
@@ -1,92 +1,139 @@
1
- import o, { css as t, keyframes as i } from "../../node_modules/styled-components/dist/styled-components.browser.esm.js";
2
- import n from "../../colors/grey.js";
3
- import a from "../Typography/P/P.js";
4
- import m from "../Icons/ChevronDown/ChevronDown.js";
5
- import { DEFAULT_BORDER as s } from "./constants.js";
6
- import p from "../../colors/white.js";
7
- const d = i`
1
+ import e, { css as r, keyframes as n } from "../../node_modules/styled-components/dist/styled-components.browser.esm.js";
2
+ import t from "../../colors/grey.js";
3
+ import m from "../Typography/P/P.js";
4
+ import s from "../Icons/ChevronDown/ChevronDown.js";
5
+ import d from "../Icons/Search/Search.js";
6
+ import { DEFAULT_BORDER as p } from "./constants.js";
7
+ import a from "../../colors/white.js";
8
+ const c = n`
8
9
  from {
9
10
  transform: rotate(0deg);
10
11
  }
11
12
  to {
12
13
  transform: rotate(180deg);
13
14
  }
14
- `, c = i`
15
+ `, l = n`
15
16
  from {
16
17
  transform: rotate(180deg);
17
18
  }
18
19
  to {
19
20
  transform: rotate(0deg);
20
21
  }
21
- `, $ = o.div`
22
- max-width: ${({ $width: r }) => r};
22
+ `, w = e.div`
23
+ max-width: ${({ $width: o }) => o};
23
24
  position: relative;
25
+ outline: none;
24
26
 
25
- ${({ $isLoading: r }) => r && t`
27
+ ${({ $isLoading: o }) => o && r`
26
28
  pointer-events: none;
27
29
  opacity: 0.8;
28
30
  `}
29
31
 
30
- ${({ $isDisabled: r }) => r && t`
32
+ ${({ $isDisabled: o }) => o && r`
31
33
  pointer-events: none;
32
34
  `}
33
- `, v = o.div`
35
+ `, $ = e.div`
34
36
  height: 2rem;
35
- width: ${({ $width: r }) => r};
37
+ width: ${({ $width: o }) => o};
36
38
  border-radius: 0.6rem;
37
- border: ${({ $isOpen: r, $border: e }) => r ? `2px solid ${e}` : `1px solid ${s}`};
39
+ border: ${({ $isOpen: o, $border: i }) => o ? `2px solid ${i}` : `1px solid ${p}`};
38
40
  padding: 0.4rem 0.6rem 0.4rem;
39
41
  display: flex;
40
42
  align-items: center;
41
43
  justify-content: space-between;
42
44
  cursor: pointer;
43
- `, x = o(a)`
45
+ `, y = e(m)`
44
46
  overflow: hidden;
45
47
  white-space: nowrap;
46
48
  text-overflow: ellipsis;
47
- max-width: calc(${({ $width: r }) => r} - 2rem);
49
+ max-width: calc(${({ $width: o }) => o} - 2rem);
48
50
  pointer-events: none;
49
- `, u = o(m)`
50
- animation: ${({ $isOpen: r }) => r ? d : c} 0.15s linear;
51
- transform: rotate(${({ $isOpen: r }) => r ? 180 : 0}deg);
52
- `, y = o.div`
53
- border: 1px solid ${n.m700};
54
- width: calc(${({ $width: r }) => r} + 1rem);
55
- overflow: auto;
51
+ `, S = e(s)`
52
+ animation: ${({ $isOpen: o }) => o ? c : l} 0.15s linear;
53
+ transform: rotate(${({ $isOpen: o }) => o ? 180 : 0}deg);
54
+ `, k = e.div`
55
+ border: 1px solid ${t.m700};
56
+ width: calc(${({ $width: o }) => o} + 1rem);
57
+ /* Remove overflow: auto from here */
58
+ display: flex;
59
+ flex-direction: column;
56
60
  position: absolute;
57
61
  z-index: 1000;
58
- background-color: ${p};
62
+ background-color: ${a};
59
63
  left: 0.15rem;
60
64
  max-height: 0;
61
65
  transition: max-height 0.15s ease-out;
62
66
  opacity: 0;
67
+ overflow: hidden; /* Keep this hidden so the collapse works */
63
68
 
64
- ${({ $isOpen: r }) => r && t`
65
- max-height: ${({ $height: e }) => e};
69
+ ${({ $isOpen: o }) => o && r`
70
+ max-height: ${({ $height: i }) => i};
66
71
  opacity: 1;
67
72
  `};
68
73
 
69
- ${({ $top: r }) => r ? t`
74
+ ${({ $top: o }) => o ? r`
70
75
  bottom: 100%;
76
+ flex-direction: column-reverse; /* Search at bottom if menu opens upward */
71
77
  border-top-right-radius: 0.6rem;
72
78
  border-top-left-radius: 0.6rem;
73
- border-bottom-width: 0;
74
- ` : t`
79
+ margin-bottom: 0.1rem;
80
+ ` : r`
75
81
  top: 100%;
76
82
  border-bottom-right-radius: 0.6rem;
77
83
  border-bottom-left-radius: 0.6rem;
78
- border-top-width: 0;
84
+ margin-top: 0.1rem;
79
85
  `}
80
- `, D = o.div`
86
+ `, D = e.div`
87
+ overflow-y: auto;
88
+ flex: 1;
89
+ `, W = e.div`
81
90
  position: absolute;
82
91
  top: 0.7rem;
83
92
  right: 1rem;
93
+ `, z = e.div`
94
+ position: relative;
95
+ display: flex;
96
+ align-items: center;
97
+ border-bottom: 1px solid ${t.m300};
98
+ background: ${a};
99
+
100
+ &:focus-within {
101
+ border-bottom-color: ${t.m500};
102
+ }
103
+ `, C = e.input`
104
+ width: 100%;
105
+ box-sizing: border-box;
106
+ border: none;
107
+ /* Add left padding to make room for the icon */
108
+ padding: 0.5rem 0.75rem 0.5rem 0;
109
+ font-size: 1.2rem;
110
+ color: ${t.m700};
111
+ background: transparent;
112
+ outline: none;
113
+
114
+ &::placeholder {
115
+ color: ${t.m400};
116
+ }
117
+ `, L = e(d)`
118
+ margin: 0 1.2rem;
119
+ `, O = e.div`
120
+ display: flex;
121
+ justify-content: center;
122
+ align-items: center;
123
+ padding: 1rem 0;
124
+ min-height: 1rem;
125
+ width: 100%;
84
126
  `;
85
127
  export {
86
- v as Box,
87
- u as ChevronDownWrapper,
88
- $ as DropdownWrapper,
89
- y as OptionWrapper,
90
- x as PWrapper,
91
- D as SpinnerWrapper
128
+ $ as Box,
129
+ S as ChevronDownWrapper,
130
+ w as DropdownWrapper,
131
+ O as LoadMoreSentinel,
132
+ k as OptionWrapper,
133
+ D as OptionsList,
134
+ y as PWrapper,
135
+ z as SearchContainer,
136
+ L as SearchIcon,
137
+ C as SearchInput,
138
+ W as SpinnerWrapper
92
139
  };
@@ -0,0 +1,4 @@
1
+ import r from "./ChevronDown.js";
2
+ export {
3
+ r as default
4
+ };
@@ -0,0 +1,4 @@
1
+ import a from "./Search.js";
2
+ export {
3
+ a as default
4
+ };
@@ -1,40 +1,44 @@
1
1
  import { j as n } from "../../_virtual/jsx-runtime.js";
2
- import e from "../../colors/grey.js";
3
- import t from "../../colors/blue.js";
4
- import d from "../../colors/white.js";
5
- import { Wrapper as C, PWrapper as h } from "./styles.js";
6
- const x = ({ isSelected: o, isDisabled: r }) => o ? e.m700 : r ? e.m300 : e.m500, W = ({
2
+ import t from "../../colors/grey.js";
3
+ import m from "../../colors/blue.js";
4
+ import a from "../../colors/white.js";
5
+ import { Wrapper as x, PWrapper as g } from "./styles.js";
6
+ const j = ({ isSelected: o, isDisabled: r }) => o ? t.m700 : r ? t.m300 : t.m500, E = ({
7
7
  value: o,
8
8
  label: r,
9
- width: m = "20rem",
10
- isSelected: i,
11
- defaultColor: p = d,
12
- selectedColor: c = t.m200,
13
- hoverColor: s = t.m50,
14
- activeColor: f = t.m100,
15
- size: u = "1.2rem",
16
- onSelect: $,
17
- isDisabled: l
9
+ width: i = "20rem",
10
+ isSelected: l,
11
+ defaultColor: p = a,
12
+ selectedColor: c = m.m200,
13
+ hoverColor: f = m.m50,
14
+ activeColor: s = m.m100,
15
+ isHighlighted: u,
16
+ size: $ = "1.2rem",
17
+ onSelect: h,
18
+ isDisabled: e,
19
+ onMouseEnter: d
18
20
  }) => {
19
- const a = () => {
20
- $(o);
21
+ const C = () => {
22
+ e || h(o);
21
23
  };
22
24
  return /* @__PURE__ */ n.jsx(
23
- C,
25
+ x,
24
26
  {
25
- $isSelected: i,
26
- $width: m,
27
+ $isSelected: l,
28
+ $width: i,
27
29
  $defaultColor: p,
28
30
  $selectedColor: c,
29
- $hoverColor: s,
30
- $activeColor: f,
31
- $isDisabled: l,
32
- onClick: a,
31
+ $hoverColor: f,
32
+ $activeColor: s,
33
+ $isDisabled: e,
34
+ $isHighlighted: u,
35
+ onClick: C,
36
+ onMouseEnter: d,
33
37
  title: r,
34
- children: /* @__PURE__ */ n.jsx(h, { size: u, color: x({ isSelected: i, isDisabled: l }), $width: m, children: r })
38
+ children: /* @__PURE__ */ n.jsx(g, { size: $, color: j({ isSelected: l, isDisabled: e }), $width: i, children: r })
35
39
  }
36
40
  );
37
41
  };
38
42
  export {
39
- W as default
43
+ E as default
40
44
  };
@@ -1,27 +1,30 @@
1
1
  import t from "../../node_modules/styled-components/dist/styled-components.browser.esm.js";
2
- import a from "../Typography/P/P.js";
3
- const p = t.div`
2
+ import n from "../Typography/P/P.js";
3
+ const d = t.div`
4
4
  width: ${({ $width: o }) => o};
5
- background-color: ${({ $isSelected: o, $defaultColor: r, $selectedColor: e }) => o ? e : r};
6
- cursor: ${({ $isSelected: o }) => o ? "auto" : "pointer"};
5
+ background-color: ${({
6
+ $isSelected: o,
7
+ $defaultColor: r,
8
+ $isHighlighted: e,
9
+ $hoverColor: a,
10
+ $selectedColor: i
11
+ }) => o ? i : e ? a : r};
12
+
13
+ cursor: ${({ $isSelected: o, $isDisabled: r }) => o ? "auto" : r ? "not-allowed" : "pointer"};
7
14
  padding: 0.6rem 0 0.8rem 1rem;
8
15
  margin-top: 0.1rem;
9
16
  pointer-events: ${({ $isDisabled: o }) => o ? "none" : "auto"};
10
17
 
11
- &:hover {
12
- background-color: ${({ $isSelected: o, $hoverColor: r, $selectedColor: e }) => o ? e : r};
13
- }
14
-
15
18
  &:active {
16
19
  background-color: ${({ $isSelected: o, $activeColor: r, $selectedColor: e }) => o ? e : r};
17
20
  }
18
- `, c = t(a)`
21
+ `, m = t(n)`
19
22
  overflow: hidden;
20
23
  white-space: nowrap;
21
24
  text-overflow: ellipsis;
22
25
  max-width: calc(${({ $width: o }) => o} - 2rem);
23
26
  `;
24
27
  export {
25
- c as PWrapper,
26
- p as Wrapper
28
+ m as PWrapper,
29
+ d as Wrapper
27
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meticulous-ui",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "repository": {