@beweco/aurora-ui 0.6.16 → 0.6.19

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.js CHANGED
@@ -6001,7 +6001,7 @@ var RangeFilter = function (_a) {
6001
6001
  // BASE FILTER SECTION COMPONENT
6002
6002
  // =========================================================================
6003
6003
  var FilterSection = function (_a) {
6004
- var filter = _a.filter, value = _a.value, onChange = _a.onChange, _b = _a.isExpanded, isExpanded = _b === void 0 ? false : _b, onToggleExpanded = _a.onToggleExpanded;
6004
+ var filter = _a.filter, translations = _a.translations, value = _a.value, onChange = _a.onChange, _b = _a.isExpanded, isExpanded = _b === void 0 ? false : _b, onToggleExpanded = _a.onToggleExpanded;
6005
6005
  var _c = React.useState(isExpanded), internalExpanded = _c[0], setInternalExpanded = _c[1];
6006
6006
  var handleToggleExpanded = function () {
6007
6007
  var newExpanded = !internalExpanded;
@@ -6037,7 +6037,10 @@ var FilterSection = function (_a) {
6037
6037
  case "text":
6038
6038
  return value && "value" in value && value.value !== "";
6039
6039
  case "number":
6040
- return value && "value" in value && value.value !== null && value.value !== undefined;
6040
+ return (value &&
6041
+ "value" in value &&
6042
+ value.value !== null &&
6043
+ value.value !== undefined);
6041
6044
  default:
6042
6045
  return false;
6043
6046
  }
@@ -6074,7 +6077,12 @@ var FilterSection = function (_a) {
6074
6077
  case "text":
6075
6078
  return value && "value" in value && value.value !== "" ? 1 : 0;
6076
6079
  case "number":
6077
- return value && "value" in value && value.value !== null && value.value !== undefined ? 1 : 0;
6080
+ return value &&
6081
+ "value" in value &&
6082
+ value.value !== null &&
6083
+ value.value !== undefined
6084
+ ? 1
6085
+ : 0;
6078
6086
  default:
6079
6087
  return 0;
6080
6088
  }
@@ -6084,7 +6092,7 @@ var FilterSection = function (_a) {
6084
6092
  case "select":
6085
6093
  return (jsxRuntime.jsx(SelectFilter, { filter: filter, value: value, onChange: onChange }));
6086
6094
  case "multiselect":
6087
- return (jsxRuntime.jsx(MultiSelectFilter, { filter: filter, value: value, onChange: onChange }));
6095
+ return (jsxRuntime.jsx(MultiSelectFilter, { filter: filter, value: value, onChange: onChange, translations: translations }));
6088
6096
  case "range":
6089
6097
  return (jsxRuntime.jsx(RangeFilterComponent, { filter: filter, value: value, onChange: onChange }));
6090
6098
  case "date":
@@ -6123,12 +6131,123 @@ var SelectFilter = function (_a) {
6123
6131
  // MULTISELECT FILTER
6124
6132
  // =========================================================================
6125
6133
  var MultiSelectFilter = function (_a) {
6126
- var filter = _a.filter, value = _a.value, onChange = _a.onChange;
6134
+ var _b, _c, _d, _e;
6135
+ var filter = _a.filter, value = _a.value, onChange = _a.onChange, translations = _a.translations;
6136
+ var triggerRef = React.useRef(null);
6137
+ var _f = React.useState(null), triggerWidthPx = _f[0], setTriggerWidthPx = _f[1];
6138
+ var _g = React.useState(false), isOpen = _g[0], setIsOpen = _g[1];
6139
+ var _h = React.useState(""), searchQuery = _h[0], setSearchQuery = _h[1];
6127
6140
  var currentValues = (value === null || value === void 0 ? void 0 : value.values) || [];
6128
- return (jsxRuntime.jsx(Select, { placeholder: "Seleccionar ".concat(filter.title.toLowerCase()), selectedKeys: currentValues, onSelectionChange: function (keys) {
6129
- var selectedKeys = Array.from(keys);
6130
- onChange({ values: selectedKeys });
6131
- }, selectionMode: "multiple", className: "w-full", children: filter.data.map(function (item) { return (jsxRuntime.jsx(react.SelectItem, { children: item.label }, item.value)); }) }));
6141
+ var searchable = filter.searchable === true;
6142
+ var searchPlaceholder = (_b = translations === null || translations === void 0 ? void 0 : translations.multiselectSearchPlaceholder) !== null && _b !== void 0 ? _b : "Buscar opciones...";
6143
+ var moreLabelTemplate = (_c = translations === null || translations === void 0 ? void 0 : translations.multiselectMoreLabel) !== null && _c !== void 0 ? _c : "+{more} más";
6144
+ var noResultsText = (_d = translations === null || translations === void 0 ? void 0 : translations.multiselectNoResults) !== null && _d !== void 0 ? _d : "Sin coincidencias";
6145
+ var triggerPlaceholder = "Seleccionar ".concat(filter.title.toLowerCase());
6146
+ var filteredData = React.useMemo(function () {
6147
+ if (!searchable) {
6148
+ return filter.data;
6149
+ }
6150
+ var q = searchQuery.trim().toLowerCase();
6151
+ if (!q) {
6152
+ return filter.data;
6153
+ }
6154
+ return filter.data.filter(function (item) {
6155
+ return currentValues.includes(item.value) ||
6156
+ item.label.toLowerCase().includes(q) ||
6157
+ item.value.toLowerCase().includes(q);
6158
+ });
6159
+ }, [filter.data, searchQuery, currentValues, searchable]);
6160
+ var syncPopoverWidthToTrigger = React.useCallback(function () {
6161
+ var _a;
6162
+ var w = (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth;
6163
+ if (w != null && w > 0) {
6164
+ setTriggerWidthPx(w);
6165
+ }
6166
+ }, []);
6167
+ React.useLayoutEffect(function () {
6168
+ var el = triggerRef.current;
6169
+ if (!el || typeof ResizeObserver === "undefined") {
6170
+ return;
6171
+ }
6172
+ var ro = new ResizeObserver(function () {
6173
+ syncPopoverWidthToTrigger();
6174
+ });
6175
+ ro.observe(el);
6176
+ return function () {
6177
+ ro.disconnect();
6178
+ };
6179
+ }, [syncPopoverWidthToTrigger]);
6180
+ var handleOpenChange = React.useCallback(function (open) {
6181
+ setIsOpen(open);
6182
+ if (!open) {
6183
+ setSearchQuery("");
6184
+ return;
6185
+ }
6186
+ requestAnimationFrame(function () {
6187
+ syncPopoverWidthToTrigger();
6188
+ });
6189
+ }, [syncPopoverWidthToTrigger]);
6190
+ var selectedKeys = React.useMemo(function () { return new Set(currentValues); }, [currentValues]);
6191
+ var handleListboxSelectionChange = React.useCallback(function (keys) {
6192
+ if (keys === "all") {
6193
+ onChange({
6194
+ values: filteredData.map(function (item) { return item.value; }),
6195
+ });
6196
+ return;
6197
+ }
6198
+ onChange({ values: Array.from(keys) });
6199
+ }, [filteredData, onChange]);
6200
+ var maxVisibleChips = Math.min(Math.max((_e = filter.maxVisibleChips) !== null && _e !== void 0 ? _e : 5, 1), 24);
6201
+ var triggerSelection = React.useMemo(function () {
6202
+ if (currentValues.length === 0) {
6203
+ return { visible: [], overflow: 0 };
6204
+ }
6205
+ var ordered = currentValues.map(function (val) {
6206
+ var _a;
6207
+ var meta = filter.data.find(function (d) { return d.value === val; });
6208
+ return { value: val, label: (_a = meta === null || meta === void 0 ? void 0 : meta.label) !== null && _a !== void 0 ? _a : val };
6209
+ });
6210
+ var visible = ordered.slice(0, maxVisibleChips);
6211
+ var overflow = Math.max(0, ordered.length - visible.length);
6212
+ return { visible: visible, overflow: overflow };
6213
+ }, [currentValues, filter.data, maxVisibleChips]);
6214
+ var triggerSelectionTitle = React.useMemo(function () {
6215
+ if (currentValues.length === 0) {
6216
+ return undefined;
6217
+ }
6218
+ return currentValues
6219
+ .map(function (val) {
6220
+ var _a;
6221
+ var meta = filter.data.find(function (d) { return d.value === val; });
6222
+ return (_a = meta === null || meta === void 0 ? void 0 : meta.label) !== null && _a !== void 0 ? _a : val;
6223
+ })
6224
+ .join(", ");
6225
+ }, [currentValues, filter.data]);
6226
+ var popoverWidthStyle = triggerWidthPx != null
6227
+ ? {
6228
+ width: triggerWidthPx,
6229
+ minWidth: triggerWidthPx,
6230
+ maxWidth: triggerWidthPx,
6231
+ }
6232
+ : undefined;
6233
+ return (jsxRuntime.jsxs(react.Popover, { isOpen: isOpen, onOpenChange: handleOpenChange, placement: "bottom-start", offset: 6,
6234
+ // Dentro de Drawer (modal + focus scope), blur al portal del popover cerraba el panel antes de poder usar el buscador.
6235
+ shouldCloseOnBlur: false, updatePositionDeps: [triggerWidthPx !== null && triggerWidthPx !== void 0 ? triggerWidthPx : 0], classNames: {
6236
+ base: "w-full min-w-0 max-w-none box-border",
6237
+ content: "w-full min-w-0 !max-w-none",
6238
+ }, style: popoverWidthStyle, children: [jsxRuntime.jsx(react.PopoverTrigger, { children: jsxRuntime.jsxs("button", { ref: triggerRef, type: "button", className: react.cn("flex w-full min-h-12 items-center justify-between gap-2 rounded-medium border border-default-200 bg-background px-3 py-2.5 text-left text-small transition-colors", "hover:border-default-300 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background", isOpen && "border-primary"), "aria-expanded": isOpen, "aria-haspopup": "dialog", children: [jsxRuntime.jsx("span", { className: "line-clamp-2 min-w-0 flex-1 text-small font-medium leading-snug text-foreground", title: triggerSelectionTitle, children: triggerSelection.visible.length > 0 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [triggerSelection.visible.map(function (item, index) { return (jsxRuntime.jsxs(React.Fragment, { children: [index > 0 ? (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: ", " })) : null, jsxRuntime.jsx("span", { children: item.label })] }, item.value)); }), triggerSelection.overflow > 0 ? (jsxRuntime.jsxs("span", { className: "font-normal text-default-500", children: [" ", moreLabelTemplate.replace("{more}", String(triggerSelection.overflow))] })) : null] })) : (jsxRuntime.jsx("span", { className: "font-normal text-default-400", children: triggerPlaceholder })) }), jsxRuntime.jsx(IconComponent, { icon: isOpen
6239
+ ? "solar:alt-arrow-up-outline"
6240
+ : "solar:alt-arrow-down-outline", className: "shrink-0 text-default-400", size: "sm", "aria-hidden": true })] }) }), jsxRuntime.jsx(react.PopoverContent, { className: "border border-default-200 bg-content1 p-0 shadow-medium", children: jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-0 p-2", children: [searchable && (jsxRuntime.jsx("div", { className: "border-b border-default-100 px-1 pb-2", children: jsxRuntime.jsx(Input, { type: "search", placeholder: searchPlaceholder, value: searchQuery, onValueChange: setSearchQuery, className: "w-full", size: "sm", variant: "flat", radius: "full", classNames: {
6241
+ base: "w-full",
6242
+ inputWrapper: "bg-default-100 shadow-none border-0 min-h-9 h-9",
6243
+ input: "text-small",
6244
+ }, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:magnifer-outline", className: "pointer-events-none shrink-0 text-default-400", size: "sm", "aria-hidden": true }), "aria-label": searchPlaceholder }) })), jsxRuntime.jsx("div", { className: "max-h-60 overflow-y-auto px-1 py-1", children: filteredData.length === 0 ? (jsxRuntime.jsx("p", { className: "px-2 py-3 text-center text-tiny text-default-400", children: noResultsText })) : (jsxRuntime.jsx(react.Listbox, { "aria-label": filter.title, variant: "flat", selectionMode: "multiple", selectionBehavior: "toggle", selectedKeys: selectedKeys, onSelectionChange: handleListboxSelectionChange, disallowEmptySelection: false, hideSelectedIcon: true, classNames: {
6245
+ base: "w-full gap-0.5 p-0",
6246
+ list: "gap-0.5",
6247
+ }, itemClasses: {
6248
+ base: "rounded-medium px-2 py-2.5 data-[hover=true]:bg-default-100 data-[selectable=true]:focus:bg-default-100 data-[selected=true]:bg-primary-50/80",
6249
+ title: "text-small font-normal text-default-600 data-[selected=true]:font-medium data-[selected=true]:text-primary",
6250
+ }, children: filteredData.map(function (item) { return (jsxRuntime.jsx(react.ListboxItem, { textValue: item.label, children: item.label }, item.value)); }) })) })] }) })] }));
6132
6251
  };
