@underverse-ui/underverse 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +196 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +265 -95
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6536,6 +6536,14 @@ var import_lucide_react17 = require("lucide-react");
|
|
|
6536
6536
|
var import_lucide_react15 = require("lucide-react");
|
|
6537
6537
|
var React24 = __toESM(require("react"), 1);
|
|
6538
6538
|
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
6539
|
+
var VIETNAM_HOLIDAYS = [
|
|
6540
|
+
{ date: "01-01", name: "T\u1EBFt D\u01B0\u01A1ng l\u1ECBch", recurring: true },
|
|
6541
|
+
{ date: "04-30", name: "Gi\u1EA3i ph\xF3ng mi\u1EC1n Nam", recurring: true },
|
|
6542
|
+
{ date: "05-01", name: "Qu\u1ED1c t\u1EBF Lao \u0111\u1ED9ng", recurring: true },
|
|
6543
|
+
{ date: "09-02", name: "Qu\u1ED1c kh\xE1nh", recurring: true },
|
|
6544
|
+
{ date: "03-10", name: "Gi\u1ED7 T\u1ED5 H\xF9ng V\u01B0\u01A1ng", recurring: true }
|
|
6545
|
+
// Lunar 10/3, simplified
|
|
6546
|
+
];
|
|
6539
6547
|
function startOfMonth(d) {
|
|
6540
6548
|
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
6541
6549
|
}
|
|
@@ -6565,6 +6573,20 @@ function startOfWeek(d, weekStartsOn) {
|
|
|
6565
6573
|
s.setDate(d.getDate() - diff);
|
|
6566
6574
|
return new Date(s.getFullYear(), s.getMonth(), s.getDate());
|
|
6567
6575
|
}
|
|
6576
|
+
function isHoliday(d, holidays) {
|
|
6577
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
6578
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
6579
|
+
const mmdd = `${mm}-${dd}`;
|
|
6580
|
+
for (const h of holidays) {
|
|
6581
|
+
if (h.recurring) {
|
|
6582
|
+
if (h.date === mmdd) return h;
|
|
6583
|
+
} else {
|
|
6584
|
+
const hDate = h.date instanceof Date ? h.date : new Date(h.date);
|
|
6585
|
+
if (isSameDay(d, hDate)) return h;
|
|
6586
|
+
}
|
|
6587
|
+
}
|
|
6588
|
+
return void 0;
|
|
6589
|
+
}
|
|
6568
6590
|
function getMonthGrid(view, weekStartsOn) {
|
|
6569
6591
|
const start = startOfMonth(view);
|
|
6570
6592
|
const end = endOfMonth(view);
|
|
@@ -6614,6 +6636,10 @@ function Calendar2({
|
|
|
6614
6636
|
animate = false,
|
|
6615
6637
|
showEventBadges = false,
|
|
6616
6638
|
highlightWeekends = false,
|
|
6639
|
+
weekendTextColor = "text-destructive",
|
|
6640
|
+
highlightHolidays = false,
|
|
6641
|
+
holidayTextColor = "text-destructive",
|
|
6642
|
+
holidays = VIETNAM_HOLIDAYS,
|
|
6617
6643
|
cellMode = "compact",
|
|
6618
6644
|
maxEventsPerDay = 3,
|
|
6619
6645
|
showEventCount = true,
|
|
@@ -6803,6 +6829,8 @@ function Calendar2({
|
|
|
6803
6829
|
const dayEvents = byDay.get(k) || [];
|
|
6804
6830
|
const disabled = isDateDisabled(d);
|
|
6805
6831
|
const isWeekend = d.getDay() === 0 || d.getDay() === 6;
|
|
6832
|
+
const holidayMatch = isHoliday(d, holidays);
|
|
6833
|
+
const isHolidayDay = highlightHolidays && !!holidayMatch;
|
|
6806
6834
|
const customDay = renderDay?.({ date: d, isCurrentMonth: inMonth, isToday: isToday2, isSelected: selectedDay, events: dayEvents });
|
|
6807
6835
|
if (customDay) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(React24.Fragment, { children: customDay }, `${monthLabel}-${idx}`);
|
|
6808
6836
|
if (cellMode === "events") {
|
|
@@ -6821,9 +6849,11 @@ function Calendar2({
|
|
|
6821
6849
|
!inMonth && "opacity-40",
|
|
6822
6850
|
disabled && "opacity-30 cursor-not-allowed",
|
|
6823
6851
|
highlightWeekends && isWeekend && "bg-destructive/5",
|
|
6852
|
+
isHolidayDay && "bg-destructive/5",
|
|
6824
6853
|
isToday2 && !selectedDay && "ring-2 ring-primary/40 border-primary/50",
|
|
6825
6854
|
selectedDay && "border-primary/60 bg-primary/5"
|
|
6826
6855
|
),
|
|
6856
|
+
title: holidayMatch?.name,
|
|
6827
6857
|
children: [
|
|
6828
6858
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
|
|
6829
6859
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
@@ -6832,6 +6862,8 @@ function Calendar2({
|
|
|
6832
6862
|
className: cn(
|
|
6833
6863
|
"font-semibold tabular-nums",
|
|
6834
6864
|
cellSz.day,
|
|
6865
|
+
highlightWeekends && isWeekend && weekendTextColor,
|
|
6866
|
+
isHolidayDay && holidayTextColor,
|
|
6835
6867
|
isToday2 && "text-primary",
|
|
6836
6868
|
selectedDay && "text-primary",
|
|
6837
6869
|
!inMonth && "text-muted-foreground/50"
|
|
@@ -6852,7 +6884,7 @@ function Calendar2({
|
|
|
6852
6884
|
type: "button",
|
|
6853
6885
|
onClick: () => handleEventActivate(e, d, k, i),
|
|
6854
6886
|
className: cn(
|
|
6855
|
-
"group w-full text-left rounded-lg px-2.5 py-1.5",
|
|
6887
|
+
"group w-full text-left rounded-r-lg px-2.5 py-1.5",
|
|
6856
6888
|
"transition-all duration-150",
|
|
6857
6889
|
"hover:bg-accent/50 hover:shadow-sm hover:-translate-y-0.5",
|
|
6858
6890
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
|
|
@@ -6894,11 +6926,14 @@ function Calendar2({
|
|
|
6894
6926
|
!inMonth && "text-muted-foreground/50",
|
|
6895
6927
|
disabled && "opacity-40 cursor-not-allowed",
|
|
6896
6928
|
highlightWeekends && isWeekend && "bg-destructive/5",
|
|
6929
|
+
highlightWeekends && isWeekend && !selectedDay && weekendTextColor,
|
|
6930
|
+
isHolidayDay && "bg-destructive/5",
|
|
6931
|
+
isHolidayDay && !selectedDay && holidayTextColor,
|
|
6897
6932
|
isToday2 && !selectedDay && "ring-2 ring-primary/60 bg-primary/5 font-bold",
|
|
6898
6933
|
selectedDay && "bg-linear-to-br from-primary to-primary/90 text-primary-foreground shadow-md hover:shadow-lg hover:scale-105",
|
|
6899
6934
|
!selectedDay && !disabled && "hover:bg-accent hover:text-accent-foreground hover:scale-105 active:scale-95"
|
|
6900
6935
|
),
|
|
6901
|
-
title: d.toDateString(),
|
|
6936
|
+
title: holidayMatch?.name || d.toDateString(),
|
|
6902
6937
|
children: [
|
|
6903
6938
|
d.getDate(),
|
|
6904
6939
|
dayEvents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "absolute -bottom-1 inline-flex gap-0.5", children: dayEvents.slice(0, 3).map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
@@ -6982,6 +7017,8 @@ function Calendar2({
|
|
|
6982
7017
|
const dayEvents = byDay.get(k) || [];
|
|
6983
7018
|
const disabled = isDateDisabled(d);
|
|
6984
7019
|
const isWeekend = d.getDay() === 0 || d.getDay() === 6;
|
|
7020
|
+
const holidayMatch = isHoliday(d, holidays);
|
|
7021
|
+
const isHolidayDay = highlightHolidays && !!holidayMatch;
|
|
6985
7022
|
const customDay = renderDay?.({ date: d, isCurrentMonth: inMonth, isToday: isToday2, isSelected: selectedDay, events: dayEvents });
|
|
6986
7023
|
if (customDay) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(React24.Fragment, { children: customDay }, `wd-${idx}`);
|
|
6987
7024
|
if (cellMode === "events") {
|
|
@@ -6999,12 +7036,27 @@ function Calendar2({
|
|
|
6999
7036
|
cellSz.cell,
|
|
7000
7037
|
disabled && "opacity-30 cursor-not-allowed",
|
|
7001
7038
|
highlightWeekends && isWeekend && "bg-destructive/5",
|
|
7039
|
+
isHolidayDay && "bg-destructive/5",
|
|
7002
7040
|
isToday2 && !selectedDay && "ring-2 ring-primary/40 border-primary/50",
|
|
7003
7041
|
selectedDay && "border-primary/60 bg-primary/5"
|
|
7004
7042
|
),
|
|
7043
|
+
title: holidayMatch?.name,
|
|
7005
7044
|
children: [
|
|
7006
7045
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
|
|
7007
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
7046
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
7047
|
+
"span",
|
|
7048
|
+
{
|
|
7049
|
+
className: cn(
|
|
7050
|
+
"font-semibold tabular-nums",
|
|
7051
|
+
cellSz.day,
|
|
7052
|
+
highlightWeekends && isWeekend && weekendTextColor,
|
|
7053
|
+
isHolidayDay && holidayTextColor,
|
|
7054
|
+
isToday2 && "text-primary",
|
|
7055
|
+
selectedDay && "text-primary"
|
|
7056
|
+
),
|
|
7057
|
+
children: d.getDate()
|
|
7058
|
+
}
|
|
7059
|
+
),
|
|
7008
7060
|
dayEvents.length > 0 && showEventCount && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-[10px] px-1.5 py-0.5 rounded-md bg-muted/60 text-muted-foreground font-medium", children: dayEvents.length })
|
|
7009
7061
|
] }),
|
|
7010
7062
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "space-y-1 px-2 pb-2", children: [
|
|
@@ -7018,7 +7070,7 @@ function Calendar2({
|
|
|
7018
7070
|
type: "button",
|
|
7019
7071
|
onClick: () => handleEventActivate(e, d, k, i),
|
|
7020
7072
|
className: cn(
|
|
7021
|
-
"group w-full text-left rounded-lg px-2.5 py-1.5",
|
|
7073
|
+
"group w-full text-left rounded-r-lg px-2.5 py-1.5",
|
|
7022
7074
|
"transition-all duration-150",
|
|
7023
7075
|
"hover:bg-accent/50 hover:shadow-sm hover:-translate-y-0.5",
|
|
7024
7076
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
|
|
@@ -7059,7 +7111,9 @@ function Calendar2({
|
|
|
7059
7111
|
highlightWeekends && isWeekend && "bg-accent/10",
|
|
7060
7112
|
isToday2 && !selectedDay && "ring-1 ring-primary/50",
|
|
7061
7113
|
selectedDay && "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
7062
|
-
!selectedDay && "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
|
|
7114
|
+
!selectedDay && "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
|
7115
|
+
!selectedDay && highlightHolidays && isHoliday(d, holidays) && holidayTextColor,
|
|
7116
|
+
!selectedDay && !(highlightHolidays && isHoliday(d, holidays)) && isWeekend && weekendTextColor
|
|
7063
7117
|
),
|
|
7064
7118
|
title: d.toDateString(),
|
|
7065
7119
|
children: [
|
|
@@ -12683,7 +12737,9 @@ var import_lucide_react24 = require("lucide-react");
|
|
|
12683
12737
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
12684
12738
|
var defaultLabels = {
|
|
12685
12739
|
emptyText: "No categories",
|
|
12686
|
-
selectedText: (count) => `${count} selected
|
|
12740
|
+
selectedText: (count) => `${count} selected`,
|
|
12741
|
+
searchPlaceholder: "Search...",
|
|
12742
|
+
noResultsText: "No results found"
|
|
12687
12743
|
};
|
|
12688
12744
|
function CategoryTreeSelect(props) {
|
|
12689
12745
|
const {
|
|
@@ -12692,6 +12748,7 @@ function CategoryTreeSelect(props) {
|
|
|
12692
12748
|
disabled,
|
|
12693
12749
|
viewOnly = false,
|
|
12694
12750
|
defaultExpanded = false,
|
|
12751
|
+
enableSearch,
|
|
12695
12752
|
labels,
|
|
12696
12753
|
inline = false,
|
|
12697
12754
|
onNodeClick,
|
|
@@ -12700,18 +12757,76 @@ function CategoryTreeSelect(props) {
|
|
|
12700
12757
|
} = props;
|
|
12701
12758
|
const [isOpen, setIsOpen] = (0, import_react18.useState)(false);
|
|
12702
12759
|
const [expandedNodes, setExpandedNodes] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
|
|
12760
|
+
const [query, setQuery] = (0, import_react18.useState)("");
|
|
12761
|
+
const searchInputRef = (0, import_react18.useRef)(null);
|
|
12703
12762
|
const mergedLabels = { ...defaultLabels, ...labels };
|
|
12704
12763
|
const valueArray = singleSelect ? props.value != null ? [props.value] : [] : props.value || [];
|
|
12705
|
-
const parentCategories =
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12764
|
+
const { parentCategories, childrenMap, byId } = (0, import_react18.useMemo)(() => {
|
|
12765
|
+
const byId2 = /* @__PURE__ */ new Map();
|
|
12766
|
+
const childrenMap2 = /* @__PURE__ */ new Map();
|
|
12767
|
+
const parentCategories2 = [];
|
|
12768
|
+
for (const cat of categories) byId2.set(cat.id, cat);
|
|
12769
|
+
for (const cat of categories) {
|
|
12770
|
+
if (cat.parent_id == null) {
|
|
12771
|
+
parentCategories2.push(cat);
|
|
12772
|
+
continue;
|
|
12773
|
+
}
|
|
12774
|
+
if (!childrenMap2.has(cat.parent_id)) childrenMap2.set(cat.parent_id, []);
|
|
12775
|
+
childrenMap2.get(cat.parent_id).push(cat);
|
|
12776
|
+
}
|
|
12777
|
+
return { parentCategories: parentCategories2, childrenMap: childrenMap2, byId: byId2 };
|
|
12778
|
+
}, [categories]);
|
|
12779
|
+
const isSearchEnabled = (0, import_react18.useMemo)(() => enableSearch ?? categories.length > 10, [enableSearch, categories.length]);
|
|
12780
|
+
const normalizedQuery = (0, import_react18.useMemo)(() => query.trim().toLowerCase(), [query]);
|
|
12781
|
+
const isSearchMode = isSearchEnabled && normalizedQuery.length > 0;
|
|
12782
|
+
const visibleIds = (0, import_react18.useMemo)(() => {
|
|
12783
|
+
if (!isSearchMode) return null;
|
|
12784
|
+
const matches = categories.filter((c) => c.name.toLowerCase().includes(normalizedQuery));
|
|
12785
|
+
if (matches.length === 0) return /* @__PURE__ */ new Set();
|
|
12786
|
+
const visible = /* @__PURE__ */ new Set();
|
|
12787
|
+
const addAncestors = (cat) => {
|
|
12788
|
+
let cur = cat;
|
|
12789
|
+
let guard = 0;
|
|
12790
|
+
while (cur && cur.parent_id != null && guard++ < categories.length) {
|
|
12791
|
+
const pid = cur.parent_id;
|
|
12792
|
+
if (typeof pid !== "number") break;
|
|
12793
|
+
if (visible.has(pid)) {
|
|
12794
|
+
cur = byId.get(pid);
|
|
12795
|
+
continue;
|
|
12796
|
+
}
|
|
12797
|
+
visible.add(pid);
|
|
12798
|
+
cur = byId.get(pid);
|
|
12711
12799
|
}
|
|
12712
|
-
|
|
12800
|
+
};
|
|
12801
|
+
const addDescendants = (rootId) => {
|
|
12802
|
+
const stack = [rootId];
|
|
12803
|
+
let guard = 0;
|
|
12804
|
+
while (stack.length > 0 && guard++ < categories.length * 3) {
|
|
12805
|
+
const id = stack.pop();
|
|
12806
|
+
const children = childrenMap.get(id) ?? [];
|
|
12807
|
+
for (const child of children) {
|
|
12808
|
+
if (visible.has(child.id)) continue;
|
|
12809
|
+
visible.add(child.id);
|
|
12810
|
+
stack.push(child.id);
|
|
12811
|
+
}
|
|
12812
|
+
}
|
|
12813
|
+
};
|
|
12814
|
+
for (const m of matches) {
|
|
12815
|
+
visible.add(m.id);
|
|
12816
|
+
addAncestors(m);
|
|
12817
|
+
addDescendants(m.id);
|
|
12713
12818
|
}
|
|
12714
|
-
|
|
12819
|
+
return visible;
|
|
12820
|
+
}, [byId, categories, childrenMap, isSearchMode, normalizedQuery]);
|
|
12821
|
+
(0, import_react18.useEffect)(() => {
|
|
12822
|
+
if (!isOpen) setQuery("");
|
|
12823
|
+
}, [isOpen]);
|
|
12824
|
+
(0, import_react18.useEffect)(() => {
|
|
12825
|
+
if (!isOpen) return;
|
|
12826
|
+
if (!isSearchEnabled) return;
|
|
12827
|
+
const t = setTimeout(() => searchInputRef.current?.focus(), 50);
|
|
12828
|
+
return () => clearTimeout(t);
|
|
12829
|
+
}, [isOpen, isSearchEnabled]);
|
|
12715
12830
|
(0, import_react18.useEffect)(() => {
|
|
12716
12831
|
if ((viewOnly || inline) && defaultExpanded) {
|
|
12717
12832
|
const allParentIds = categories.filter((c) => childrenMap.has(c.id)).map((c) => c.id);
|
|
@@ -12719,6 +12834,7 @@ function CategoryTreeSelect(props) {
|
|
|
12719
12834
|
}
|
|
12720
12835
|
}, [viewOnly, inline, defaultExpanded, categories]);
|
|
12721
12836
|
const toggleExpand = (id) => {
|
|
12837
|
+
if (isSearchMode) return;
|
|
12722
12838
|
const newExpanded = new Set(expandedNodes);
|
|
12723
12839
|
if (newExpanded.has(id)) {
|
|
12724
12840
|
newExpanded.delete(id);
|
|
@@ -12759,9 +12875,10 @@ function CategoryTreeSelect(props) {
|
|
|
12759
12875
|
}
|
|
12760
12876
|
};
|
|
12761
12877
|
const renderCategory = (category, level = 0) => {
|
|
12762
|
-
const
|
|
12878
|
+
const allChildren = childrenMap.get(category.id) || [];
|
|
12879
|
+
const children = isSearchMode ? allChildren.filter((c) => visibleIds?.has(c.id)) : allChildren;
|
|
12763
12880
|
const hasChildren = children.length > 0;
|
|
12764
|
-
const isExpanded = expandedNodes.has(category.id);
|
|
12881
|
+
const isExpanded = hasChildren && (isSearchMode || expandedNodes.has(category.id));
|
|
12765
12882
|
const isSelected = valueArray.includes(category.id);
|
|
12766
12883
|
const isParent = level === 0;
|
|
12767
12884
|
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "animate-in fade-in-50 duration-200", style: { animationDelay: `${level * 30}ms` }, children: [
|
|
@@ -12791,8 +12908,10 @@ function CategoryTreeSelect(props) {
|
|
|
12791
12908
|
"p-1.5 rounded-lg transition-all duration-200",
|
|
12792
12909
|
"hover:scale-110 active:scale-95",
|
|
12793
12910
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
|
|
12794
|
-
isExpanded && "text-primary"
|
|
12911
|
+
isExpanded && "text-primary",
|
|
12912
|
+
isSearchMode && "opacity-60 cursor-not-allowed hover:scale-100 active:scale-100"
|
|
12795
12913
|
),
|
|
12914
|
+
disabled: isSearchMode,
|
|
12796
12915
|
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: cn("transition-transform duration-200", isExpanded && "rotate-90"), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react24.ChevronRight, { className: "w-4 h-4" }) })
|
|
12797
12916
|
}
|
|
12798
12917
|
) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "w-7" }),
|
|
@@ -12816,15 +12935,60 @@ function CategoryTreeSelect(props) {
|
|
|
12816
12935
|
hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: cn("ml-2 pl-2 border-l-2 border-dashed border-border/50", "animate-in slide-in-from-top-2 fade-in-50 duration-200"), children: children.map((child) => renderCategory(child, level + 1)) })
|
|
12817
12936
|
] }, category.id);
|
|
12818
12937
|
};
|
|
12819
|
-
const
|
|
12820
|
-
|
|
12821
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("
|
|
12822
|
-
|
|
12938
|
+
const renderSearch = () => {
|
|
12939
|
+
if (!isSearchEnabled) return null;
|
|
12940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "sticky top-0 z-10 px-1 pt-1 pb-2 bg-popover/80 backdrop-blur-xl", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "relative", children: [
|
|
12941
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react24.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }),
|
|
12942
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
12943
|
+
"input",
|
|
12944
|
+
{
|
|
12945
|
+
ref: searchInputRef,
|
|
12946
|
+
value: query,
|
|
12947
|
+
onChange: (e) => setQuery(e.target.value),
|
|
12948
|
+
placeholder: mergedLabels.searchPlaceholder,
|
|
12949
|
+
className: cn(
|
|
12950
|
+
"w-full h-10 rounded-full px-10 pr-10 text-sm",
|
|
12951
|
+
"bg-background/70 border border-border/60",
|
|
12952
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:border-primary/40"
|
|
12953
|
+
)
|
|
12954
|
+
}
|
|
12955
|
+
),
|
|
12956
|
+
query.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
12957
|
+
"button",
|
|
12958
|
+
{
|
|
12959
|
+
type: "button",
|
|
12960
|
+
onClick: () => {
|
|
12961
|
+
setQuery("");
|
|
12962
|
+
searchInputRef.current?.focus();
|
|
12963
|
+
},
|
|
12964
|
+
className: cn(
|
|
12965
|
+
"absolute right-2 top-1/2 -translate-y-1/2 h-7 w-7 rounded-full",
|
|
12966
|
+
"flex items-center justify-center",
|
|
12967
|
+
"text-muted-foreground hover:text-foreground hover:bg-accent/40 transition-colors",
|
|
12968
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
12969
|
+
),
|
|
12970
|
+
"aria-label": "Clear search",
|
|
12971
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react24.X, { className: "h-4 w-4" })
|
|
12972
|
+
}
|
|
12973
|
+
)
|
|
12974
|
+
] }) });
|
|
12975
|
+
};
|
|
12976
|
+
const effectiveParentCategories = (0, import_react18.useMemo)(() => {
|
|
12977
|
+
if (!isSearchMode) return parentCategories;
|
|
12978
|
+
return parentCategories.filter((c) => visibleIds?.has(c.id));
|
|
12979
|
+
}, [isSearchMode, parentCategories, visibleIds]);
|
|
12980
|
+
const renderTreeContent = () => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "space-y-0.5", children: effectiveParentCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
12981
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: isSearchMode ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react24.SearchX, { className: "w-6 h-6 text-muted-foreground/50" }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react24.Layers, { className: "w-6 h-6 text-muted-foreground/50" }) }),
|
|
12982
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-sm text-muted-foreground", children: isSearchMode ? mergedLabels.noResultsText : mergedLabels.emptyText })
|
|
12983
|
+
] }) : effectiveParentCategories.map((cat) => renderCategory(cat)) });
|
|
12823
12984
|
if (viewOnly) {
|
|
12824
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.
|
|
12985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: cn("rounded-2xl border border-border/60 bg-card/50 backdrop-blur-sm p-3 shadow-sm", disabled && "opacity-50", className), children: [
|
|
12986
|
+
renderSearch(),
|
|
12987
|
+
renderTreeContent()
|
|
12988
|
+
] });
|
|
12825
12989
|
}
|
|
12826
12990
|
if (inline) {
|
|
12827
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.
|
|
12991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
12828
12992
|
"div",
|
|
12829
12993
|
{
|
|
12830
12994
|
className: cn(
|
|
@@ -12832,7 +12996,10 @@ function CategoryTreeSelect(props) {
|
|
|
12832
12996
|
disabled && "opacity-50 pointer-events-none",
|
|
12833
12997
|
className
|
|
12834
12998
|
),
|
|
12835
|
-
children:
|
|
12999
|
+
children: [
|
|
13000
|
+
renderSearch(),
|
|
13001
|
+
renderTreeContent()
|
|
13002
|
+
]
|
|
12836
13003
|
}
|
|
12837
13004
|
);
|
|
12838
13005
|
}
|
|
@@ -12889,7 +13056,7 @@ function CategoryTreeSelect(props) {
|
|
|
12889
13056
|
),
|
|
12890
13057
|
isOpen && !disabled && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
12891
13058
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fixed inset-0 z-10", onClick: () => setIsOpen(false) }),
|
|
12892
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.
|
|
13059
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
12893
13060
|
"div",
|
|
12894
13061
|
{
|
|
12895
13062
|
className: cn(
|
|
@@ -12899,7 +13066,10 @@ function CategoryTreeSelect(props) {
|
|
|
12899
13066
|
"p-2",
|
|
12900
13067
|
"animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
|
|
12901
13068
|
),
|
|
12902
|
-
children:
|
|
13069
|
+
children: [
|
|
13070
|
+
renderSearch(),
|
|
13071
|
+
renderTreeContent()
|
|
13072
|
+
]
|
|
12903
13073
|
}
|
|
12904
13074
|
)
|
|
12905
13075
|
] })
|