@underverse-ui/underverse 1.0.96 → 1.0.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "1.0.96",
3
+ "version": "1.0.98",
4
4
  "sourceEntry": "src/index.ts",
5
5
  "totalExports": 225,
6
6
  "exports": [
package/dist/index.cjs CHANGED
@@ -6793,9 +6793,15 @@ var variantStyles5 = {
6793
6793
  inactiveTab: "text-muted-foreground hover:text-foreground"
6794
6794
  }
6795
6795
  };
6796
- function getTabsBaseId(tabs) {
6796
+ function normalizeTabsId(value) {
6797
+ const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
6798
+ return normalized || "default";
6799
+ }
6800
+ function getTabsBaseId(tabs, id, fallbackId) {
6801
+ if (id) return `tabs-${normalizeTabsId(id)}`;
6802
+ if (fallbackId) return `tabs-${normalizeTabsId(fallbackId)}`;
6797
6803
  const key = tabs.map((t) => t.value).join("-");
6798
- return `tabs-${key || "default"}`;
6804
+ return `tabs-${normalizeTabsId(key || "default")}`;
6799
6805
  }
6800
6806
  function getTabTriggerId(baseId, index) {
6801
6807
  return `${baseId}-tab-${index}`;
@@ -6820,6 +6826,7 @@ function shouldHandleTabClickLocally(event, target) {
6820
6826
  return !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || target === "_blank");
6821
6827
  }
6822
6828
  var Tabs = ({
6829
+ id,
6823
6830
  tabs,
6824
6831
  defaultValue,
6825
6832
  className,
@@ -6836,7 +6843,8 @@ var Tabs = ({
6836
6843
  const [active, setActive] = React22.useState(defaultValue || tabs[0]?.value);
6837
6844
  const [underlineStyle, setUnderlineStyle] = React22.useState({});
6838
6845
  const tabRefs = React22.useRef([]);
6839
- const baseId = React22.useMemo(() => getTabsBaseId(tabs), [tabs]);
6846
+ const autoId = React22.useId();
6847
+ const baseId = React22.useMemo(() => getTabsBaseId(tabs, id, autoId), [autoId, id, tabs]);
6840
6848
  const handleTabChange = (value) => {
6841
6849
  setActive(value);
6842
6850
  onTabChange?.(value);
@@ -17111,15 +17119,47 @@ var TREE_NODE_INDENT_REM = 1;
17111
17119
  var TREE_BRANCH_OFFSET_CLASS = "ml-1.5 pl-1.5";
17112
17120
  var TREE_NODE_GAP_CLASS = "gap-1.5";
17113
17121
  var TREE_EXPANDER_PLACEHOLDER_CLASS = "w-5";
17114
- function getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline) {
17115
- if (!(viewOnly || inline) || !defaultExpanded) return /* @__PURE__ */ new Set();
17116
- const parentIds = /* @__PURE__ */ new Set();
17117
- for (const category of categories) {
17118
- if (typeof category.parent_id === "number") {
17119
- parentIds.add(category.parent_id);
17122
+ function getAncestorPathIds(categories, targetId) {
17123
+ const byId = new Map(categories.map((category) => [category.id, category]));
17124
+ const expanded = /* @__PURE__ */ new Set();
17125
+ let current = byId.get(targetId);
17126
+ let guard = 0;
17127
+ while (current && guard++ < categories.length) {
17128
+ expanded.add(current.id);
17129
+ if (typeof current.parent_id !== "number") break;
17130
+ current = byId.get(current.parent_id);
17131
+ }
17132
+ return expanded;
17133
+ }
17134
+ function getInitialExpandedNodes(categories, {
17135
+ defaultExpanded,
17136
+ defaultExpandedIds,
17137
+ expandToId,
17138
+ viewOnly,
17139
+ inline
17140
+ }) {
17141
+ const expanded = /* @__PURE__ */ new Set();
17142
+ if ((viewOnly || inline) && defaultExpanded) {
17143
+ for (const category of categories) {
17144
+ if (typeof category.parent_id === "number") {
17145
+ expanded.add(category.parent_id);
17146
+ }
17147
+ }
17148
+ }
17149
+ for (const id of defaultExpandedIds ?? []) {
17150
+ if (typeof id === "number") {
17151
+ expanded.add(id);
17152
+ }
17153
+ }
17154
+ if (typeof expandToId === "number") {
17155
+ for (const id of getAncestorPathIds(categories, expandToId)) {
17156
+ expanded.add(id);
17120
17157
  }
17121
17158
  }
17122
- return parentIds;
17159
+ return expanded;
17160
+ }
17161
+ function getExpandedNodesState(expandedIds, uncontrolledExpandedNodes) {
17162
+ return expandedIds !== void 0 ? new Set(expandedIds) : uncontrolledExpandedNodes;
17123
17163
  }
17124
17164
  function CategoryTreeSelect(props) {
17125
17165
  const tv = useSmartTranslations("ValidationInput");
@@ -17138,6 +17178,10 @@ function CategoryTreeSelect(props) {
17138
17178
  helperText,
17139
17179
  viewOnly = false,
17140
17180
  defaultExpanded = false,
17181
+ defaultExpandedIds,
17182
+ expandToId = null,
17183
+ expandedIds,
17184
+ onExpandedChange,
17141
17185
  enableSearch,
17142
17186
  labels,
17143
17187
  inline = false,
@@ -17148,7 +17192,9 @@ function CategoryTreeSelect(props) {
17148
17192
  singleSelect = false
17149
17193
  } = props;
17150
17194
  const [isOpen, setIsOpen] = (0, import_react22.useState)(false);
17151
- const [expandedNodes, setExpandedNodes] = (0, import_react22.useState)(() => getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline));
17195
+ const [expandedNodes, setExpandedNodes] = (0, import_react22.useState)(
17196
+ () => getInitialExpandedNodes(categories, { defaultExpanded, defaultExpandedIds, expandToId, viewOnly, inline })
17197
+ );
17152
17198
  const [query, setQuery] = (0, import_react22.useState)("");
17153
17199
  const [localRequiredError, setLocalRequiredError] = (0, import_react22.useState)();
17154
17200
  const searchInputRef = (0, import_react22.useRef)(null);
@@ -17185,6 +17231,7 @@ function CategoryTreeSelect(props) {
17185
17231
  const isSearchEnabled = (0, import_react22.useMemo)(() => enableSearch ?? categories.length > 10, [enableSearch, categories.length]);
17186
17232
  const normalizedQuery = (0, import_react22.useMemo)(() => query.trim().toLowerCase(), [query]);
17187
17233
  const isSearchMode = isSearchEnabled && normalizedQuery.length > 0;
17234
+ const effectiveExpandedNodes = (0, import_react22.useMemo)(() => getExpandedNodesState(expandedIds, expandedNodes), [expandedIds, expandedNodes]);
17188
17235
  const visibleIds = (0, import_react22.useMemo)(() => {
17189
17236
  if (!isSearchMode) return null;
17190
17237
  const matches = categories.filter((c) => c.name.toLowerCase().includes(normalizedQuery));
@@ -17237,13 +17284,16 @@ function CategoryTreeSelect(props) {
17237
17284
  }, [disabled, required, valueArray.length]);
17238
17285
  const toggleExpand = (id2) => {
17239
17286
  if (isSearchMode) return;
17240
- const newExpanded = new Set(expandedNodes);
17287
+ const newExpanded = new Set(effectiveExpandedNodes);
17241
17288
  if (newExpanded.has(id2)) {
17242
17289
  newExpanded.delete(id2);
17243
17290
  } else {
17244
17291
  newExpanded.add(id2);
17245
17292
  }
17246
- setExpandedNodes(newExpanded);
17293
+ if (expandedIds === void 0) {
17294
+ setExpandedNodes(newExpanded);
17295
+ }
17296
+ onExpandedChange?.(Array.from(newExpanded));
17247
17297
  };
17248
17298
  const handleSelect = (categoryId, category) => {
17249
17299
  if (viewOnly) return;
@@ -17285,7 +17335,7 @@ function CategoryTreeSelect(props) {
17285
17335
  const renderCategory = (category, level = 0) => {
17286
17336
  const children = effectiveChildrenMap.get(category.id) || [];
17287
17337
  const hasChildren = children.length > 0;
17288
- const isExpanded = hasChildren && (isSearchMode || expandedNodes.has(category.id));
17338
+ const isExpanded = hasChildren && (isSearchMode || effectiveExpandedNodes.has(category.id));
17289
17339
  const isSelected = selectedIds.has(category.id);
17290
17340
  const isSelectable = !viewOnly && (!leafOnlySelect || !hasChildren);
17291
17341
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(