6133
6252
  // =========================================================================
6134
6253
  // RANGE FILTER
@@ -6215,7 +6334,7 @@ var NumberFilter = function (_a) {
6215
6334
  *
6216
6335
  * Características:
6217
6336
  * - Dynamic header with title and description
6218
- * - Body with configurable filters (select, multiselect, range, date)
6337
+ * - Body with configurable filters (select, multiselect con panel; buscador si `searchable: true`, range, date)
6219
6338
  * - Footer with action buttons (clear, cancel, apply)
6220
6339
  * - Internal state management of filters
6221
6340
  * - Callback for applying filters with processed values
@@ -6296,7 +6415,10 @@ var DrawerFilters = function (_a) {
6296
6415
  }
6297
6416
  break;
6298
6417
  case "number":
6299
- if (value && "value" in value && value.value !== null && value.value !== undefined) {
6418
+ if (value &&
6419
+ "value" in value &&
6420
+ value.value !== null &&
6421
+ value.value !== undefined) {
6300
6422
  processedFilters[key] = String(value.value);
6301
6423
  }
6302
6424
  break;
@@ -6311,7 +6433,7 @@ var DrawerFilters = function (_a) {
6311
6433
  onOpenChange(false);
6312
6434
  }, [filterValues, config.data, onApplyFilters, onOpenChange]);
6313
6435
  return (jsxRuntime.jsx(react.Drawer, { isOpen: isOpen, onOpenChange: handleOpenChange, placement: "right", size: "md", className: react.cn("drawer-filters", className), isDismissable: false, hideCloseButton: false, children: jsxRuntime.jsxs(react.DrawerContent, { children: [jsxRuntime.jsx(DrawerFiltersHeader, { title: config.title, description: config.description }), jsxRuntime.jsx(react.DrawerBody, { className: "px-6 py-10", children: jsxRuntime.jsx("div", { className: "space-y-3", children: config.data.map(function (filter) {
6314
- return (jsxRuntime.jsx(FilterSection, { filter: filter, value: filterValues[filter.key], onChange: function (value) { return handleFilterChange(filter.key, value); } }, filter.key));
6436
+ return (jsxRuntime.jsx(FilterSection, { filter: filter, translations: translations, value: filterValues[filter.key], onChange: function (value) { return handleFilterChange(filter.key, value); } }, filter.key));
6315
6437
  }) }) }), jsxRuntime.jsx(DrawerFiltersFooter, { onClearFilters: handleClearFilters, onCancel: handleCancel, onApplyFilters: handleApplyFilters, translations: translations })] }) }));
6316
6438
  };
