@underverse-ui/underverse 1.0.97 → 1.0.99
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 +14 -15
- package/api-reference.json +7 -7
- package/dist/index.cjs +202 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -15
- package/dist/index.d.ts +181 -15
- package/dist/index.js +202 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,27 +109,26 @@ All components follow [Vercel Web Interface Guidelines](https://github.com/verce
|
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
112
|
-
##
|
|
112
|
+
## Package Exports
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
### Main Entry (Server-safe)
|
|
114
|
+
Hiện tại package publish **một public entry point duy nhất**:
|
|
117
115
|
|
|
118
116
|
```tsx
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
import {
|
|
118
|
+
Button,
|
|
119
|
+
DataTable,
|
|
120
|
+
Form,
|
|
121
|
+
FormField,
|
|
122
|
+
UEditor,
|
|
123
|
+
} from "@underverse-ui/underverse";
|
|
122
124
|
```
|
|
123
125
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```tsx
|
|
127
|
-
// dist/form.js - Form components (phụ thuộc react-hook-form)
|
|
128
|
-
// Chỉ sử dụng trong Client Components ("use client")
|
|
129
|
-
import { Form, FormField, FormItem, FormLabel, FormMessage } from "@underverse-ui/underverse/form";
|
|
130
|
-
```
|
|
126
|
+
Không có subpath export như `@underverse-ui/underverse/form` ở version hiện tại.
|
|
131
127
|
|
|
132
|
-
|
|
128
|
+
Lưu ý:
|
|
129
|
+
- Nhiều component trong package là client component và nên dùng trong môi trường React client.
|
|
130
|
+
- Form primitives yêu cầu `react-hook-form` và `@hookform/resolvers`.
|
|
131
|
+
- `UEditor` và các component dựa trên Tiptap yêu cầu peer dependencies tương ứng.
|
|
133
132
|
|
|
134
133
|
---
|
|
135
134
|
|
package/api-reference.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@underverse-ui/underverse",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.99",
|
|
4
4
|
"sourceEntry": "src/index.ts",
|
|
5
5
|
"totalExports": 225,
|
|
6
6
|
"exports": [
|
|
@@ -361,7 +361,7 @@
|
|
|
361
361
|
{
|
|
362
362
|
"name": "cn",
|
|
363
363
|
"kind": "value",
|
|
364
|
-
"source": "
|
|
364
|
+
"source": "./utils/cn",
|
|
365
365
|
"reexport": true,
|
|
366
366
|
"local": false
|
|
367
367
|
},
|
|
@@ -1487,14 +1487,14 @@
|
|
|
1487
1487
|
{
|
|
1488
1488
|
"name": "UnderverseProvider",
|
|
1489
1489
|
"kind": "value",
|
|
1490
|
-
"source": "
|
|
1490
|
+
"source": "./contexts/translation-adapter",
|
|
1491
1491
|
"reexport": true,
|
|
1492
1492
|
"local": false
|
|
1493
1493
|
},
|
|
1494
1494
|
{
|
|
1495
1495
|
"name": "UnderverseProviderProps",
|
|
1496
1496
|
"kind": "type",
|
|
1497
|
-
"source": "
|
|
1497
|
+
"source": "./contexts/translation-adapter",
|
|
1498
1498
|
"reexport": true,
|
|
1499
1499
|
"local": false
|
|
1500
1500
|
},
|
|
@@ -1557,7 +1557,7 @@
|
|
|
1557
1557
|
{
|
|
1558
1558
|
"name": "useUnderverseI18n",
|
|
1559
1559
|
"kind": "value",
|
|
1560
|
-
"source": "
|
|
1560
|
+
"source": "./contexts/translation-adapter",
|
|
1561
1561
|
"reexport": true,
|
|
1562
1562
|
"local": false,
|
|
1563
1563
|
"aliasOf": "useTranslations"
|
|
@@ -1565,7 +1565,7 @@
|
|
|
1565
1565
|
{
|
|
1566
1566
|
"name": "useUnderverseI18nLocale",
|
|
1567
1567
|
"kind": "value",
|
|
1568
|
-
"source": "
|
|
1568
|
+
"source": "./contexts/translation-adapter",
|
|
1569
1569
|
"reexport": true,
|
|
1570
1570
|
"local": false,
|
|
1571
1571
|
"aliasOf": "useLocale"
|
|
@@ -1587,7 +1587,7 @@
|
|
|
1587
1587
|
{
|
|
1588
1588
|
"name": "VARIANT_STYLES_ALERT",
|
|
1589
1589
|
"kind": "value",
|
|
1590
|
-
"source": "
|
|
1590
|
+
"source": "./constants/alert",
|
|
1591
1591
|
"reexport": true,
|
|
1592
1592
|
"local": false
|
|
1593
1593
|
},
|
package/dist/index.cjs
CHANGED
|
@@ -171,7 +171,7 @@ __export(index_exports, {
|
|
|
171
171
|
VIETNAM_HOLIDAYS: () => VIETNAM_HOLIDAYS,
|
|
172
172
|
VerticalTabs: () => VerticalTabs,
|
|
173
173
|
Watermark: () => Watermark_default,
|
|
174
|
-
cn: () =>
|
|
174
|
+
cn: () => cn,
|
|
175
175
|
cnLocal: () => cn,
|
|
176
176
|
extractImageSrcsFromHtml: () => extractImageSrcsFromHtml,
|
|
177
177
|
getAnimationStyles: () => getAnimationStyles,
|
|
@@ -2000,8 +2000,9 @@ function useSmartTranslations(namespace) {
|
|
|
2000
2000
|
return internalT;
|
|
2001
2001
|
}
|
|
2002
2002
|
return (key) => {
|
|
2003
|
-
const
|
|
2004
|
-
const
|
|
2003
|
+
const resolvedEnvironmentLocale = environmentLocale && environmentLocale !== internalLocale ? environmentLocale : null;
|
|
2004
|
+
const primaryLocale = nextIntlBridge?.locale ?? resolvedEnvironmentLocale ?? internalLocale;
|
|
2005
|
+
const fallbackLocale = resolvedEnvironmentLocale && resolvedEnvironmentLocale !== primaryLocale ? resolvedEnvironmentLocale : null;
|
|
2005
2006
|
let translated = null;
|
|
2006
2007
|
if (nextIntlBridge) {
|
|
2007
2008
|
const nextIntlResult = nextIntlBridge.translate(namespace, key);
|
|
@@ -2033,10 +2034,20 @@ function useSmartLocale() {
|
|
|
2033
2034
|
const forceInternal = React6.useContext(ForceInternalContext);
|
|
2034
2035
|
const nextIntlBridge = useNextIntlBridge();
|
|
2035
2036
|
const internalLocale = useUnderverseLocale();
|
|
2037
|
+
const [environmentLocale, setEnvironmentLocale] = React6.useState(null);
|
|
2038
|
+
React6.useEffect(() => {
|
|
2039
|
+
if (forceInternal) return;
|
|
2040
|
+
if (nextIntlBridge) return;
|
|
2041
|
+
if (internalLocale !== "en") return;
|
|
2042
|
+
const detected = getEnvironmentLocale(internalLocale);
|
|
2043
|
+
if (detected !== internalLocale) {
|
|
2044
|
+
setEnvironmentLocale(detected);
|
|
2045
|
+
}
|
|
2046
|
+
}, [forceInternal, internalLocale, nextIntlBridge]);
|
|
2036
2047
|
if (forceInternal) {
|
|
2037
2048
|
return internalLocale;
|
|
2038
2049
|
}
|
|
2039
|
-
return nextIntlBridge?.locale ?? internalLocale;
|
|
2050
|
+
return nextIntlBridge?.locale ?? environmentLocale ?? internalLocale;
|
|
2040
2051
|
}
|
|
2041
2052
|
|
|
2042
2053
|
// src/components/Input.tsx
|
|
@@ -7381,9 +7392,10 @@ var Combobox = ({
|
|
|
7381
7392
|
{
|
|
7382
7393
|
id: `combobox-item-${index}`,
|
|
7383
7394
|
type: "button",
|
|
7395
|
+
role: "option",
|
|
7384
7396
|
tabIndex: -1,
|
|
7385
7397
|
disabled: itemDisabled,
|
|
7386
|
-
"aria-
|
|
7398
|
+
"aria-selected": isSelected,
|
|
7387
7399
|
onClick: () => handleSelect(item),
|
|
7388
7400
|
style: {
|
|
7389
7401
|
animationDelay: open ? `${Math.min(index * 15, 150)}ms` : "0ms"
|
|
@@ -7488,40 +7500,50 @@ var Combobox = ({
|
|
|
7488
7500
|
}
|
|
7489
7501
|
)
|
|
7490
7502
|
] }) }),
|
|
7491
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
{
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7503
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
7504
|
+
"div",
|
|
7505
|
+
{
|
|
7506
|
+
ref: optionsViewportRef,
|
|
7507
|
+
role: "listbox",
|
|
7508
|
+
"aria-labelledby": labelId,
|
|
7509
|
+
className: "overflow-y-auto overscroll-contain",
|
|
7510
|
+
style: { maxHeight },
|
|
7511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(size === "sm" ? "p-1" : size === "lg" ? "p-2" : "p-1.5"), children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "px-3 py-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center gap-3 animate-in fade-in-0 zoom-in-95 duration-300", children: [
|
|
7512
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-10 h-10 rounded-full border-2 border-primary/20 border-t-primary animate-spin" }) }),
|
|
7513
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-sm text-muted-foreground", children: loadingText })
|
|
7514
|
+
] }) }) : filteredOptions.length > 0 ? groupedOptions ? (
|
|
7515
|
+
// Render grouped options with global index tracking
|
|
7516
|
+
(() => {
|
|
7517
|
+
let globalIndex = 0;
|
|
7518
|
+
return Object.entries(groupedOptions).map(([group, items]) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn(globalIndex > 0 && "mt-2 pt-2 border-t border-border/30"), children: [
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "px-3 py-1.5 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: group }),
|
|
7520
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ul", { className: "space-y-0.5", children: items.map((item) => {
|
|
7521
|
+
const index = globalIndex++;
|
|
7522
|
+
return renderOptionItem(item, index);
|
|
7523
|
+
}) })
|
|
7524
|
+
] }, group));
|
|
7525
|
+
})()
|
|
7526
|
+
) : (
|
|
7527
|
+
// Render flat options
|
|
7528
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ul", { className: "space-y-0.5", children: filteredOptions.map((item, index) => renderOptionItem(item, index)) })
|
|
7529
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "px-3 py-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center gap-3 animate-in fade-in-0 zoom-in-95 duration-300", children: [
|
|
7530
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-12 h-12 rounded-full bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.SearchX, { className: "h-6 w-6 text-muted-foreground/60" }) }),
|
|
7531
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "space-y-1", children: [
|
|
7532
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "block text-sm font-medium text-foreground", children: emptyText }),
|
|
7533
|
+
query && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "block text-xs text-muted-foreground", children: "Try a different search term" })
|
|
7534
|
+
] }),
|
|
7535
|
+
query && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
7536
|
+
"button",
|
|
7537
|
+
{
|
|
7538
|
+
type: "button",
|
|
7539
|
+
onClick: () => setQuery(""),
|
|
7540
|
+
className: "px-3 py-1.5 text-xs font-medium text-primary bg-primary/10 rounded-full hover:bg-primary/20 transition-colors",
|
|
7541
|
+
children: "Clear search"
|
|
7542
|
+
}
|
|
7543
|
+
)
|
|
7544
|
+
] }) }) })
|
|
7545
|
+
}
|
|
7546
|
+
)
|
|
7525
7547
|
]
|
|
7526
7548
|
}
|
|
7527
7549
|
);
|
|
@@ -17119,15 +17141,83 @@ var TREE_NODE_INDENT_REM = 1;
|
|
|
17119
17141
|
var TREE_BRANCH_OFFSET_CLASS = "ml-1.5 pl-1.5";
|
|
17120
17142
|
var TREE_NODE_GAP_CLASS = "gap-1.5";
|
|
17121
17143
|
var TREE_EXPANDER_PLACEHOLDER_CLASS = "w-5";
|
|
17122
|
-
function
|
|
17123
|
-
|
|
17124
|
-
const
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17144
|
+
function getAncestorPathIds(categories, targetId) {
|
|
17145
|
+
const byId = new Map(categories.map((category) => [category.id, category]));
|
|
17146
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
17147
|
+
let current = byId.get(targetId);
|
|
17148
|
+
let guard = 0;
|
|
17149
|
+
while (current && guard++ < categories.length) {
|
|
17150
|
+
expanded.add(current.id);
|
|
17151
|
+
if (typeof current.parent_id !== "number") break;
|
|
17152
|
+
current = byId.get(current.parent_id);
|
|
17153
|
+
}
|
|
17154
|
+
return expanded;
|
|
17155
|
+
}
|
|
17156
|
+
function getInitialExpandedNodes(categories, {
|
|
17157
|
+
defaultExpanded,
|
|
17158
|
+
defaultExpandedIds,
|
|
17159
|
+
expandToId,
|
|
17160
|
+
viewOnly,
|
|
17161
|
+
inline
|
|
17162
|
+
}) {
|
|
17163
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
17164
|
+
if ((viewOnly || inline) && defaultExpanded) {
|
|
17165
|
+
for (const category of categories) {
|
|
17166
|
+
if (typeof category.parent_id === "number") {
|
|
17167
|
+
expanded.add(category.parent_id);
|
|
17168
|
+
}
|
|
17169
|
+
}
|
|
17170
|
+
}
|
|
17171
|
+
for (const id of defaultExpandedIds ?? []) {
|
|
17172
|
+
if (typeof id === "number") {
|
|
17173
|
+
expanded.add(id);
|
|
17128
17174
|
}
|
|
17129
17175
|
}
|
|
17130
|
-
|
|
17176
|
+
if (typeof expandToId === "number") {
|
|
17177
|
+
for (const id of getAncestorPathIds(categories, expandToId)) {
|
|
17178
|
+
expanded.add(id);
|
|
17179
|
+
}
|
|
17180
|
+
}
|
|
17181
|
+
return expanded;
|
|
17182
|
+
}
|
|
17183
|
+
function getExpandedNodesState(expandedIds, uncontrolledExpandedNodes) {
|
|
17184
|
+
return expandedIds !== void 0 ? new Set(expandedIds) : uncontrolledExpandedNodes;
|
|
17185
|
+
}
|
|
17186
|
+
function collectAncestorIds(categories, categoryId) {
|
|
17187
|
+
const ancestorIds = getAncestorPathIds(categories, categoryId);
|
|
17188
|
+
ancestorIds.delete(categoryId);
|
|
17189
|
+
return ancestorIds;
|
|
17190
|
+
}
|
|
17191
|
+
function collectDescendantIds(childrenMap, categoryId) {
|
|
17192
|
+
const descendants = /* @__PURE__ */ new Set();
|
|
17193
|
+
const stack = [categoryId];
|
|
17194
|
+
while (stack.length > 0) {
|
|
17195
|
+
const currentId = stack.pop();
|
|
17196
|
+
for (const child of childrenMap.get(currentId) ?? []) {
|
|
17197
|
+
if (descendants.has(child.id)) continue;
|
|
17198
|
+
descendants.add(child.id);
|
|
17199
|
+
stack.push(child.id);
|
|
17200
|
+
}
|
|
17201
|
+
}
|
|
17202
|
+
return descendants;
|
|
17203
|
+
}
|
|
17204
|
+
function pruneAncestorSelection(categories, childrenMap, selected, fromCategoryId) {
|
|
17205
|
+
const byId = new Map(categories.map((category) => [category.id, category]));
|
|
17206
|
+
let current = byId.get(fromCategoryId);
|
|
17207
|
+
let guard = 0;
|
|
17208
|
+
while (current && typeof current.parent_id === "number" && guard++ < categories.length) {
|
|
17209
|
+
const parent = byId.get(current.parent_id);
|
|
17210
|
+
if (!parent) break;
|
|
17211
|
+
const descendantIds = collectDescendantIds(childrenMap, parent.id);
|
|
17212
|
+
const hasSelectedDescendant = Array.from(descendantIds).some((id) => selected.has(id));
|
|
17213
|
+
if (!hasSelectedDescendant) {
|
|
17214
|
+
selected.delete(parent.id);
|
|
17215
|
+
}
|
|
17216
|
+
current = parent;
|
|
17217
|
+
}
|
|
17218
|
+
}
|
|
17219
|
+
function toCategoryOrderSelection(categories, selected) {
|
|
17220
|
+
return categories.map((category) => category.id).filter((categoryId) => selected.has(categoryId));
|
|
17131
17221
|
}
|
|
17132
17222
|
function CategoryTreeSelect(props) {
|
|
17133
17223
|
const tv = useSmartTranslations("ValidationInput");
|
|
@@ -17146,6 +17236,10 @@ function CategoryTreeSelect(props) {
|
|
|
17146
17236
|
helperText,
|
|
17147
17237
|
viewOnly = false,
|
|
17148
17238
|
defaultExpanded = false,
|
|
17239
|
+
defaultExpandedIds,
|
|
17240
|
+
expandToId = null,
|
|
17241
|
+
expandedIds,
|
|
17242
|
+
onExpandedChange,
|
|
17149
17243
|
enableSearch,
|
|
17150
17244
|
labels,
|
|
17151
17245
|
inline = false,
|
|
@@ -17156,7 +17250,9 @@ function CategoryTreeSelect(props) {
|
|
|
17156
17250
|
singleSelect = false
|
|
17157
17251
|
} = props;
|
|
17158
17252
|
const [isOpen, setIsOpen] = (0, import_react22.useState)(false);
|
|
17159
|
-
const [expandedNodes, setExpandedNodes] = (0, import_react22.useState)(
|
|
17253
|
+
const [expandedNodes, setExpandedNodes] = (0, import_react22.useState)(
|
|
17254
|
+
() => getInitialExpandedNodes(categories, { defaultExpanded, defaultExpandedIds, expandToId, viewOnly, inline })
|
|
17255
|
+
);
|
|
17160
17256
|
const [query, setQuery] = (0, import_react22.useState)("");
|
|
17161
17257
|
const [localRequiredError, setLocalRequiredError] = (0, import_react22.useState)();
|
|
17162
17258
|
const searchInputRef = (0, import_react22.useRef)(null);
|
|
@@ -17193,6 +17289,7 @@ function CategoryTreeSelect(props) {
|
|
|
17193
17289
|
const isSearchEnabled = (0, import_react22.useMemo)(() => enableSearch ?? categories.length > 10, [enableSearch, categories.length]);
|
|
17194
17290
|
const normalizedQuery = (0, import_react22.useMemo)(() => query.trim().toLowerCase(), [query]);
|
|
17195
17291
|
const isSearchMode = isSearchEnabled && normalizedQuery.length > 0;
|
|
17292
|
+
const effectiveExpandedNodes = (0, import_react22.useMemo)(() => getExpandedNodesState(expandedIds, expandedNodes), [expandedIds, expandedNodes]);
|
|
17196
17293
|
const visibleIds = (0, import_react22.useMemo)(() => {
|
|
17197
17294
|
if (!isSearchMode) return null;
|
|
17198
17295
|
const matches = categories.filter((c) => c.name.toLowerCase().includes(normalizedQuery));
|
|
@@ -17245,13 +17342,16 @@ function CategoryTreeSelect(props) {
|
|
|
17245
17342
|
}, [disabled, required, valueArray.length]);
|
|
17246
17343
|
const toggleExpand = (id2) => {
|
|
17247
17344
|
if (isSearchMode) return;
|
|
17248
|
-
const newExpanded = new Set(
|
|
17345
|
+
const newExpanded = new Set(effectiveExpandedNodes);
|
|
17249
17346
|
if (newExpanded.has(id2)) {
|
|
17250
17347
|
newExpanded.delete(id2);
|
|
17251
17348
|
} else {
|
|
17252
17349
|
newExpanded.add(id2);
|
|
17253
17350
|
}
|
|
17254
|
-
|
|
17351
|
+
if (expandedIds === void 0) {
|
|
17352
|
+
setExpandedNodes(newExpanded);
|
|
17353
|
+
}
|
|
17354
|
+
onExpandedChange?.(Array.from(newExpanded));
|
|
17255
17355
|
};
|
|
17256
17356
|
const handleSelect = (categoryId, category) => {
|
|
17257
17357
|
if (viewOnly) return;
|
|
@@ -17279,21 +17379,23 @@ function CategoryTreeSelect(props) {
|
|
|
17279
17379
|
const newSelected = new Set(valueArray);
|
|
17280
17380
|
if (newSelected.has(categoryId)) {
|
|
17281
17381
|
newSelected.delete(categoryId);
|
|
17282
|
-
const
|
|
17283
|
-
|
|
17382
|
+
for (const descendantId of collectDescendantIds(childrenMap, categoryId)) {
|
|
17383
|
+
newSelected.delete(descendantId);
|
|
17384
|
+
}
|
|
17385
|
+
pruneAncestorSelection(categories, childrenMap, newSelected, categoryId);
|
|
17284
17386
|
} else {
|
|
17285
17387
|
newSelected.add(categoryId);
|
|
17286
|
-
|
|
17287
|
-
newSelected.add(
|
|
17388
|
+
for (const ancestorId of collectAncestorIds(categories, categoryId)) {
|
|
17389
|
+
newSelected.add(ancestorId);
|
|
17288
17390
|
}
|
|
17289
17391
|
}
|
|
17290
|
-
onChange(
|
|
17392
|
+
onChange(toCategoryOrderSelection(categories, newSelected));
|
|
17291
17393
|
}
|
|
17292
17394
|
};
|
|
17293
17395
|
const renderCategory = (category, level = 0) => {
|
|
17294
17396
|
const children = effectiveChildrenMap.get(category.id) || [];
|
|
17295
17397
|
const hasChildren = children.length > 0;
|
|
17296
|
-
const isExpanded = hasChildren && (isSearchMode ||
|
|
17398
|
+
const isExpanded = hasChildren && (isSearchMode || effectiveExpandedNodes.has(category.id));
|
|
17297
17399
|
const isSelected = selectedIds.has(category.id);
|
|
17298
17400
|
const isSelectable = !viewOnly && (!leafOnlySelect || !hasChildren);
|
|
17299
17401
|
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
|
|
@@ -17641,11 +17743,10 @@ function CategoryTreeSelect(props) {
|
|
|
17641
17743
|
"shadow-2xl backdrop-blur-xl"
|
|
17642
17744
|
),
|
|
17643
17745
|
trigger: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
|
|
17644
|
-
"
|
|
17746
|
+
"div",
|
|
17645
17747
|
{
|
|
17646
17748
|
id: resolvedId,
|
|
17647
|
-
|
|
17648
|
-
disabled,
|
|
17749
|
+
tabIndex: disabled ? -1 : 0,
|
|
17649
17750
|
role: "combobox",
|
|
17650
17751
|
"aria-haspopup": "tree",
|
|
17651
17752
|
"aria-expanded": isOpen,
|
|
@@ -17654,6 +17755,13 @@ function CategoryTreeSelect(props) {
|
|
|
17654
17755
|
"aria-describedby": describedBy,
|
|
17655
17756
|
"aria-required": required,
|
|
17656
17757
|
"aria-invalid": !!effectiveError,
|
|
17758
|
+
onKeyDown: (event) => {
|
|
17759
|
+
if (disabled) return;
|
|
17760
|
+
if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown") {
|
|
17761
|
+
event.preventDefault();
|
|
17762
|
+
handleOpenChange(!isOpen);
|
|
17763
|
+
}
|
|
17764
|
+
},
|
|
17657
17765
|
className: cn(
|
|
17658
17766
|
"group flex w-full items-center justify-between rounded-full transition-all duration-200",
|
|
17659
17767
|
"backdrop-blur-sm",
|
|
@@ -17692,13 +17800,11 @@ function CategoryTreeSelect(props) {
|
|
|
17692
17800
|
] }),
|
|
17693
17801
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "ml-2 flex shrink-0 items-center gap-1.5", children: [
|
|
17694
17802
|
allowClear && selectedCount > 0 && !disabled && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
17695
|
-
"
|
|
17803
|
+
"button",
|
|
17696
17804
|
{
|
|
17697
|
-
|
|
17698
|
-
tabIndex: 0,
|
|
17805
|
+
type: "button",
|
|
17699
17806
|
"aria-label": "Clear selection",
|
|
17700
17807
|
onClick: handleClear,
|
|
17701
|
-
onKeyDown: (event) => (event.key === "Enter" || event.key === " ") && handleClear(event),
|
|
17702
17808
|
className: cn(
|
|
17703
17809
|
"opacity-0 group-hover:opacity-100 transition-all duration-200",
|
|
17704
17810
|
"p-1 rounded-lg hover:bg-destructive/10 text-muted-foreground hover:text-destructive",
|
|
@@ -21405,6 +21511,18 @@ function DataTableBodyRows({
|
|
|
21405
21511
|
var import_react30 = __toESM(require("react"), 1);
|
|
21406
21512
|
var import_lucide_react35 = require("lucide-react");
|
|
21407
21513
|
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
21514
|
+
function getColumnLabel(title) {
|
|
21515
|
+
if (typeof title === "string" || typeof title === "number") {
|
|
21516
|
+
return String(title).replace(/\s+/g, " ").trim();
|
|
21517
|
+
}
|
|
21518
|
+
if (Array.isArray(title)) {
|
|
21519
|
+
return title.map((item) => getColumnLabel(item)).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
21520
|
+
}
|
|
21521
|
+
if (import_react30.default.isValidElement(title)) {
|
|
21522
|
+
return getColumnLabel(title.props.children);
|
|
21523
|
+
}
|
|
21524
|
+
return "";
|
|
21525
|
+
}
|
|
21408
21526
|
function DataTableHeader({
|
|
21409
21527
|
headerRows,
|
|
21410
21528
|
headerAlign,
|
|
@@ -21429,12 +21547,13 @@ function DataTableHeader({
|
|
|
21429
21547
|
if (!col.filter) return null;
|
|
21430
21548
|
const key = col.key;
|
|
21431
21549
|
const commonProps = { className: "w-full", size };
|
|
21550
|
+
const columnLabel = getColumnLabel(col.title) || key;
|
|
21432
21551
|
if (col.filter.type === "text") {
|
|
21433
21552
|
return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
21434
21553
|
Input_default,
|
|
21435
21554
|
{
|
|
21436
21555
|
...commonProps,
|
|
21437
|
-
placeholder: col.filter.placeholder || `Search ${
|
|
21556
|
+
placeholder: col.filter.placeholder || `Search ${columnLabel}`,
|
|
21438
21557
|
value: filters[key] || "",
|
|
21439
21558
|
onChange: (e) => {
|
|
21440
21559
|
setCurPage(1);
|
|
@@ -21455,7 +21574,7 @@ function DataTableHeader({
|
|
|
21455
21574
|
setCurPage(1);
|
|
21456
21575
|
setFilters((prev) => ({ ...prev, [key]: value || void 0 }));
|
|
21457
21576
|
},
|
|
21458
|
-
placeholder: col.filter.placeholder || `Select ${
|
|
21577
|
+
placeholder: col.filter.placeholder || `Select ${columnLabel}`
|
|
21459
21578
|
}
|
|
21460
21579
|
);
|
|
21461
21580
|
}
|
|
@@ -21464,7 +21583,7 @@ function DataTableHeader({
|
|
|
21464
21583
|
DatePicker,
|
|
21465
21584
|
{
|
|
21466
21585
|
size,
|
|
21467
|
-
placeholder: col.filter.placeholder || `Select ${
|
|
21586
|
+
placeholder: col.filter.placeholder || `Select ${columnLabel}`,
|
|
21468
21587
|
value: filters[key] || null,
|
|
21469
21588
|
onChange: (date) => {
|
|
21470
21589
|
setCurPage(1);
|
|
@@ -21496,16 +21615,19 @@ function DataTableHeader({
|
|
|
21496
21615
|
}
|
|
21497
21616
|
const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
|
|
21498
21617
|
const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
|
|
21618
|
+
const columnLabel = getColumnLabel(col.title) || col.key;
|
|
21499
21619
|
const titleContent = /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
21500
21620
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: cn("font-medium whitespace-nowrap select-text", headerTitleClass), children: col.title }),
|
|
21501
21621
|
col.sortable && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
21502
21622
|
Tooltip,
|
|
21503
21623
|
{
|
|
21504
21624
|
placement: "top",
|
|
21505
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "text-xs font-medium", children: `Sort by ${
|
|
21625
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "text-xs font-medium", children: `Sort by ${columnLabel}` }),
|
|
21506
21626
|
children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
21507
21627
|
"button",
|
|
21508
21628
|
{
|
|
21629
|
+
type: "button",
|
|
21630
|
+
title: `Sort by ${columnLabel}`,
|
|
21509
21631
|
className: cn(
|
|
21510
21632
|
"p-1 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
21511
21633
|
sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
|
|
@@ -21518,7 +21640,7 @@ function DataTableHeader({
|
|
|
21518
21640
|
return null;
|
|
21519
21641
|
});
|
|
21520
21642
|
},
|
|
21521
|
-
"aria-label":
|
|
21643
|
+
"aria-label": `Sort by ${columnLabel}`,
|
|
21522
21644
|
children: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("svg", { viewBox: "0 0 20 20", fill: "none", className: cn("inline-block", sortIconClass), children: [
|
|
21523
21645
|
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
21524
21646
|
"path",
|
|
@@ -21556,15 +21678,17 @@ function DataTableHeader({
|
|
|
21556
21678
|
Tooltip,
|
|
21557
21679
|
{
|
|
21558
21680
|
placement: "top",
|
|
21559
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "text-xs font-medium", children: `Filter by ${
|
|
21681
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "text-xs font-medium", children: `Filter by ${columnLabel}` }),
|
|
21560
21682
|
children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
21561
21683
|
"button",
|
|
21562
21684
|
{
|
|
21685
|
+
type: "button",
|
|
21686
|
+
title: `Filter by ${columnLabel}`,
|
|
21563
21687
|
className: cn(
|
|
21564
21688
|
"p-1.5 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
21565
21689
|
filters[col.key] ? "bg-accent text-primary" : "text-muted-foreground"
|
|
21566
21690
|
),
|
|
21567
|
-
"aria-label":
|
|
21691
|
+
"aria-label": `Filter by ${columnLabel}`,
|
|
21568
21692
|
children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react35.Filter, { className: "w-4 h-4" })
|
|
21569
21693
|
}
|
|
21570
21694
|
)
|
|
@@ -23080,16 +23204,8 @@ function LanguageSwitcherHeadless({
|
|
|
23080
23204
|
] });
|
|
23081
23205
|
}
|
|
23082
23206
|
|
|
23083
|
-
//
|
|
23084
|
-
var import_clsx2 = require("clsx");
|
|
23085
|
-
var import_tailwind_merge2 = require("tailwind-merge");
|
|
23086
|
-
function cn2(...inputs) {
|
|
23087
|
-
return (0, import_tailwind_merge2.twMerge)((0, import_clsx2.clsx)(...inputs));
|
|
23088
|
-
}
|
|
23089
|
-
|
|
23090
|
-
// ../../lib/constants/constants-ui/alert.ts
|
|
23207
|
+
// src/constants/alert.ts
|
|
23091
23208
|
var VARIANT_STYLES_ALERT = {
|
|
23092
|
-
// Use system colors for background + border; leave text colors to content
|
|
23093
23209
|
default: "border border-border bg-card/60 backdrop-blur-sm",
|
|
23094
23210
|
info: "border border-info/30 bg-info/10 backdrop-blur-sm",
|
|
23095
23211
|
success: "border border-success/30 bg-success/10 backdrop-blur-sm",
|
|
@@ -23097,7 +23213,7 @@ var VARIANT_STYLES_ALERT = {
|
|
|
23097
23213
|
error: "border border-destructive/30 bg-destructive/10 backdrop-blur-sm"
|
|
23098
23214
|
};
|
|
23099
23215
|
|
|
23100
|
-
//
|
|
23216
|
+
// src/contexts/translation-adapter.tsx
|
|
23101
23217
|
var React65 = __toESM(require("react"), 1);
|
|
23102
23218
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
23103
23219
|
function isUnresolvedTranslation2(value, namespace, key) {
|
|
@@ -31745,6 +31861,7 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
31745
31861
|
const t = useSmartTranslations("UEditor");
|
|
31746
31862
|
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
31747
31863
|
const inFlightPrepareRef = (0, import_react52.useRef)(null);
|
|
31864
|
+
const lastAppliedContentRef = (0, import_react52.useRef)(content ?? "");
|
|
31748
31865
|
const editorContentRef = (0, import_react52.useRef)(null);
|
|
31749
31866
|
const tableColumnGuideRef = (0, import_react52.useRef)(null);
|
|
31750
31867
|
const tableRowGuideRef = (0, import_react52.useRef)(null);
|
|
@@ -32047,10 +32164,12 @@ var UEditor = import_react52.default.forwardRef(({
|
|
|
32047
32164
|
[content, editor, uploadImageForSave]
|
|
32048
32165
|
);
|
|
32049
32166
|
(0, import_react52.useEffect)(() => {
|
|
32050
|
-
if (editor
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32167
|
+
if (!editor) return;
|
|
32168
|
+
const nextContent = content ?? "";
|
|
32169
|
+
if (lastAppliedContentRef.current === nextContent) return;
|
|
32170
|
+
lastAppliedContentRef.current = nextContent;
|
|
32171
|
+
if (editor.getHTML() !== nextContent) {
|
|
32172
|
+
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
32054
32173
|
}
|
|
32055
32174
|
}, [content, editor]);
|
|
32056
32175
|
(0, import_react52.useEffect)(() => {
|