laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
347 lines (346 loc) • 11 kB
JavaScript
"use client";
import { jsxs as x, jsx as r } from "react/jsx-runtime";
import { useDebounce as me } from "../../hooks/use-debounce.js";
import { cva as ue } from "../../node_modules/class-variance-authority/dist/index.js";
import * as k from "react";
import { useState as y, useEffect as A, useCallback as j } from "react";
import { designTokens as u } from "../design-tokens.js";
import { cn as z } from "../../lib/utils.js";
import { Checkbox as he } from "./checkbox.js";
import { Command as ge, CommandInput as pe, CommandList as we, CommandEmpty as xe, CommandGroup as _, CommandItem as O } from "./command.js";
import { Icon as Z } from "./icon.js";
import { Label as ye } from "./label.js";
import { Popover as Ne, PopoverTrigger as be, PopoverContent as Ce } from "./popover.js";
import Ae from "../../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
const Se = ue(
z(
u.input.base,
u.radius.default,
u.interaction.disabled,
"flex items-center justify-between whitespace-nowrap transition-all [&>span]:line-clamp-1",
"data-[placeholder]:text-d-muted-foreground",
"focus:outline-none"
),
{
variants: {
size: {
default: u.sizes.default,
sm: u.sizes.sm,
lg: u.sizes.lg
}
},
defaultVariants: {
size: "default"
}
}
);
function $e({
fetcher: i,
initialOptions: n,
debounce: N = 300,
renderOptionItem: S,
resolveOptionValue: s,
renderSelectedValue: c,
notFound: h,
label: C,
placeholder: f = "Select...",
value: t,
onChange: g,
disabled: M = !1,
className: v,
wrpClassName: E,
noResultsMessage: I,
clearable: R = !0,
multiple: o = !1,
size: V,
id: ee,
"data-testid": re
}) {
const [m, P] = y(!1), L = k.useRef(null), F = k.useRef(null), te = k.useRef(null), [ne, W] = y({ loading: !1, error: null }), [X, se] = y(""), B = me(X, N), [$, ce] = y(/* @__PURE__ */ new Map()), [G, K] = y([]), [q, ae] = y(0), [H, J] = y(() => n?.length ? new Map(
n.map((e) => [s(e), e])
) : /* @__PURE__ */ new Map());
A(() => {
n?.length && (K((e) => e.length ? e : n), J((e) => {
const p = new Map(e);
return n.forEach((a) => p.set(s(a), a)), p;
}));
}, [n, s]);
const [D, Q] = y([]), T = j(
(e) => {
if (!e) {
Q([]);
return;
}
const a = (Array.isArray(e) ? e : [e]).map((l) => {
const d = H.get(l);
if (d) return d;
if (n?.length) {
const b = n.find(
(fe) => s(fe) === l
);
if (b) return b;
}
return G.find(
(b) => s(b) === l
) ?? null;
}).filter(Boolean);
Q(a);
},
[H, s, n, G]
);
A(() => {
T(t);
}, [t, T]);
const U = k.useMemo(() => o ? null : D[0] ?? null, [o, D]);
A(() => {
if (!m) return;
const e = B || "";
if ($.has(e)) {
K($.get(e));
return;
}
(async () => {
try {
W({ loading: !0, error: null });
const a = await i(B), l = (() => {
if (!n?.length) return a;
const d = /* @__PURE__ */ new Map();
return n.forEach((w) => {
d.set(s(w), w);
}), a.forEach((w) => {
d.set(s(w), w);
}), Array.from(d.values());
})();
ce((d) => new Map(d).set(e, l)), K(l), J((d) => {
const w = new Map(d);
return l.forEach((b) => w.set(s(b), b)), w;
});
} catch (a) {
W({
loading: !1,
error: a instanceof Error ? a.message : "Failed to fetch options"
});
} finally {
W((a) => ({ ...a, loading: !1 }));
}
})();
}, [
m,
B,
$,
i,
s,
n
]), A(() => {
m && T(t);
}, [m, T, t]), A(() => {
m && L.current && L.current.focus();
}, [m]), A(() => {
if (!m || !F.current) return;
const e = F.current.getBoundingClientRect();
ae(e.width);
}, [m]);
const oe = j(
(e) => {
g?.(R && e === t ? "" : e), P(!1);
},
[t, g, R]
), de = j(
(e) => {
if (!o) return;
const p = Array.isArray(t) ? t : [], a = p.includes(e);
let l;
a ? l = p.filter((d) => d !== e) : l = [...p, e], g?.(l);
},
[t, g, o]
), le = j(
(e) => {
e.stopPropagation(), e.preventDefault(), g?.(o ? [] : ""), P(!1);
},
[g]
), ie = k.useId(), Y = ee ?? ie;
return /* @__PURE__ */ x("div", { className: z("flex flex-col gap-1.5", E), children: [
C && /* @__PURE__ */ r(ye, { htmlFor: Y, children: C }),
/* @__PURE__ */ x(Ne, { open: m, onOpenChange: P, children: [
/* @__PURE__ */ r(be, { asChild: !0, children: /* @__PURE__ */ r(
"button",
{
id: Y,
"data-testid": re,
ref: F,
type: "button",
disabled: M,
className: z(
Se({ size: V }),
"!border-d-border/50 border !shadow-none",
M && "cursor-not-allowed opacity-50",
"font-normal",
"w-full",
"w-full",
u.focusRing,
m && u.activeRing,
v
),
children: /* @__PURE__ */ x("div", { className: "flex w-full flex-1 items-center justify-between overflow-hidden", children: [
o ? Array.isArray(t) && t.length > 0 ? /* @__PURE__ */ r("div", { className: "min-w-0 flex-1 truncate text-left", children: t.length === 1 ? D[0] && c(D[0]) : `${t.length} elementi selezionati` }) : /* @__PURE__ */ r("span", { className: "text-d-muted-foreground truncate text-left", children: f }) : U ? /* @__PURE__ */ r("div", { className: "min-w-0 flex-1 truncate text-left", children: c(U) }) : /* @__PURE__ */ r("span", { className: "text-d-muted-foreground truncate text-left", children: f }),
/* @__PURE__ */ x("div", { className: "flex flex-shrink-0 items-center justify-end gap-1", children: [
R && (o && Array.isArray(t) && t.length > 0 || !o && U) && /* @__PURE__ */ r(
"div",
{
className: "border-d-input bg-d-accent cursor-pointer rounded-full p-1",
onClick: le,
onMouseDown: (e) => e.preventDefault(),
"aria-label": "Clear selection",
children: /* @__PURE__ */ r(
Z,
{
name: "X",
size: "xs",
className: "!text-d-foreground opacity-50"
}
)
}
),
/* @__PURE__ */ r(
Z,
{
name: "ChevronsUpDown",
size: "xs",
className: "!text-d-foreground opacity-50"
}
)
] })
] })
}
) }),
/* @__PURE__ */ r(
Ce,
{
className: z("p-0"),
style: { width: q ? `${q}px` : void 0 },
align: "start",
side: "bottom",
sideOffset: 4,
onWheel: (e) => e.stopPropagation(),
avoidCollisions: !0,
collisionPadding: 8,
children: /* @__PURE__ */ r(
Re,
{
inputRef: L,
commandListRef: te,
placeholder: f,
searchTerm: X,
onSearchTermChange: se,
fetchState: ne,
options: G,
notFound: h,
noResultsMessage: I,
multiple: o,
value: t,
resolveOptionValue: s,
renderSelectedValue: c,
renderOptionItem: S,
onSelect: oe,
onSelectMultiple: de
}
)
}
)
] })
] });
}
function Me({
option: i,
multiple: n,
value: N,
resolveOptionValue: S,
renderSelectedValue: s,
renderOptionItem: c,
onSelect: h,
onSelectMultiple: C
}) {
const f = S(i);
let t = !1;
return n ? t = Array.isArray(N) && N.includes(f) : t = N === f, /* @__PURE__ */ r(
O,
{
value: f,
onSelect: n ? C : h,
className: z(
"cursor-pointer",
u.dropdownItem.hover,
t && u.dropdownItem.selected
),
children: /* @__PURE__ */ r("div", { className: "flex w-full items-center justify-between overflow-hidden", children: /* @__PURE__ */ x("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
n && /* @__PURE__ */ r(he, { checked: t }),
c ? /* @__PURE__ */ r("div", { className: "truncate", children: c(i) }) : /* @__PURE__ */ r("span", { className: "truncate", children: s(i) })
] }) })
},
f
);
}
function Re({
inputRef: i,
commandListRef: n,
placeholder: N,
searchTerm: S,
onSearchTermChange: s,
fetchState: c,
options: h,
notFound: C,
noResultsMessage: f,
multiple: t,
value: g,
resolveOptionValue: M,
renderSelectedValue: v,
renderOptionItem: E,
onSelect: I,
onSelectMultiple: R
}) {
return /* @__PURE__ */ x(ge, { shouldFilter: !1, className: "w-full border-none shadow-sm", children: [
/* @__PURE__ */ r(
pe,
{
ref: i,
placeholder: N,
className: "placeholder:text-d-muted-foreground",
value: S,
onValueChange: s
}
),
c.loading && h.length > 0 && /* @__PURE__ */ r("div", { className: "flex items-center justify-center p-2", children: /* @__PURE__ */ r(Ae, { className: "h-4 w-4 animate-spin" }) }),
/* @__PURE__ */ x(we, { ref: n, children: [
c.error && /* @__PURE__ */ r("div", { className: "text-d-destructive p-3 text-center", children: c.error }),
c.loading && h.length === 0 && /* @__PURE__ */ r(ke, {}),
!c.loading && !c.error && h.length === 0 && (C || /* @__PURE__ */ r(xe, { children: f || "No results found." })),
!c.loading && !c.error && h.length > 0 && /* @__PURE__ */ r(_, { children: h.map((o) => /* @__PURE__ */ r(
Me,
{
option: o,
multiple: t,
value: g,
resolveOptionValue: M,
renderSelectedValue: v,
renderOptionItem: E,
onSelect: I,
onSelectMultiple: R
},
M(o)
)) })
] })
] });
}
function ke() {
return /* @__PURE__ */ r(_, { children: [1, 2, 3].map((i) => /* @__PURE__ */ r(O, { disabled: !0, children: /* @__PURE__ */ x("div", { className: "flex w-full items-center gap-2", children: [
/* @__PURE__ */ r("div", { className: "bg-d-secondary h-6 w-6 animate-pulse rounded-full" }),
/* @__PURE__ */ x("div", { className: "flex flex-1 flex-col gap-1", children: [
/* @__PURE__ */ r("div", { className: "bg-d-secondary h-4 w-24 animate-pulse rounded" }),
/* @__PURE__ */ r("div", { className: "bg-d-secondary h-3 w-16 animate-pulse rounded" })
] })
] }) }, i)) });
}
export {
$e as AsyncSelect,
Se as selectTriggerVariants
};