6317
6439
  DrawerFilters.displayName = "DrawerFilters";
@@ -7013,7 +7135,157 @@ var ModalContent = react.ModalContent;
7013
7135
 
7014
7136
  var ModalHeader = react.ModalHeader;
7015
7137
 
7016
- var ModalBody = react.ModalBody;
7138
+ var ModalBody = React.forwardRef(function (props, forwardedRef) {
7139
+ var nodeRef = React.useRef(null);
7140
+ var callbackRef = React.useCallback(function (node) {
7141
+ nodeRef.current = node;
7142
+ if (forwardedRef) {
7143
+ if (typeof forwardedRef === "function")
7144
+ forwardedRef(node);
7145
+ else
7146
+ forwardedRef.current = node;
7147
+ }
7148
+ }, [forwardedRef]);
7149
+ React.useEffect(function () {
7150
+ var node = nodeRef.current;
7151
+ if (!node)
7152
+ return;
7153
+ var parent = node.parentElement;
7154
+ if (!parent)
7155
+ return;
7156
+ // Hide native scrollbar
7157
+ node.style.scrollbarWidth = "none";
7158
+ // Parent needs relative positioning for the track
7159
+ var parentPos = window.getComputedStyle(parent).position;
7160
+ if (parentPos === "static") {
7161
+ parent.style.position = "relative";
7162
+ }
7163
+ // Create track — placed on the PARENT so it doesn't scroll
7164
+ var track = document.createElement("div");
7165
+ track.setAttribute("data-auraui-scrollbar", "track");
7166
+ Object.assign(track.style, {
7167
+ position: "absolute",
7168
+ right: "20px",
7169
+ width: "6px",
7170
+ zIndex: "10",
7171
+ cursor: "pointer",
7172
+ });
7173
+ // Create thumb
7174
+ var thumb = document.createElement("div");
7175
+ thumb.setAttribute("data-auraui-scrollbar", "thumb");
7176
+ Object.assign(thumb.style, {
7177
+ width: "6px",
7178
+ borderRadius: "3px",
7179
+ backgroundColor: "rgba(255,255,255,0.28)",
7180
+ cursor: "grab",
7181
+ });
7182
+ track.appendChild(thumb);
7183
+ parent.appendChild(track);
7184
+ // --- Scroll position update ---
7185
+ var trackHeight = 0;
7186
+ var thumbH = 0;
7187
+ var update = function () {
7188
+ var scrollTop = node.scrollTop, scrollHeight = node.scrollHeight, clientHeight = node.clientHeight;
7189
+ var hasOverflow = scrollHeight > clientHeight;
7190
+ if (!hasOverflow) {
7191
+ track.style.display = "none";
7192
+ return;
7193
+ }
7194
+ track.style.display = "block";
7195
+ var nodeRect = node.getBoundingClientRect();
7196
+ var parentRect = parent.getBoundingClientRect();
7197
+ var trackTop = nodeRect.top - parentRect.top;
7198
+ trackHeight = nodeRect.height;
7199
+ track.style.top = "".concat(trackTop, "px");
7200
+ track.style.height = "".concat(trackHeight, "px");
7201
+ var ratio = clientHeight / scrollHeight;
7202
+ thumbH = Math.max(ratio * trackHeight, 30);
7203
+ var maxScroll = scrollHeight - clientHeight;
7204
+ var thumbTop = maxScroll > 0
7205
+ ? (scrollTop / maxScroll) * (trackHeight - thumbH)
7206
+ : 0;
7207
+ thumb.style.height = "".concat(thumbH, "px");
7208
+ thumb.style.marginTop = "".concat(thumbTop, "px");
7209
+ };
7210
+ node.addEventListener("scroll", update, { passive: true });
7211
+ var ro = new ResizeObserver(update);
7212
+ ro.observe(node);
7213
+ requestAnimationFrame(update);
7214
+ // --- Drag support ---
7215
+ var isDragging = false;
7216
+ var startY = 0;
7217
+ var startScrollTop = 0;
7218
+ var getIsDark = function () {
7219
+ return document.documentElement.classList.contains("dark") ||
7220
+ document.documentElement.getAttribute("data-theme") === "dark" ||
7221
+ document.body.classList.contains("dark");
7222
+ };
7223
+ var onMouseDown = function (e) {
7224
+ e.preventDefault();
7225
+ e.stopPropagation();
7226
+ isDragging = true;
7227
+ startY = e.clientY;
7228
+ startScrollTop = node.scrollTop;
7229
+ thumb.style.cursor = "grabbing";
7230
+ thumb.style.backgroundColor = getIsDark()
7231
+ ? "rgba(255,255,255,0.45)"
7232
+ : "rgba(0,0,0,0.55)";
7233
+ document.addEventListener("mousemove", onMouseMove);
7234
+ document.addEventListener("mouseup", onMouseUp);
7235
+ };
7236
+ var onMouseMove = function (e) {
7237
+ if (!isDragging)
7238
+ return;
7239
+ e.preventDefault();
7240
+ var deltaY = e.clientY - startY;
7241
+ var maxScroll = node.scrollHeight - node.clientHeight;
7242
+ var scrollDelta = (deltaY / (trackHeight - thumbH)) * maxScroll;
7243
+ node.scrollTop = startScrollTop + scrollDelta;
7244
+ };
7245
+ var onMouseUp = function () {
7246
+ isDragging = false;
7247
+ thumb.style.cursor = "grab";
7248
+ detectTheme(); // Reset thumb color
7249
+ document.removeEventListener("mousemove", onMouseMove);
7250
+ document.removeEventListener("mouseup", onMouseUp);
7251
+ };
7252
+ // Click on track to jump
7253
+ var onTrackClick = function (e) {
7254
+ if (e.target === thumb)
7255
+ return;
7256
+ var trackRect = track.getBoundingClientRect();
7257
+ var clickRatio = (e.clientY - trackRect.top) / trackHeight;
7258
+ node.scrollTop =
7259
+ clickRatio * (node.scrollHeight - node.clientHeight);
7260
+ };
7261
+ thumb.addEventListener("mousedown", onMouseDown);
7262
+ track.addEventListener("click", onTrackClick);
7263
+ // --- Theme detection ---
7264
+ var detectTheme = function () {
7265
+ if (isDragging)
7266
+ return;
7267
+ thumb.style.backgroundColor = getIsDark()
7268
+ ? "rgba(255,255,255,0.28)"
7269
+ : "rgba(0,0,0,0.4)";
7270
+ };
7271
+ detectTheme();
7272
+ var mo = new MutationObserver(detectTheme);
7273
+ mo.observe(document.documentElement, {
7274
+ attributes: true,
7275
+ attributeFilter: ["class", "data-theme", "style"],
7276
+ });
7277
+ return function () {
7278
+ node.removeEventListener("scroll", update);
7279
+ ro.disconnect();
7280
+ mo.disconnect();
7281
+ document.removeEventListener("mousemove", onMouseMove);
7282
+ document.removeEventListener("mouseup", onMouseUp);
7283
+ track.remove();
7284
+ };
7285
+ }, []);
7286
+ return (jsxRuntime.jsx(react.ModalBody, __assign({ ref: callbackRef }, props)));
7287
+ });
7288
+ ModalBody.displayName = "ModalBody";
7017
7289
 
7018
7290
  var ModalFooter = react.ModalFooter;
7019
7291