@dreamtree-org/twreact-ui 1.0.69 → 1.0.71
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.esm.js +287 -110
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +286 -109
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import React__default, { forwardRef, createElement, useId, useRef, useState, useEffect, useImperativeHandle, useMemo, useCallback, createContext, useContext, cloneElement, PureComponent } from 'react';
|
|
2
|
+
import React__default, { forwardRef, createElement, useId, useRef, useState, useEffect, useImperativeHandle, useMemo, useLayoutEffect, useCallback, createContext, useContext, cloneElement, PureComponent } from 'react';
|
|
3
3
|
import ReactDOM, { createPortal } from 'react-dom';
|
|
4
4
|
|
|
5
5
|
function _extends() {
|
|
@@ -3863,7 +3863,7 @@ var Select = /*#__PURE__*/React__default.forwardRef(function (_ref, forwardedRef
|
|
|
3863
3863
|
}, error));
|
|
3864
3864
|
});
|
|
3865
3865
|
|
|
3866
|
-
var _excluded$k = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "stripedColors", "responsiveBreakpoint"];
|
|
3866
|
+
var _excluded$k = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "stripedColors", "responsiveBreakpoint", "serverSide", "totalRecords", "pageNumber", "onPageChange"];
|
|
3867
3867
|
function ownKeys$9(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3868
3868
|
function _objectSpread$9(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$9(Object(t), true).forEach(function (r) { _defineProperty$4(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$9(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3869
3869
|
var Table = function Table(_ref) {
|
|
@@ -3917,7 +3917,13 @@ var Table = function Table(_ref) {
|
|
|
3917
3917
|
stripedColors = _ref$stripedColors === void 0 ? ["#ffffff", "#f7fafc"] : _ref$stripedColors,
|
|
3918
3918
|
_ref$responsiveBreakp = _ref.responsiveBreakpoint,
|
|
3919
3919
|
responsiveBreakpoint = _ref$responsiveBreakp === void 0 ? 768 : _ref$responsiveBreakp,
|
|
3920
|
-
|
|
3920
|
+
_ref$serverSide = _ref.serverSide,
|
|
3921
|
+
serverSide = _ref$serverSide === void 0 ? false : _ref$serverSide,
|
|
3922
|
+
_ref$totalRecords = _ref.totalRecords,
|
|
3923
|
+
totalRecords = _ref$totalRecords === void 0 ? 0 : _ref$totalRecords,
|
|
3924
|
+
pageNumber = _ref.pageNumber;
|
|
3925
|
+
_ref.onPageChange;
|
|
3926
|
+
var props = _objectWithoutProperties$1(_ref, _excluded$k);
|
|
3921
3927
|
// State for responsive view
|
|
3922
3928
|
var _useState = useState(false),
|
|
3923
3929
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -3978,7 +3984,7 @@ var Table = function Table(_ref) {
|
|
|
3978
3984
|
_useState16 = _slicedToArray(_useState15, 2),
|
|
3979
3985
|
expandedRows = _useState16[0],
|
|
3980
3986
|
setExpandedRows = _useState16[1];
|
|
3981
|
-
var _useState17 = useState(1),
|
|
3987
|
+
var _useState17 = useState(typeof pageNumber === "number" ? pageNumber : 1),
|
|
3982
3988
|
_useState18 = _slicedToArray(_useState17, 2),
|
|
3983
3989
|
currentPage = _useState18[0],
|
|
3984
3990
|
setCurrentPage = _useState18[1];
|
|
@@ -4008,6 +4014,14 @@ var Table = function Table(_ref) {
|
|
|
4008
4014
|
openActionKey = _useState28[0],
|
|
4009
4015
|
setOpenActionKey = _useState28[1];
|
|
4010
4016
|
var openRef = useRef(null);
|
|
4017
|
+
useEffect(function () {
|
|
4018
|
+
if (typeof pageNumber === "number" && pageNumber !== currentPage) {
|
|
4019
|
+
setCurrentPage(pageNumber);
|
|
4020
|
+
}
|
|
4021
|
+
}, [pageNumber]);
|
|
4022
|
+
useEffect(function () {
|
|
4023
|
+
setLimit(pageSize);
|
|
4024
|
+
}, [pageSize]);
|
|
4011
4025
|
|
|
4012
4026
|
// Check if mobile view
|
|
4013
4027
|
useEffect(function () {
|
|
@@ -4027,9 +4041,6 @@ var Table = function Table(_ref) {
|
|
|
4027
4041
|
var isValidList = function isValidList(d) {
|
|
4028
4042
|
return Array.isArray(d);
|
|
4029
4043
|
};
|
|
4030
|
-
var setDataForExternal = function setDataForExternal(newData) {
|
|
4031
|
-
if (isValidList(newData)) setTableData(newData);else setTableData([]);
|
|
4032
|
-
};
|
|
4033
4044
|
|
|
4034
4045
|
// Close column menu when clicking outside
|
|
4035
4046
|
useEffect(function () {
|
|
@@ -4126,70 +4137,42 @@ var Table = function Table(_ref) {
|
|
|
4126
4137
|
|
|
4127
4138
|
// Sorting
|
|
4128
4139
|
var sortedData = useMemo(function () {
|
|
4129
|
-
if (!sortConfig.key) return tableData;
|
|
4140
|
+
if (serverSide || !sortConfig.key) return tableData;
|
|
4130
4141
|
var key = sortConfig.key,
|
|
4131
4142
|
direction = sortConfig.direction;
|
|
4132
4143
|
return _toConsumableArray$1(tableData).sort(function (a, b) {
|
|
4133
|
-
var
|
|
4134
|
-
var
|
|
4135
|
-
if (
|
|
4136
|
-
if (
|
|
4137
|
-
|
|
4138
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
4139
|
-
return direction === "asc" ? aValue - bValue : bValue - aValue;
|
|
4140
|
-
}
|
|
4141
|
-
var aStr = String(aValue).toLowerCase();
|
|
4142
|
-
var bStr = String(bValue).toLowerCase();
|
|
4143
|
-
if (aStr < bStr) return direction === "asc" ? -1 : 1;
|
|
4144
|
-
if (aStr > bStr) return direction === "asc" ? 1 : -1;
|
|
4145
|
-
return 0;
|
|
4144
|
+
var av = a === null || a === void 0 ? void 0 : a[key];
|
|
4145
|
+
var bv = b === null || b === void 0 ? void 0 : b[key];
|
|
4146
|
+
if (av == null || bv == null) return 0;
|
|
4147
|
+
if (typeof av === "number") return direction === "asc" ? av - bv : bv - av;
|
|
4148
|
+
return direction === "asc" ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
|
|
4146
4149
|
});
|
|
4147
|
-
}, [tableData, sortConfig]);
|
|
4150
|
+
}, [tableData, sortConfig, serverSide]);
|
|
4148
4151
|
|
|
4149
4152
|
// Filtering
|
|
4150
4153
|
var filteredData = useMemo(function () {
|
|
4151
|
-
if (!filterable || Object.keys(filters).length
|
|
4152
|
-
var
|
|
4154
|
+
if (serverSide || !filterable || !Object.keys(filters).length) return sortedData;
|
|
4155
|
+
var q = (filters.global || "").toLowerCase();
|
|
4153
4156
|
return sortedData.filter(function (row) {
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
var _ref3 = _slicedToArray(_ref2, 2),
|
|
4157
|
-
key = _ref3[0],
|
|
4158
|
-
value = _ref3[1];
|
|
4159
|
-
if (key === "global") return true;
|
|
4160
|
-
if (!value) return true;
|
|
4161
|
-
var cell = row === null || row === void 0 ? void 0 : row[key];
|
|
4162
|
-
if (cell == null) return false;
|
|
4163
|
-
return String(cell).toLowerCase().includes(String(value).toLowerCase());
|
|
4157
|
+
return Object.values(row || {}).some(function (v) {
|
|
4158
|
+
return String(v).toLowerCase().includes(q);
|
|
4164
4159
|
});
|
|
4165
|
-
if (!perColumnOk) return false;
|
|
4166
|
-
|
|
4167
|
-
// Global filter
|
|
4168
|
-
if (globalQuery) {
|
|
4169
|
-
var matchesVisible = visibleColumns.some(function (col) {
|
|
4170
|
-
var v = row === null || row === void 0 ? void 0 : row[col.key];
|
|
4171
|
-
if (v == null) return false;
|
|
4172
|
-
return String(v).toLowerCase().includes(globalQuery);
|
|
4173
|
-
});
|
|
4174
|
-
if (matchesVisible) return true;
|
|
4175
|
-
return Object.values(row || {}).some(function (v) {
|
|
4176
|
-
return v != null ? String(v).toLowerCase().includes(globalQuery) : false;
|
|
4177
|
-
});
|
|
4178
|
-
}
|
|
4179
|
-
return true;
|
|
4180
4160
|
});
|
|
4181
|
-
}, [sortedData, filters, filterable,
|
|
4182
|
-
|
|
4161
|
+
}, [sortedData, filters, filterable, serverSide]);
|
|
4183
4162
|
// Pagination indices
|
|
4184
4163
|
var startIndex = pagination ? (currentPage - 1) * limit : 0;
|
|
4185
4164
|
var endIndex = pagination ? startIndex + limit : filteredData.length;
|
|
4186
4165
|
|
|
4187
4166
|
// Paginated view
|
|
4188
4167
|
var paginatedData = useMemo(function () {
|
|
4189
|
-
if (!pagination) return filteredData;
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4168
|
+
if (!pagination || serverSide) return filteredData;
|
|
4169
|
+
var start = (currentPage - 1) * limit;
|
|
4170
|
+
return filteredData.slice(start, start + limit);
|
|
4171
|
+
}, [filteredData, pagination, serverSide, currentPage, limit]);
|
|
4172
|
+
var totalPages = useMemo(function () {
|
|
4173
|
+
if (!pagination) return 1;
|
|
4174
|
+
return serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
|
|
4175
|
+
}, [pagination, serverSide, totalRecords, filteredData.length, limit]);
|
|
4193
4176
|
|
|
4194
4177
|
// Sorting handler
|
|
4195
4178
|
var handleSort = function handleSort(key) {
|
|
@@ -4304,17 +4287,19 @@ var Table = function Table(_ref) {
|
|
|
4304
4287
|
useEffect(function () {
|
|
4305
4288
|
if (!onFetch) return;
|
|
4306
4289
|
onFetch({
|
|
4307
|
-
setData:
|
|
4308
|
-
|
|
4290
|
+
setData: function setData(rows) {
|
|
4291
|
+
return setTableData(Array.isArray(rows) ? rows : []);
|
|
4292
|
+
},
|
|
4309
4293
|
setLoading: setLoading,
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
nextRecords: paginatedData
|
|
4315
|
-
}
|
|
4294
|
+
filters: filters,
|
|
4295
|
+
page: currentPage,
|
|
4296
|
+
limit: limit,
|
|
4297
|
+
sort: sortConfig
|
|
4316
4298
|
});
|
|
4317
|
-
}, [filters, currentPage, limit]);
|
|
4299
|
+
}, [onFetch, filters, currentPage, limit, sortConfig]);
|
|
4300
|
+
useEffect(function () {
|
|
4301
|
+
if (!serverSide) setTableData(data);
|
|
4302
|
+
}, [data, serverSide]);
|
|
4318
4303
|
useEffect(function () {
|
|
4319
4304
|
if (!onFetch && isValidList(data)) setTableData(data);
|
|
4320
4305
|
}, [data, onFetch]);
|
|
@@ -4332,13 +4317,11 @@ var Table = function Table(_ref) {
|
|
|
4332
4317
|
applyGlobalSearch();
|
|
4333
4318
|
}
|
|
4334
4319
|
};
|
|
4335
|
-
useEffect(function () {
|
|
4336
|
-
setLimit(pageSize);
|
|
4337
|
-
}, [pageSize]);
|
|
4338
4320
|
var handleLimitChange = function handleLimitChange(nextLimit) {
|
|
4339
4321
|
var parsed = Number(nextLimit);
|
|
4340
4322
|
if (!Number.isFinite(parsed) || parsed <= 0) return;
|
|
4341
4323
|
setLimit(parsed);
|
|
4324
|
+
setCurrentPage(1);
|
|
4342
4325
|
onLimitChange === null || onLimitChange === void 0 || onLimitChange(parsed);
|
|
4343
4326
|
};
|
|
4344
4327
|
|
|
@@ -4681,7 +4664,7 @@ var Table = function Table(_ref) {
|
|
|
4681
4664
|
}, /*#__PURE__*/React__default.createElement("input", {
|
|
4682
4665
|
type: "text",
|
|
4683
4666
|
placeholder: "Filter ".concat(column.label),
|
|
4684
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm",
|
|
4667
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm font-normal",
|
|
4685
4668
|
value: filters[column.key] || "",
|
|
4686
4669
|
onChange: function onChange(e) {
|
|
4687
4670
|
return handleFilter(column.key, e.target.value);
|
|
@@ -4881,20 +4864,15 @@ var Table = function Table(_ref) {
|
|
|
4881
4864
|
}
|
|
4882
4865
|
}, "Next")))));
|
|
4883
4866
|
};
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
menuRef = _ref4.menuRef;
|
|
4894
|
-
var _useState29 = useState(0),
|
|
4895
|
-
_useState30 = _slicedToArray(_useState29, 2),
|
|
4896
|
-
setTick = _useState30[1];
|
|
4897
|
-
var _useState31 = useState({
|
|
4867
|
+
function ActionMenuPortal(_ref2) {
|
|
4868
|
+
var anchorElem = _ref2.anchorElem,
|
|
4869
|
+
anchorRow = _ref2.anchorRow,
|
|
4870
|
+
_ref2$actions = _ref2.actions,
|
|
4871
|
+
actions = _ref2$actions === void 0 ? [] : _ref2$actions;
|
|
4872
|
+
_ref2.onClose;
|
|
4873
|
+
var onAction = _ref2.onAction,
|
|
4874
|
+
menuRef = _ref2.menuRef;
|
|
4875
|
+
var _useState29 = useState({
|
|
4898
4876
|
left: 0,
|
|
4899
4877
|
top: 0,
|
|
4900
4878
|
transformOrigin: "top right",
|
|
@@ -4902,11 +4880,15 @@ function ActionMenuPortal(_ref4) {
|
|
|
4902
4880
|
width: 180,
|
|
4903
4881
|
opacity: 0
|
|
4904
4882
|
}),
|
|
4905
|
-
|
|
4906
|
-
style =
|
|
4907
|
-
setStyle =
|
|
4883
|
+
_useState30 = _slicedToArray(_useState29, 2),
|
|
4884
|
+
style = _useState30[0],
|
|
4885
|
+
setStyle = _useState30[1];
|
|
4908
4886
|
var menuWidth = 180;
|
|
4909
4887
|
var maxMenuHeight = 320;
|
|
4888
|
+
var margin = 8;
|
|
4889
|
+
var minMenuHeight = 80;
|
|
4890
|
+
|
|
4891
|
+
// compute position using actual menu height (if available) and layout measurements
|
|
4910
4892
|
var computePosition = function computePosition() {
|
|
4911
4893
|
if (!anchorElem) return;
|
|
4912
4894
|
var rect = anchorElem.getBoundingClientRect();
|
|
@@ -4914,52 +4896,95 @@ function ActionMenuPortal(_ref4) {
|
|
|
4914
4896
|
var scrollX = window.scrollX || window.pageXOffset;
|
|
4915
4897
|
var spaceBelow = window.innerHeight - rect.bottom;
|
|
4916
4898
|
var spaceAbove = rect.top;
|
|
4917
|
-
|
|
4899
|
+
|
|
4900
|
+
// allowed max height based on available space
|
|
4901
|
+
var allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, Math.max(spaceBelow - margin, spaceAbove - margin)));
|
|
4902
|
+
|
|
4903
|
+
// choose placement by comparing actual available spaces
|
|
4918
4904
|
var placement = "bottom";
|
|
4919
|
-
var maxHeight = Math.min(maxMenuHeight, Math.max(80, spaceBelow - 16));
|
|
4920
4905
|
if (spaceBelow < 160 && spaceAbove > spaceBelow) {
|
|
4921
4906
|
placement = "top";
|
|
4922
|
-
|
|
4923
|
-
|
|
4907
|
+
// when placing on top we should cap allowedMaxHeight by spaceAbove
|
|
4908
|
+
allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceAbove - margin));
|
|
4924
4909
|
} else {
|
|
4925
|
-
|
|
4910
|
+
// placing bottom: cap by spaceBelow
|
|
4911
|
+
allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceBelow - margin));
|
|
4926
4912
|
}
|
|
4913
|
+
|
|
4914
|
+
// measure the menu's content height if we can, and compute the actual menu height we'll use.
|
|
4915
|
+
var measuredMenuHeight = allowedMaxHeight;
|
|
4916
|
+
var menuEl = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current;
|
|
4917
|
+
if (menuEl) {
|
|
4918
|
+
// scrollHeight is the content height; offsetHeight may reflect current rendered height.
|
|
4919
|
+
var contentHeight = menuEl.scrollHeight || menuEl.offsetHeight || allowedMaxHeight;
|
|
4920
|
+
// actual height will be min(contentHeight, allowedMaxHeight)
|
|
4921
|
+
measuredMenuHeight = Math.min(contentHeight, allowedMaxHeight);
|
|
4922
|
+
}
|
|
4923
|
+
|
|
4924
|
+
// compute top according to placement and measuredMenuHeight
|
|
4925
|
+
var top;
|
|
4926
|
+
if (placement === "top") {
|
|
4927
|
+
// place menu so its bottom sits just above the anchor (rect.top - margin)
|
|
4928
|
+
top = rect.top + scrollY - measuredMenuHeight - margin;
|
|
4929
|
+
} else {
|
|
4930
|
+
// place menu just below the anchor (rect.bottom + margin)
|
|
4931
|
+
top = rect.bottom + scrollY + margin;
|
|
4932
|
+
}
|
|
4933
|
+
|
|
4934
|
+
// clamp top to viewport (so it never goes off-screen)
|
|
4935
|
+
var minTop = margin + scrollY;
|
|
4936
|
+
var maxTop = window.innerHeight + scrollY - measuredMenuHeight - margin;
|
|
4937
|
+
if (top < minTop) top = minTop;
|
|
4938
|
+
if (top > maxTop) top = maxTop;
|
|
4939
|
+
|
|
4940
|
+
// compute left and clamp horizontally
|
|
4927
4941
|
var left = rect.right + scrollX - menuWidth;
|
|
4928
|
-
if (left <
|
|
4929
|
-
if (left + menuWidth > window.innerWidth -
|
|
4942
|
+
if (left < margin) left = margin;
|
|
4943
|
+
if (left + menuWidth > window.innerWidth - margin) {
|
|
4944
|
+
left = Math.max(margin, window.innerWidth - menuWidth - margin);
|
|
4945
|
+
}
|
|
4930
4946
|
var transformOrigin = placement === "bottom" ? "top right" : "bottom right";
|
|
4947
|
+
|
|
4948
|
+
// set style (opacity 1 to fade-in)
|
|
4931
4949
|
setStyle({
|
|
4932
4950
|
left: left,
|
|
4933
4951
|
top: top,
|
|
4934
4952
|
transformOrigin: transformOrigin,
|
|
4935
|
-
maxHeight:
|
|
4953
|
+
maxHeight: allowedMaxHeight,
|
|
4936
4954
|
width: menuWidth,
|
|
4937
4955
|
opacity: 1
|
|
4938
4956
|
});
|
|
4939
4957
|
};
|
|
4940
|
-
|
|
4958
|
+
|
|
4959
|
+
// useLayoutEffect so the position is measured & applied before paint
|
|
4960
|
+
useLayoutEffect(function () {
|
|
4961
|
+
// compute once after mount
|
|
4941
4962
|
computePosition();
|
|
4942
4963
|
var onScrollOrResize = function onScrollOrResize() {
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
return
|
|
4964
|
+
// using requestAnimationFrame to avoid layout thrash on fast scroll/resize
|
|
4965
|
+
window.requestAnimationFrame(function () {
|
|
4966
|
+
return computePosition();
|
|
4946
4967
|
});
|
|
4947
4968
|
};
|
|
4948
4969
|
window.addEventListener("resize", onScrollOrResize);
|
|
4970
|
+
// capture scrolls (true) so position updates even when scrolling ancestor elements
|
|
4949
4971
|
window.addEventListener("scroll", onScrollOrResize, true);
|
|
4950
4972
|
return function () {
|
|
4951
4973
|
window.removeEventListener("resize", onScrollOrResize);
|
|
4952
4974
|
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
4953
4975
|
};
|
|
4954
|
-
|
|
4976
|
+
// Recompute when anchor element changes or actions change (content height may change).
|
|
4977
|
+
}, [anchorElem, actions, menuRef]);
|
|
4955
4978
|
return /*#__PURE__*/createPortal(/*#__PURE__*/React__default.createElement("div", {
|
|
4956
4979
|
ref: menuRef,
|
|
4957
4980
|
style: {
|
|
4981
|
+
position: "absolute",
|
|
4958
4982
|
top: style.top,
|
|
4959
4983
|
left: style.left,
|
|
4960
4984
|
width: style.width,
|
|
4961
4985
|
maxHeight: style.maxHeight,
|
|
4962
|
-
transformOrigin: style.transformOrigin
|
|
4986
|
+
transformOrigin: style.transformOrigin,
|
|
4987
|
+
opacity: style.opacity
|
|
4963
4988
|
},
|
|
4964
4989
|
className: "absolute z-50 bg-white rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 overflow-y-auto transition-opacity duration-150 ease-out",
|
|
4965
4990
|
onClick: function onClick(e) {
|
|
@@ -10350,7 +10375,12 @@ var DatePicker = /*#__PURE__*/React__default.forwardRef(function (_ref, forwarde
|
|
|
10350
10375
|
currentMonth = _useState4[0],
|
|
10351
10376
|
setCurrentMonth = _useState4[1];
|
|
10352
10377
|
var datePickerRef = useRef(null);
|
|
10378
|
+
var popupRef = useRef(null);
|
|
10353
10379
|
var gridButtonRefs = useRef([]);
|
|
10380
|
+
var _useState5 = useState({}),
|
|
10381
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
10382
|
+
popupStyle = _useState6[0],
|
|
10383
|
+
setPopupStyle = _useState6[1];
|
|
10354
10384
|
useImperativeHandle(forwardedRef, function () {
|
|
10355
10385
|
return datePickerRef.current;
|
|
10356
10386
|
}, []);
|
|
@@ -10363,7 +10393,7 @@ var DatePicker = /*#__PURE__*/React__default.forwardRef(function (_ref, forwarde
|
|
|
10363
10393
|
// Close on outside click
|
|
10364
10394
|
useEffect(function () {
|
|
10365
10395
|
var handleClickOutside = function handleClickOutside(e) {
|
|
10366
|
-
if (datePickerRef.current && !datePickerRef.current.contains(e.target)) {
|
|
10396
|
+
if (datePickerRef.current && !datePickerRef.current.contains(e.target) && popupRef.current && !popupRef.current.contains(e.target)) {
|
|
10367
10397
|
setIsOpen(false);
|
|
10368
10398
|
}
|
|
10369
10399
|
};
|
|
@@ -10479,6 +10509,75 @@ var DatePicker = /*#__PURE__*/React__default.forwardRef(function (_ref, forwarde
|
|
|
10479
10509
|
if (idx >= 0) focusDayAtIndex(idx);
|
|
10480
10510
|
}, 0);
|
|
10481
10511
|
};
|
|
10512
|
+
|
|
10513
|
+
// compute popup position so it's aware of viewport edges (top/bottom/left/right)
|
|
10514
|
+
var computePopupPosition = function computePopupPosition() {
|
|
10515
|
+
var margin = 8;
|
|
10516
|
+
var trigger = datePickerRef.current;
|
|
10517
|
+
var popup = popupRef.current;
|
|
10518
|
+
if (!trigger || !popup) return;
|
|
10519
|
+
var triggerRect = trigger.getBoundingClientRect();
|
|
10520
|
+
// measure popup by temporarily making it visible if hidden
|
|
10521
|
+
var popupRect = popup.getBoundingClientRect();
|
|
10522
|
+
|
|
10523
|
+
// If the popup is not yet fully measured (width/height 0), try to read offsetWidth/Height
|
|
10524
|
+
if (popupRect.width === 0 || popupRect.height === 0) {
|
|
10525
|
+
popupRect = {
|
|
10526
|
+
width: popup.offsetWidth || 240,
|
|
10527
|
+
height: popup.offsetHeight || 300
|
|
10528
|
+
};
|
|
10529
|
+
}
|
|
10530
|
+
|
|
10531
|
+
// Decide vertical placement
|
|
10532
|
+
var spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
10533
|
+
var spaceAbove = triggerRect.top;
|
|
10534
|
+
var placeBelow = spaceBelow >= popupRect.height + margin;
|
|
10535
|
+
if (!placeBelow && spaceAbove >= popupRect.height + margin) placeBelow = false;
|
|
10536
|
+
// If neither side has full space, pick the side with more space
|
|
10537
|
+
if (!placeBelow && spaceBelow < popupRect.height + margin && spaceAbove < popupRect.height + margin) {
|
|
10538
|
+
placeBelow = spaceBelow >= spaceAbove;
|
|
10539
|
+
}
|
|
10540
|
+
|
|
10541
|
+
// compute top coordinate (fixed positioning)
|
|
10542
|
+
var top;
|
|
10543
|
+
if (placeBelow) {
|
|
10544
|
+
top = Math.min(window.innerHeight - margin - popupRect.height, triggerRect.bottom + margin);
|
|
10545
|
+
} else {
|
|
10546
|
+
top = Math.max(margin, triggerRect.top - popupRect.height - margin);
|
|
10547
|
+
}
|
|
10548
|
+
|
|
10549
|
+
// Decide horizontal placement (try align left to trigger)
|
|
10550
|
+
var left = triggerRect.left;
|
|
10551
|
+
// If overflowing right, shift left
|
|
10552
|
+
if (left + popupRect.width > window.innerWidth - margin) {
|
|
10553
|
+
left = Math.max(margin, window.innerWidth - margin - popupRect.width);
|
|
10554
|
+
}
|
|
10555
|
+
// If overflowing left, clamp
|
|
10556
|
+
if (left < margin) left = margin;
|
|
10557
|
+
var transformOrigin = placeBelow ? "top left" : "bottom left";
|
|
10558
|
+
setPopupStyle({
|
|
10559
|
+
position: "fixed",
|
|
10560
|
+
top: "".concat(Math.round(top), "px"),
|
|
10561
|
+
left: "".concat(Math.round(left), "px"),
|
|
10562
|
+
zIndex: 9999,
|
|
10563
|
+
transformOrigin: transformOrigin
|
|
10564
|
+
});
|
|
10565
|
+
};
|
|
10566
|
+
|
|
10567
|
+
// recompute on open, on resize/scroll, and when popup content changes (currentMonth)
|
|
10568
|
+
useLayoutEffect(function () {
|
|
10569
|
+
if (!isOpen) return;
|
|
10570
|
+
computePopupPosition();
|
|
10571
|
+
var handleResize = function handleResize() {
|
|
10572
|
+
return computePopupPosition();
|
|
10573
|
+
};
|
|
10574
|
+
window.addEventListener("resize", handleResize);
|
|
10575
|
+
window.addEventListener("scroll", handleResize, true); // capture scrolling in ancestors
|
|
10576
|
+
return function () {
|
|
10577
|
+
window.removeEventListener("resize", handleResize);
|
|
10578
|
+
window.removeEventListener("scroll", handleResize, true);
|
|
10579
|
+
};
|
|
10580
|
+
}, [isOpen, currentMonth]);
|
|
10482
10581
|
var header = /*#__PURE__*/React__default.createElement("div", {
|
|
10483
10582
|
className: "mb-4 flex items-center justify-between"
|
|
10484
10583
|
}, /*#__PURE__*/React__default.createElement("button", {
|
|
@@ -10503,9 +10602,11 @@ var DatePicker = /*#__PURE__*/React__default.forwardRef(function (_ref, forwarde
|
|
|
10503
10602
|
className: "h-4 w-4"
|
|
10504
10603
|
})));
|
|
10505
10604
|
var calendarPopup = /*#__PURE__*/React__default.createElement("div", {
|
|
10506
|
-
|
|
10605
|
+
ref: popupRef,
|
|
10606
|
+
className: "w-80 rounded-md border border-gray-300 bg-white p-4 shadow-lg",
|
|
10507
10607
|
role: "dialog",
|
|
10508
|
-
"aria-modal": "false"
|
|
10608
|
+
"aria-modal": "false",
|
|
10609
|
+
style: popupStyle
|
|
10509
10610
|
}, header, /*#__PURE__*/React__default.createElement("div", {
|
|
10510
10611
|
className: "mb-2 grid grid-cols-7 gap-1"
|
|
10511
10612
|
}, Array.from({
|
|
@@ -11854,11 +11955,10 @@ function Slider(_ref6) {
|
|
|
11854
11955
|
var _excluded$g = ["value", "onChange", "placeholder", "label", "error", "disabled", "required", "minDate", "maxDate", "className", "weekStartsOn", "portal", "displayFormat", "locale", "showClear", "closeOnSelect"];
|
|
11855
11956
|
|
|
11856
11957
|
/*
|
|
11857
|
-
Single-calendar DateRangePicker with hover-preview
|
|
11858
|
-
- Enforces mandatory range selection
|
|
11859
|
-
|
|
11860
|
-
- Popup
|
|
11861
|
-
a start date is selected. Use Clear to cancel the in-progress selection.
|
|
11958
|
+
Single-calendar DateRangePicker with hover-preview and space-aware popup positioning
|
|
11959
|
+
- Enforces mandatory range selection until both start and end are chosen.
|
|
11960
|
+
- Popup flips above/below and clamps horizontally to avoid clipping.
|
|
11961
|
+
- Popup won't close while only a start date is selected (Clear cancels in-progress selection).
|
|
11862
11962
|
*/
|
|
11863
11963
|
|
|
11864
11964
|
var normalizeDate = function normalizeDate(d) {
|
|
@@ -11932,11 +12032,16 @@ var DateRangePicker = function DateRangePicker(_ref) {
|
|
|
11932
12032
|
if (start) setCurrentMonth(start);
|
|
11933
12033
|
}, [start, end]);
|
|
11934
12034
|
var datePickerRef = useRef(null);
|
|
12035
|
+
var popupRef = useRef(null);
|
|
12036
|
+
var _useState1 = useState({}),
|
|
12037
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
12038
|
+
popupStyle = _useState10[0],
|
|
12039
|
+
setPopupStyle = _useState10[1];
|
|
11935
12040
|
|
|
11936
12041
|
// Outside click: only close if there is NOT an in-progress single-date selection
|
|
11937
12042
|
useEffect(function () {
|
|
11938
12043
|
var handleClickOutside = function handleClickOutside(e) {
|
|
11939
|
-
if (datePickerRef.current && !datePickerRef.current.contains(e.target)) {
|
|
12044
|
+
if (datePickerRef.current && !datePickerRef.current.contains(e.target) && (!popupRef.current || !popupRef.current.contains(e.target))) {
|
|
11940
12045
|
// If user has selected a start but no end, prevent closing to force range selection
|
|
11941
12046
|
if (localStart && !localEnd) {
|
|
11942
12047
|
return;
|
|
@@ -12092,10 +12197,82 @@ var DateRangePicker = function DateRangePicker(_ref) {
|
|
|
12092
12197
|
}, /*#__PURE__*/React__default.createElement(ChevronRight, {
|
|
12093
12198
|
className: "h-4 w-4"
|
|
12094
12199
|
})));
|
|
12200
|
+
|
|
12201
|
+
// compute popup position so it's aware of viewport edges (top/bottom/left/right)
|
|
12202
|
+
var computePopupPosition = function computePopupPosition() {
|
|
12203
|
+
var margin = 8;
|
|
12204
|
+
var trigger = datePickerRef.current;
|
|
12205
|
+
var popup = popupRef.current;
|
|
12206
|
+
if (!trigger || !popup) return;
|
|
12207
|
+
var triggerRect = trigger.getBoundingClientRect();
|
|
12208
|
+
// measure popup by temporarily making it visible if hidden
|
|
12209
|
+
var popupRect = popup.getBoundingClientRect();
|
|
12210
|
+
|
|
12211
|
+
// If the popup is not yet fully measured (width/height 0), try to read offsetWidth/Height
|
|
12212
|
+
if (popupRect.width === 0 || popupRect.height === 0) {
|
|
12213
|
+
popupRect = {
|
|
12214
|
+
width: popup.offsetWidth || 320,
|
|
12215
|
+
height: popup.offsetHeight || 300
|
|
12216
|
+
};
|
|
12217
|
+
}
|
|
12218
|
+
|
|
12219
|
+
// Decide vertical placement
|
|
12220
|
+
var spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
12221
|
+
var spaceAbove = triggerRect.top;
|
|
12222
|
+
var placeBelow = spaceBelow >= popupRect.height + margin;
|
|
12223
|
+
if (!placeBelow && spaceAbove >= popupRect.height + margin) placeBelow = false;
|
|
12224
|
+
// If neither side has full space, pick the side with more space
|
|
12225
|
+
if (!placeBelow && spaceBelow < popupRect.height + margin && spaceAbove < popupRect.height + margin) {
|
|
12226
|
+
placeBelow = spaceBelow >= spaceAbove;
|
|
12227
|
+
}
|
|
12228
|
+
|
|
12229
|
+
// compute top coordinate (fixed positioning)
|
|
12230
|
+
var top;
|
|
12231
|
+
if (placeBelow) {
|
|
12232
|
+
top = Math.min(window.innerHeight - margin - popupRect.height, triggerRect.bottom + margin);
|
|
12233
|
+
} else {
|
|
12234
|
+
top = Math.max(margin, triggerRect.top - popupRect.height - margin);
|
|
12235
|
+
}
|
|
12236
|
+
|
|
12237
|
+
// Decide horizontal placement (try align left to trigger)
|
|
12238
|
+
var left = triggerRect.left;
|
|
12239
|
+
// If overflowing right, shift left
|
|
12240
|
+
if (left + popupRect.width > window.innerWidth - margin) {
|
|
12241
|
+
left = Math.max(margin, window.innerWidth - margin - popupRect.width);
|
|
12242
|
+
}
|
|
12243
|
+
// If overflowing left, clamp
|
|
12244
|
+
if (left < margin) left = margin;
|
|
12245
|
+
var transformOrigin = placeBelow ? "top left" : "bottom left";
|
|
12246
|
+
setPopupStyle({
|
|
12247
|
+
position: "fixed",
|
|
12248
|
+
top: "".concat(Math.round(top), "px"),
|
|
12249
|
+
left: "".concat(Math.round(left), "px"),
|
|
12250
|
+
zIndex: 9999,
|
|
12251
|
+
transformOrigin: transformOrigin
|
|
12252
|
+
});
|
|
12253
|
+
};
|
|
12254
|
+
|
|
12255
|
+
// recompute on open, on resize/scroll, and when popup content changes (currentMonth)
|
|
12256
|
+
useLayoutEffect(function () {
|
|
12257
|
+
if (!isOpen) return;
|
|
12258
|
+
// compute on next frame to ensure popup ref exists in DOM (especially with portal)
|
|
12259
|
+
computePopupPosition();
|
|
12260
|
+
var handleResize = function handleResize() {
|
|
12261
|
+
return computePopupPosition();
|
|
12262
|
+
};
|
|
12263
|
+
window.addEventListener("resize", handleResize);
|
|
12264
|
+
window.addEventListener("scroll", handleResize, true); // capture scrolling in ancestors
|
|
12265
|
+
return function () {
|
|
12266
|
+
window.removeEventListener("resize", handleResize);
|
|
12267
|
+
window.removeEventListener("scroll", handleResize, true);
|
|
12268
|
+
};
|
|
12269
|
+
}, [isOpen, currentMonth]);
|
|
12095
12270
|
var calendarPopup = /*#__PURE__*/React__default.createElement("div", {
|
|
12096
|
-
|
|
12271
|
+
ref: popupRef,
|
|
12272
|
+
className: "w-80 rounded-md border border-gray-300 bg-white p-4 shadow-lg",
|
|
12097
12273
|
role: "dialog",
|
|
12098
|
-
"aria-modal": "false"
|
|
12274
|
+
"aria-modal": "false",
|
|
12275
|
+
style: popupStyle
|
|
12099
12276
|
}, header, /*#__PURE__*/React__default.createElement("div", {
|
|
12100
12277
|
className: "mb-2 grid grid-cols-7 gap-1"
|
|
12101
12278
|
}, Array.from({
|