@vkzstudio/muza-ui 1.4.1 → 1.5.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/components/DropdownSearchMenu/DropdownSearchMenu.d.ts +73 -0
- package/dist/components/DropdownSearchMenu/DropdownSearchMenu.d.ts.map +1 -0
- package/dist/components/DropdownSearchMenu/DropdownSearchMenu.js +257 -0
- package/dist/components/DropdownSearchMenu/DropdownSearchMenu.stories.d.ts +28 -0
- package/dist/components/DropdownSearchMenu/DropdownSearchMenu.stories.d.ts.map +1 -0
- package/dist/components/DropdownSearchMenu/index.d.ts +2 -0
- package/dist/components/DropdownSearchMenu/index.d.ts.map +1 -0
- package/dist/components/PhoneInput/CountrySelector.d.ts +34 -0
- package/dist/components/PhoneInput/CountrySelector.d.ts.map +1 -0
- package/dist/components/PhoneInput/CountrySelector.js +109 -0
- package/dist/components/PhoneInput/PhoneInput.d.ts +86 -0
- package/dist/components/PhoneInput/PhoneInput.d.ts.map +1 -0
- package/dist/components/PhoneInput/PhoneInput.js +144 -0
- package/dist/components/PhoneInput/PhoneInput.stories.d.ts +29 -0
- package/dist/components/PhoneInput/PhoneInput.stories.d.ts.map +1 -0
- package/dist/components/PhoneInput/index.d.ts +2 -0
- package/dist/components/PhoneInput/index.d.ts.map +1 -0
- package/dist/components/Searchbar/Searchbar.js +4 -4
- package/dist/components/Toast/Toast.d.ts +2 -1
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +37 -36
- package/dist/components/Toast/Toast.stories.d.ts +1 -0
- package/dist/components/Toast/Toast.stories.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +16 -2
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +99 -22
- package/dist/components/Tooltip/Tooltip.stories.d.ts +1 -0
- package/dist/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.js +329 -322
- package/dist/muza-ui.css +1 -1
- package/dist/styles/token-colors.css +34 -0
- package/dist/styles/token-sizes.css +88 -8
- package/dist/translations/locales/cs.d.ts.map +1 -1
- package/dist/translations/locales/cs.js +8 -0
- package/dist/translations/locales/en.d.ts.map +1 -1
- package/dist/translations/locales/en.js +8 -0
- package/dist/translations/locales/sk.d.ts.map +1 -1
- package/dist/translations/locales/sk.js +8 -0
- package/dist/translations/types.d.ts +20 -0
- package/dist/translations/types.d.ts.map +1 -1
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/cn.js +2 -1
- package/package.json +2 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { PopoverContentProps, PopoverTriggerProps } from '../Popover';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Props for the DropdownSearchMenu root component.
|
|
5
|
+
*/
|
|
6
|
+
export interface DropdownSearchMenuProps {
|
|
7
|
+
/** The trigger and content of the menu. */
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
/** Controlled open state. */
|
|
10
|
+
open?: boolean;
|
|
11
|
+
/** Initial open state for uncontrolled usage. @default false */
|
|
12
|
+
defaultOpen?: boolean;
|
|
13
|
+
/** Fires when the open state changes. */
|
|
14
|
+
onOpenChange?: (open: boolean) => void;
|
|
15
|
+
/** Controlled search-field value. Pair with `onSearchChange`. */
|
|
16
|
+
search?: string;
|
|
17
|
+
/** Initial search value for uncontrolled usage. @default '' */
|
|
18
|
+
defaultSearch?: string;
|
|
19
|
+
/** Fires when the search value changes. */
|
|
20
|
+
onSearchChange?: (value: string) => void;
|
|
21
|
+
/** Whether selecting an item closes the menu. @default true */
|
|
22
|
+
closeOnSelect?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare const DropdownSearchMenu: {
|
|
25
|
+
({ children, open: openProp, defaultOpen, onOpenChange, search: searchProp, defaultSearch, onSearchChange, closeOnSelect, }: DropdownSearchMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
displayName: string;
|
|
27
|
+
};
|
|
28
|
+
/** Props for DropdownSearchMenuTrigger. Use `asChild` to compose with a custom trigger. */
|
|
29
|
+
export type DropdownSearchMenuTriggerProps = PopoverTriggerProps;
|
|
30
|
+
declare const DropdownSearchMenuTrigger: {
|
|
31
|
+
(props: DropdownSearchMenuTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
displayName: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Props for DropdownSearchMenuContent — the floating panel containing the
|
|
36
|
+
* search field, divider, and scrollable list of items.
|
|
37
|
+
*/
|
|
38
|
+
export interface DropdownSearchMenuContentProps extends PopoverContentProps {
|
|
39
|
+
/** Placeholder for the search field. */
|
|
40
|
+
searchPlaceholder?: string;
|
|
41
|
+
/** Accessible label for the search field (defaults to `searchPlaceholder`). */
|
|
42
|
+
searchAriaLabel?: string;
|
|
43
|
+
/** Content shown when no item children are present (no-matches state). */
|
|
44
|
+
emptyMessage?: React.ReactNode;
|
|
45
|
+
}
|
|
46
|
+
declare const DropdownSearchMenuContent: {
|
|
47
|
+
({ className, searchPlaceholder, searchAriaLabel, emptyMessage, align, sideOffset, children, ...props }: DropdownSearchMenuContentProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
displayName: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Props for DropdownSearchMenuItem — a selectable row mirroring
|
|
52
|
+
* `DropdownMenuItem` content: leading icon, label, and optional trailing text.
|
|
53
|
+
*/
|
|
54
|
+
export interface DropdownSearchMenuItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {
|
|
55
|
+
/** Unique value identifying the item. Passed to `onSelect`. */
|
|
56
|
+
value: string;
|
|
57
|
+
/** Fires with `value` when the item is chosen (click or Enter). */
|
|
58
|
+
onSelect?: (value: string) => void;
|
|
59
|
+
/** Icon or flag element rendered before the label. */
|
|
60
|
+
icon?: React.ReactNode;
|
|
61
|
+
/** Right-aligned trailing content (e.g. a dial code). */
|
|
62
|
+
trailing?: React.ReactNode;
|
|
63
|
+
/** Highlights the item as the currently selected value (brand color + fill). @default false */
|
|
64
|
+
isActive?: boolean;
|
|
65
|
+
/** Prevents selection and greys out the item. @default false */
|
|
66
|
+
disabled?: boolean;
|
|
67
|
+
}
|
|
68
|
+
declare const DropdownSearchMenuItem: {
|
|
69
|
+
({ className, value, onSelect, icon, trailing, isActive, disabled, children, onMouseEnter, ...props }: DropdownSearchMenuItemProps): import("react/jsx-runtime").JSX.Element;
|
|
70
|
+
displayName: string;
|
|
71
|
+
};
|
|
72
|
+
export { DropdownSearchMenu, DropdownSearchMenuTrigger, DropdownSearchMenuContent, DropdownSearchMenuItem, };
|
|
73
|
+
//# sourceMappingURL=DropdownSearchMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropdownSearchMenu.d.ts","sourceRoot":"","sources":["../../../src/components/DropdownSearchMenu/DropdownSearchMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAGL,KAAK,mBAAmB,EAExB,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAA;AAkDnB;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,2CAA2C;IAC3C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,QAAA,MAAM,kBAAkB;iIASrB,uBAAuB;;CAqDzB,CAAA;AAED,2FAA2F;AAC3F,MAAM,MAAM,8BAA8B,GAAG,mBAAmB,CAAA;AAEhE,QAAA,MAAM,yBAAyB;YAAW,8BAA8B;;CAEvE,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA+B,SAAQ,mBAAmB;IACzE,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC/B;AAED,QAAA,MAAM,yBAAyB;6GAS5B,8BAA8B;;CAqJhC,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,2BACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,sDAAsD;IACtD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,QAAA,MAAM,sBAAsB;2GAWzB,2BAA2B;;CAsE7B,CAAA;AAOD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,GACvB,CAAA"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { jsx as t, jsxs as z } from "react/jsx-runtime";
|
|
2
|
+
import * as r from "react";
|
|
3
|
+
import { Popover as T, PopoverTrigger as Y, PopoverContent as j } from "../Popover/Popover.js";
|
|
4
|
+
import { MagnifyingGlass as K } from "../Icons/CustomIcons.js";
|
|
5
|
+
import { cn as N } from "../../utils/cn.js";
|
|
6
|
+
import { typographyVariants as U, Typography as A } from "../Typography/Typography.js";
|
|
7
|
+
const R = r.createContext(null), E = () => {
|
|
8
|
+
const s = r.useContext(R);
|
|
9
|
+
if (!s)
|
|
10
|
+
throw new Error(
|
|
11
|
+
"DropdownSearchMenu components must be used within a <DropdownSearchMenu>"
|
|
12
|
+
);
|
|
13
|
+
return s;
|
|
14
|
+
}, V = ({
|
|
15
|
+
children: s,
|
|
16
|
+
open: c,
|
|
17
|
+
defaultOpen: p = !1,
|
|
18
|
+
onOpenChange: d,
|
|
19
|
+
search: m,
|
|
20
|
+
defaultSearch: w = "",
|
|
21
|
+
onSearchChange: n,
|
|
22
|
+
closeOnSelect: x = !0
|
|
23
|
+
}) => {
|
|
24
|
+
const u = r.useId(), [b, k] = r.useState(null), l = c !== void 0, [f, v] = r.useState(p), i = l ? c : f, a = m !== void 0, [I, M] = r.useState(w), y = a ? m : I, h = r.useCallback(
|
|
25
|
+
(e) => {
|
|
26
|
+
a || M(e), n == null || n(e);
|
|
27
|
+
},
|
|
28
|
+
[a, n]
|
|
29
|
+
), D = r.useCallback(
|
|
30
|
+
(e) => {
|
|
31
|
+
l || v(e), d == null || d(e), e || h("");
|
|
32
|
+
},
|
|
33
|
+
[l, d, h]
|
|
34
|
+
), o = r.useMemo(
|
|
35
|
+
() => ({
|
|
36
|
+
search: y,
|
|
37
|
+
setSearch: h,
|
|
38
|
+
open: i,
|
|
39
|
+
setOpen: D,
|
|
40
|
+
activeId: b,
|
|
41
|
+
setActiveId: k,
|
|
42
|
+
listboxId: u,
|
|
43
|
+
closeOnSelect: x
|
|
44
|
+
}),
|
|
45
|
+
[y, h, i, D, b, u, x]
|
|
46
|
+
);
|
|
47
|
+
return /* @__PURE__ */ t(R.Provider, { value: o, children: /* @__PURE__ */ t(T, { open: i, onOpenChange: D, children: s }) });
|
|
48
|
+
}, $ = (s) => /* @__PURE__ */ t(Y, { "data-slot": "dropdown-search-menu-trigger", ...s }), q = ({
|
|
49
|
+
className: s,
|
|
50
|
+
searchPlaceholder: c,
|
|
51
|
+
searchAriaLabel: p,
|
|
52
|
+
emptyMessage: d,
|
|
53
|
+
align: m = "start",
|
|
54
|
+
sideOffset: w = 8,
|
|
55
|
+
children: n,
|
|
56
|
+
...x
|
|
57
|
+
}) => {
|
|
58
|
+
const { search: u, setSearch: b, setOpen: k, activeId: l, setActiveId: f, listboxId: v } = E(), i = r.useRef(null), a = r.useRef(null), M = r.Children.toArray(n).filter(Boolean).length === 0, y = r.useCallback(
|
|
59
|
+
() => {
|
|
60
|
+
var o;
|
|
61
|
+
return Array.from(
|
|
62
|
+
((o = i.current) == null ? void 0 : o.querySelectorAll(
|
|
63
|
+
'[role="option"]:not([aria-disabled="true"])'
|
|
64
|
+
)) ?? []
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
[]
|
|
68
|
+
);
|
|
69
|
+
r.useEffect(() => {
|
|
70
|
+
f(null);
|
|
71
|
+
}, [u, f]);
|
|
72
|
+
const h = (o) => {
|
|
73
|
+
const e = y();
|
|
74
|
+
if (e.length === 0) return;
|
|
75
|
+
const g = e.findIndex((O) => O.id === l), S = g < 0 ? o === 1 ? 0 : e.length - 1 : Math.min(Math.max(g + o, 0), e.length - 1), C = e[S];
|
|
76
|
+
f(C.id), C.scrollIntoView({ block: "nearest" });
|
|
77
|
+
}, D = (o) => {
|
|
78
|
+
switch (o.key) {
|
|
79
|
+
case "ArrowDown":
|
|
80
|
+
o.preventDefault(), h(1);
|
|
81
|
+
break;
|
|
82
|
+
case "ArrowUp":
|
|
83
|
+
o.preventDefault(), h(-1);
|
|
84
|
+
break;
|
|
85
|
+
case "Enter": {
|
|
86
|
+
o.preventDefault();
|
|
87
|
+
const e = y(), g = e.find((S) => S.id === l) ?? e[0];
|
|
88
|
+
g == null || g.click();
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case "Escape":
|
|
92
|
+
k(!1);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return /* @__PURE__ */ z(
|
|
97
|
+
j,
|
|
98
|
+
{
|
|
99
|
+
align: m,
|
|
100
|
+
sideOffset: w,
|
|
101
|
+
onOpenAutoFocus: (o) => {
|
|
102
|
+
var e;
|
|
103
|
+
o.preventDefault(), (e = a.current) == null || e.focus();
|
|
104
|
+
},
|
|
105
|
+
className: N(
|
|
106
|
+
"flex w-[280px] flex-col overflow-hidden rounded-comp-dropdown-menu-radius bg-comp-select-fill-def p-0 dropdown-shadow-default",
|
|
107
|
+
s
|
|
108
|
+
),
|
|
109
|
+
...x,
|
|
110
|
+
children: [
|
|
111
|
+
/* @__PURE__ */ t("div", { className: "p-sm", children: /* @__PURE__ */ z("div", { className: "flex items-center gap-sm rounded-comp-dropdown-menu-radius-item px-lg py-sm", children: [
|
|
112
|
+
/* @__PURE__ */ t(
|
|
113
|
+
K,
|
|
114
|
+
{
|
|
115
|
+
"aria-hidden": "true",
|
|
116
|
+
className: "size-icon-small shrink-0 text-icon-dark-secondary-def"
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ t(
|
|
120
|
+
"input",
|
|
121
|
+
{
|
|
122
|
+
ref: a,
|
|
123
|
+
type: "text",
|
|
124
|
+
role: "combobox",
|
|
125
|
+
"aria-expanded": !0,
|
|
126
|
+
"aria-controls": v,
|
|
127
|
+
"aria-autocomplete": "list",
|
|
128
|
+
"aria-activedescendant": l ?? void 0,
|
|
129
|
+
"aria-label": p ?? c,
|
|
130
|
+
value: u,
|
|
131
|
+
placeholder: c,
|
|
132
|
+
onChange: (o) => b(o.target.value),
|
|
133
|
+
onKeyDown: D,
|
|
134
|
+
className: N(
|
|
135
|
+
U({
|
|
136
|
+
size: "sm",
|
|
137
|
+
weight: "regular",
|
|
138
|
+
fixY: !0
|
|
139
|
+
}),
|
|
140
|
+
"w-full bg-transparent text-comp-dropdown-menu-text-base-def outline-none",
|
|
141
|
+
// The field is auto-focused on open, so the placeholder is redundant
|
|
142
|
+
// once focused — hide it to keep the focused field clean.
|
|
143
|
+
"placeholder:text-text-dark-tertiary focus:placeholder:text-transparent"
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
] }) }),
|
|
148
|
+
/* @__PURE__ */ t(
|
|
149
|
+
"div",
|
|
150
|
+
{
|
|
151
|
+
"aria-hidden": "true",
|
|
152
|
+
className: "h-0 w-full border-b border-stroke-base-primary"
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
/* @__PURE__ */ t("div", { className: "py-sm pr-1 pl-sm", children: /* @__PURE__ */ t(
|
|
156
|
+
"div",
|
|
157
|
+
{
|
|
158
|
+
ref: i,
|
|
159
|
+
id: v,
|
|
160
|
+
role: "listbox",
|
|
161
|
+
"aria-label": p ?? c,
|
|
162
|
+
className: N(
|
|
163
|
+
"flex max-h-[280px] flex-col gap-comp-dropdown-menu-gap-phone-code overflow-y-auto pr-1",
|
|
164
|
+
"[&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-stroke-base-secondary hover:[&::-webkit-scrollbar-thumb]:bg-stroke-base-primary [&::-webkit-scrollbar-track]:bg-transparent"
|
|
165
|
+
),
|
|
166
|
+
children: M ? /* @__PURE__ */ t("div", { className: "px-lg py-md", role: "presentation", children: /* @__PURE__ */ t(
|
|
167
|
+
A,
|
|
168
|
+
{
|
|
169
|
+
component: "span",
|
|
170
|
+
size: "sm",
|
|
171
|
+
weight: "regular",
|
|
172
|
+
className: "text-comp-dropdown-menu-text-base-def",
|
|
173
|
+
children: d
|
|
174
|
+
}
|
|
175
|
+
) }) : n
|
|
176
|
+
}
|
|
177
|
+
) })
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
}, B = ({
|
|
182
|
+
className: s,
|
|
183
|
+
value: c,
|
|
184
|
+
onSelect: p,
|
|
185
|
+
icon: d,
|
|
186
|
+
trailing: m,
|
|
187
|
+
isActive: w = !1,
|
|
188
|
+
disabled: n = !1,
|
|
189
|
+
children: x,
|
|
190
|
+
onMouseEnter: u,
|
|
191
|
+
...b
|
|
192
|
+
}) => {
|
|
193
|
+
const { activeId: k, setOpen: l, listboxId: f, closeOnSelect: v } = E(), i = `${f}-${encodeURIComponent(c)}`, a = k === i, I = () => {
|
|
194
|
+
n || (p == null || p(c), v && l(!1));
|
|
195
|
+
};
|
|
196
|
+
return /* @__PURE__ */ z(
|
|
197
|
+
"div",
|
|
198
|
+
{
|
|
199
|
+
id: i,
|
|
200
|
+
role: "option",
|
|
201
|
+
"aria-selected": w,
|
|
202
|
+
"aria-disabled": n || void 0,
|
|
203
|
+
"data-active": a || void 0,
|
|
204
|
+
className: N(
|
|
205
|
+
"flex cursor-pointer items-center gap-sm rounded-comp-dropdown-menu-radius-item px-lg py-md outline-0 transition-colors",
|
|
206
|
+
n ? "pointer-events-none text-comp-dropdown-menu-text-phone-code-disabled" : [
|
|
207
|
+
"text-comp-dropdown-menu-text-phone-code-def",
|
|
208
|
+
// Mouse hover — lighter fill.
|
|
209
|
+
"hover:bg-comp-dropdown-menu-fill-phone-code-hover hover:text-comp-dropdown-menu-text-phone-code-hover",
|
|
210
|
+
// Selected value — brand fill/text (unless the keyboard highlight is on it).
|
|
211
|
+
w && !a && "bg-comp-dropdown-menu-fill-phone-code-active text-comp-dropdown-menu-text-phone-code-active",
|
|
212
|
+
// Keyboard-navigated row — distinct darker "focused/pressed" fill.
|
|
213
|
+
a && "bg-comp-dropdown-menu-fill-phone-code-focused text-comp-dropdown-menu-text-phone-code-focused hover:bg-comp-dropdown-menu-fill-phone-code-focused hover:text-comp-dropdown-menu-text-phone-code-focused"
|
|
214
|
+
],
|
|
215
|
+
s
|
|
216
|
+
),
|
|
217
|
+
onClick: I,
|
|
218
|
+
onMouseEnter: u,
|
|
219
|
+
...b,
|
|
220
|
+
children: [
|
|
221
|
+
d && /* @__PURE__ */ t("span", { className: "block size-icon-small shrink-0 [&>svg]:block [&>svg]:size-icon-small", children: d }),
|
|
222
|
+
/* @__PURE__ */ t(
|
|
223
|
+
A,
|
|
224
|
+
{
|
|
225
|
+
component: "span",
|
|
226
|
+
size: "sm",
|
|
227
|
+
weight: "medium",
|
|
228
|
+
fixY: !0,
|
|
229
|
+
className: "min-w-0 flex-1 truncate",
|
|
230
|
+
children: x
|
|
231
|
+
}
|
|
232
|
+
),
|
|
233
|
+
m != null && /* @__PURE__ */ t(
|
|
234
|
+
A,
|
|
235
|
+
{
|
|
236
|
+
component: "span",
|
|
237
|
+
size: "sm",
|
|
238
|
+
weight: "medium",
|
|
239
|
+
fixY: !0,
|
|
240
|
+
className: "shrink-0 text-right",
|
|
241
|
+
children: m
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
V.displayName = "DropdownSearchMenu";
|
|
249
|
+
$.displayName = "DropdownSearchMenuTrigger";
|
|
250
|
+
q.displayName = "DropdownSearchMenuContent";
|
|
251
|
+
B.displayName = "DropdownSearchMenuItem";
|
|
252
|
+
export {
|
|
253
|
+
V as DropdownSearchMenu,
|
|
254
|
+
q as DropdownSearchMenuContent,
|
|
255
|
+
B as DropdownSearchMenuItem,
|
|
256
|
+
$ as DropdownSearchMenuTrigger
|
|
257
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { DropdownSearchMenu } from './DropdownSearchMenu';
|
|
3
|
+
declare const meta: Meta<typeof DropdownSearchMenu>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof DropdownSearchMenu>;
|
|
6
|
+
/**
|
|
7
|
+
* Interactive example with plain, label-only items. Selecting an option closes
|
|
8
|
+
* the menu; the search field filters the list. The full controlled wiring is
|
|
9
|
+
* inline so the code preview teaches the real integration pattern.
|
|
10
|
+
*/
|
|
11
|
+
export declare const Default: Story;
|
|
12
|
+
/**
|
|
13
|
+
* Menu rendered open so the visual-regression suite captures the portaled panel
|
|
14
|
+
* — search field, divider, and the scrollable list with an active (selected)
|
|
15
|
+
* item. The closed `Default` story cannot show it.
|
|
16
|
+
*/
|
|
17
|
+
export declare const OpenState: Story;
|
|
18
|
+
/**
|
|
19
|
+
* No-matches state: when the filtered list is empty, `emptyMessage` renders in
|
|
20
|
+
* place of the items.
|
|
21
|
+
*/
|
|
22
|
+
export declare const NoResults: Story;
|
|
23
|
+
/**
|
|
24
|
+
* Rich items: a leading `icon` (flag) and right-aligned `trailing` content
|
|
25
|
+
* (dial code). This is the shape `PhoneInput`'s country selector uses.
|
|
26
|
+
*/
|
|
27
|
+
export declare const WithIconAndTrailing: Story;
|
|
28
|
+
//# sourceMappingURL=DropdownSearchMenu.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropdownSearchMenu.stories.d.ts","sourceRoot":"","sources":["../../../src/components/DropdownSearchMenu/DropdownSearchMenu.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAI3D,OAAO,EACL,kBAAkB,EAInB,MAAM,sBAAsB,CAAA;AAE7B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,kBAAkB,CAuCzC,CAAA;AAED,eAAe,IAAI,CAAA;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAchD;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,KAqDrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KA6BvB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAqBvB,CAAA;AAYD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgCjC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DropdownSearchMenu/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CountryData } from 'react-international-phone';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the internal CountrySelector segment. Not exported from the
|
|
4
|
+
* library — consumers configure it through `PhoneInput`.
|
|
5
|
+
*/
|
|
6
|
+
export interface CountrySelectorProps {
|
|
7
|
+
/** iso2 code of the currently selected country (e.g. `"cz"`). */
|
|
8
|
+
selectedCountry: string;
|
|
9
|
+
/** Fires with the iso2 of the newly selected country. */
|
|
10
|
+
onCountryChange: (iso2: string) => void;
|
|
11
|
+
/** Raw country dataset used to build the list. */
|
|
12
|
+
countries: CountryData[];
|
|
13
|
+
/** Accessible label for the trigger button. */
|
|
14
|
+
ariaLabel: string;
|
|
15
|
+
/** Placeholder for the search field. */
|
|
16
|
+
searchPlaceholder: string;
|
|
17
|
+
/** Message rendered when the search yields no matches. */
|
|
18
|
+
noResultsText: string;
|
|
19
|
+
/** Disables the trigger and greys out its content. @default false */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Applies error border colors to the divider. @default false */
|
|
22
|
+
error?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Left segment of `PhoneInput`: a flag + dial-code button that opens a
|
|
26
|
+
* searchable country list in a `DropdownSearchMenu`. The right border acts as
|
|
27
|
+
* the divider between the country selector and the phone number field,
|
|
28
|
+
* matching the wrapper's border color across `group` hover/focus/error states.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CountrySelector: {
|
|
31
|
+
({ selectedCountry, onCountryChange, countries, ariaLabel, searchPlaceholder, noResultsText, disabled, error, }: CountrySelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
displayName: string;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=CountrySelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CountrySelector.d.ts","sourceRoot":"","sources":["../../../src/components/PhoneInput/CountrySelector.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,WAAW,EAGjB,MAAM,2BAA2B,CAAA;AAWlC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAA;IACvB,yDAAyD;IACzD,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,kDAAkD;IAClD,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAA;IACjB,wCAAwC;IACxC,iBAAiB,EAAE,MAAM,CAAA;IACzB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe;qHASzB,oBAAoB;;CAiGtB,CAAA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { jsxs as p, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useState as u, useMemo as a } from "react";
|
|
3
|
+
import { parseCountry as v, FlagImage as l } from "react-international-phone";
|
|
4
|
+
import { DropdownSearchMenu as M, DropdownSearchMenuTrigger as y, DropdownSearchMenuContent as z, DropdownSearchMenuItem as D } from "../DropdownSearchMenu/DropdownSearchMenu.js";
|
|
5
|
+
import { cn as f } from "../../utils/cn.js";
|
|
6
|
+
import { Typography as N } from "../Typography/Typography.js";
|
|
7
|
+
import { AltArrowUpOutline as A } from "@solar-icons/react-perf";
|
|
8
|
+
const O = ({
|
|
9
|
+
selectedCountry: c,
|
|
10
|
+
onCountryChange: h,
|
|
11
|
+
countries: d,
|
|
12
|
+
ariaLabel: g,
|
|
13
|
+
searchPlaceholder: x,
|
|
14
|
+
noResultsText: C,
|
|
15
|
+
disabled: t = !1,
|
|
16
|
+
error: b = !1
|
|
17
|
+
}) => {
|
|
18
|
+
const [m, w] = u(!1), [i, k] = u(""), o = a(
|
|
19
|
+
() => d.map((e) => v(e)),
|
|
20
|
+
[d]
|
|
21
|
+
), n = a(
|
|
22
|
+
() => o.find((e) => e.iso2 === c) ?? o[0],
|
|
23
|
+
[o, c]
|
|
24
|
+
), S = a(() => {
|
|
25
|
+
const e = i.trim().toLowerCase();
|
|
26
|
+
return e ? o.filter(
|
|
27
|
+
(s) => s.name.toLowerCase().includes(e) || s.iso2.includes(e) || s.dialCode.includes(e.replace(/^\+/, ""))
|
|
28
|
+
) : o;
|
|
29
|
+
}, [o, i]);
|
|
30
|
+
return /* @__PURE__ */ p(
|
|
31
|
+
M,
|
|
32
|
+
{
|
|
33
|
+
open: m,
|
|
34
|
+
onOpenChange: w,
|
|
35
|
+
search: i,
|
|
36
|
+
onSearchChange: k,
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ r(y, { asChild: !0, children: /* @__PURE__ */ p(
|
|
39
|
+
"button",
|
|
40
|
+
{
|
|
41
|
+
type: "button",
|
|
42
|
+
disabled: t,
|
|
43
|
+
"aria-label": g,
|
|
44
|
+
className: f(
|
|
45
|
+
"flex h-full shrink-0 items-center gap-sm border-r px-comp-input-p-hor transition-colors outline-none",
|
|
46
|
+
"focus-visible-default",
|
|
47
|
+
"border-comp-input-stroke-def",
|
|
48
|
+
"group-hover:border-comp-input-stroke-hover",
|
|
49
|
+
"group-focus-within:border-comp-input-icon-brand-focused",
|
|
50
|
+
b && "border-comp-input-stroke-error-def group-focus-within:border-comp-input-stroke-error-def group-hover:border-comp-input-stroke-error-def",
|
|
51
|
+
t ? "cursor-not-allowed border-comp-input-stroke-disabled" : "cursor-pointer"
|
|
52
|
+
),
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ r(l, { iso2: n.iso2, size: "20px" }),
|
|
55
|
+
/* @__PURE__ */ p(
|
|
56
|
+
N,
|
|
57
|
+
{
|
|
58
|
+
size: "input",
|
|
59
|
+
weight: "medium",
|
|
60
|
+
fixY: !0,
|
|
61
|
+
component: "span",
|
|
62
|
+
className: t ? "text-comp-input-text-disabled" : "text-comp-input-text-primary",
|
|
63
|
+
children: [
|
|
64
|
+
"+",
|
|
65
|
+
n.dialCode
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ r(
|
|
70
|
+
A,
|
|
71
|
+
{
|
|
72
|
+
"aria-hidden": "true",
|
|
73
|
+
className: f(
|
|
74
|
+
"size-icon-small shrink-0 transition-transform duration-200",
|
|
75
|
+
m ? "rotate-0" : "rotate-180",
|
|
76
|
+
t ? "text-comp-input-text-disabled" : "text-icon-dark-secondary-def"
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
) }),
|
|
83
|
+
/* @__PURE__ */ r(
|
|
84
|
+
z,
|
|
85
|
+
{
|
|
86
|
+
searchPlaceholder: x,
|
|
87
|
+
emptyMessage: C,
|
|
88
|
+
children: S.map((e) => /* @__PURE__ */ r(
|
|
89
|
+
D,
|
|
90
|
+
{
|
|
91
|
+
value: e.iso2,
|
|
92
|
+
onSelect: h,
|
|
93
|
+
isActive: e.iso2 === n.iso2,
|
|
94
|
+
icon: /* @__PURE__ */ r(l, { iso2: e.iso2, size: "20px" }),
|
|
95
|
+
trailing: `+${e.dialCode}`,
|
|
96
|
+
children: e.name
|
|
97
|
+
},
|
|
98
|
+
e.iso2
|
|
99
|
+
))
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
O.displayName = "CountrySelector";
|
|
107
|
+
export {
|
|
108
|
+
O as CountrySelector
|
|
109
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import { VariantProps } from 'class-variance-authority';
|
|
3
|
+
import { CountryData, ParsedCountry } from 'react-international-phone';
|
|
4
|
+
/**
|
|
5
|
+
* Metadata passed alongside the E.164 value to `PhoneInput`'s `onChange`.
|
|
6
|
+
*/
|
|
7
|
+
export interface PhoneInputChangeMeta {
|
|
8
|
+
/** The formatted, human-readable value shown in the input (e.g. `"777 123 456"`). */
|
|
9
|
+
inputValue: string;
|
|
10
|
+
/** The resolved country the number currently belongs to. */
|
|
11
|
+
country: ParsedCountry;
|
|
12
|
+
}
|
|
13
|
+
declare const phoneWrapperVariants: (props?: ({
|
|
14
|
+
size?: "xs" | "sm" | "lg" | "base" | null | undefined;
|
|
15
|
+
error?: boolean | null | undefined;
|
|
16
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Props for the PhoneInput component.
|
|
19
|
+
*
|
|
20
|
+
* A segmented phone-number field: a searchable country selector (flag + dial
|
|
21
|
+
* code) on the left and a formatted national-number input on the right. The
|
|
22
|
+
* value is composed and emitted as a single E.164 string. Formatting, country
|
|
23
|
+
* detection, and dial-code handling are powered by
|
|
24
|
+
* [react-international-phone](https://react-international-phone.vercel.app/).
|
|
25
|
+
*
|
|
26
|
+
* Extends native input attributes except `size`/`type`/`prefix` (managed
|
|
27
|
+
* internally) and `value`/`defaultValue`/`onChange` (narrowed to the phone
|
|
28
|
+
* string contract below).
|
|
29
|
+
*/
|
|
30
|
+
export interface PhoneInputProps extends Omit<ComponentPropsWithoutRef<'input'>, 'size' | 'type' | 'prefix' | 'value' | 'defaultValue' | 'onChange'>, VariantProps<typeof phoneWrapperVariants> {
|
|
31
|
+
/** Label text rendered above the input. */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** Helper or error text rendered below the input. */
|
|
34
|
+
hint?: string;
|
|
35
|
+
/** Controls height and typography. @default 'base' */
|
|
36
|
+
size?: 'xs' | 'sm' | 'base' | 'lg';
|
|
37
|
+
/** Applies error border and hint styling. @default false */
|
|
38
|
+
error?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Controlled phone value in E.164 format (e.g. `"+420777123456"`). Pair with
|
|
41
|
+
* `onChange` for controlled usage.
|
|
42
|
+
*/
|
|
43
|
+
value?: string;
|
|
44
|
+
/** Initial phone value in E.164 format for uncontrolled usage. */
|
|
45
|
+
defaultValue?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Fires on every change with the composed E.164 phone string and formatting
|
|
48
|
+
* metadata. The phone string is empty (`""`) when no number is entered.
|
|
49
|
+
*/
|
|
50
|
+
onChange?: (phone: string, meta: PhoneInputChangeMeta) => void;
|
|
51
|
+
/** ISO2 code of the initial country selection (e.g. `"cz"`). @default 'cz' */
|
|
52
|
+
defaultCountry?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Country dataset used for the selector and number guessing. Rarely needed —
|
|
55
|
+
* override to restrict or reorder the available countries.
|
|
56
|
+
* @default defaultCountries
|
|
57
|
+
*/
|
|
58
|
+
countries?: CountryData[];
|
|
59
|
+
/**
|
|
60
|
+
* Hides the required asterisk in the label even when `required` is `true`.
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
disableRequiredAsterisk?: boolean;
|
|
64
|
+
/** Custom content rendered inline next to the label. Takes precedence over `infoTooltip`. */
|
|
65
|
+
labelExtra?: ReactNode;
|
|
66
|
+
/** Tooltip content shown in an info icon next to the label. Ignored when `labelExtra` is provided. */
|
|
67
|
+
infoTooltip?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Accessible label for the country selector trigger.
|
|
70
|
+
* @default translations.phoneInput.countrySelectorAriaLabel
|
|
71
|
+
*/
|
|
72
|
+
countrySelectorAriaLabel?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Placeholder for the country search field.
|
|
75
|
+
* @default translations.phoneInput.searchPlaceholder
|
|
76
|
+
*/
|
|
77
|
+
searchPlaceholder?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Message shown when the country search yields no matches.
|
|
80
|
+
* @default translations.phoneInput.noResults
|
|
81
|
+
*/
|
|
82
|
+
noResultsText?: string;
|
|
83
|
+
}
|
|
84
|
+
export declare const PhoneInput: import('react').ForwardRefExoticComponent<PhoneInputProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=PhoneInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneInput.d.ts","sourceRoot":"","sources":["../../../src/components/PhoneInput/PhoneInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EAMf,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,KAAK,YAAY,EAAO,MAAM,0BAA0B,CAAA;AACjE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,aAAa,EAGnB,MAAM,2BAA2B,CAAA;AAOlC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAA;IAClB,4DAA4D;IAC5D,OAAO,EAAE,aAAa,CAAA;CACvB;AAKD,QAAA,MAAM,oBAAoB;;;8EAyBzB,CAAA;AAcD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eACf,SAAQ,IAAI,CACR,wBAAwB,CAAC,OAAO,CAAC,EACjC,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CACnE,EACD,YAAY,CAAC,OAAO,oBAAoB,CAAC;IAC3C,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;IAClC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC9D,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,WAAW,EAAE,CAAA;IACzB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,6FAA6F;IAC7F,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,sGAAsG;IACtG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,UAAU,8GA6HtB,CAAA"}
|