@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.js
CHANGED
|
@@ -3883,7 +3883,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
3883
3883
|
}, error));
|
|
3884
3884
|
});
|
|
3885
3885
|
|
|
3886
|
-
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"];
|
|
3886
|
+
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"];
|
|
3887
3887
|
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; }
|
|
3888
3888
|
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; }
|
|
3889
3889
|
var Table = function Table(_ref) {
|
|
@@ -3937,7 +3937,13 @@ var Table = function Table(_ref) {
|
|
|
3937
3937
|
stripedColors = _ref$stripedColors === void 0 ? ["#ffffff", "#f7fafc"] : _ref$stripedColors,
|
|
3938
3938
|
_ref$responsiveBreakp = _ref.responsiveBreakpoint,
|
|
3939
3939
|
responsiveBreakpoint = _ref$responsiveBreakp === void 0 ? 768 : _ref$responsiveBreakp,
|
|
3940
|
-
|
|
3940
|
+
_ref$serverSide = _ref.serverSide,
|
|
3941
|
+
serverSide = _ref$serverSide === void 0 ? false : _ref$serverSide,
|
|
3942
|
+
_ref$totalRecords = _ref.totalRecords,
|
|
3943
|
+
totalRecords = _ref$totalRecords === void 0 ? 0 : _ref$totalRecords,
|
|
3944
|
+
pageNumber = _ref.pageNumber;
|
|
3945
|
+
_ref.onPageChange;
|
|
3946
|
+
var props = _objectWithoutProperties$1(_ref, _excluded$k);
|
|
3941
3947
|
// State for responsive view
|
|
3942
3948
|
var _useState = React.useState(false),
|
|
3943
3949
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -3998,7 +4004,7 @@ var Table = function Table(_ref) {
|
|
|
3998
4004
|
_useState16 = _slicedToArray(_useState15, 2),
|
|
3999
4005
|
expandedRows = _useState16[0],
|
|
4000
4006
|
setExpandedRows = _useState16[1];
|
|
4001
|
-
var _useState17 = React.useState(1),
|
|
4007
|
+
var _useState17 = React.useState(typeof pageNumber === "number" ? pageNumber : 1),
|
|
4002
4008
|
_useState18 = _slicedToArray(_useState17, 2),
|
|
4003
4009
|
currentPage = _useState18[0],
|
|
4004
4010
|
setCurrentPage = _useState18[1];
|
|
@@ -4028,6 +4034,14 @@ var Table = function Table(_ref) {
|
|
|
4028
4034
|
openActionKey = _useState28[0],
|
|
4029
4035
|
setOpenActionKey = _useState28[1];
|
|
4030
4036
|
var openRef = React.useRef(null);
|
|
4037
|
+
React.useEffect(function () {
|
|
4038
|
+
if (typeof pageNumber === "number" && pageNumber !== currentPage) {
|
|
4039
|
+
setCurrentPage(pageNumber);
|
|
4040
|
+
}
|
|
4041
|
+
}, [pageNumber]);
|
|
4042
|
+
React.useEffect(function () {
|
|
4043
|
+
setLimit(pageSize);
|
|
4044
|
+
}, [pageSize]);
|
|
4031
4045
|
|
|
4032
4046
|
// Check if mobile view
|
|
4033
4047
|
React.useEffect(function () {
|
|
@@ -4047,9 +4061,6 @@ var Table = function Table(_ref) {
|
|
|
4047
4061
|
var isValidList = function isValidList(d) {
|
|
4048
4062
|
return Array.isArray(d);
|
|
4049
4063
|
};
|
|
4050
|
-
var setDataForExternal = function setDataForExternal(newData) {
|
|
4051
|
-
if (isValidList(newData)) setTableData(newData);else setTableData([]);
|
|
4052
|
-
};
|
|
4053
4064
|
|
|
4054
4065
|
// Close column menu when clicking outside
|
|
4055
4066
|
React.useEffect(function () {
|
|
@@ -4146,70 +4157,42 @@ var Table = function Table(_ref) {
|
|
|
4146
4157
|
|
|
4147
4158
|
// Sorting
|
|
4148
4159
|
var sortedData = React.useMemo(function () {
|
|
4149
|
-
if (!sortConfig.key) return tableData;
|
|
4160
|
+
if (serverSide || !sortConfig.key) return tableData;
|
|
4150
4161
|
var key = sortConfig.key,
|
|
4151
4162
|
direction = sortConfig.direction;
|
|
4152
4163
|
return _toConsumableArray$1(tableData).sort(function (a, b) {
|
|
4153
|
-
var
|
|
4154
|
-
var
|
|
4155
|
-
if (
|
|
4156
|
-
if (
|
|
4157
|
-
|
|
4158
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
4159
|
-
return direction === "asc" ? aValue - bValue : bValue - aValue;
|
|
4160
|
-
}
|
|
4161
|
-
var aStr = String(aValue).toLowerCase();
|
|
4162
|
-
var bStr = String(bValue).toLowerCase();
|
|
4163
|
-
if (aStr < bStr) return direction === "asc" ? -1 : 1;
|
|
4164
|
-
if (aStr > bStr) return direction === "asc" ? 1 : -1;
|
|
4165
|
-
return 0;
|
|
4164
|
+
var av = a === null || a === void 0 ? void 0 : a[key];
|
|
4165
|
+
var bv = b === null || b === void 0 ? void 0 : b[key];
|
|
4166
|
+
if (av == null || bv == null) return 0;
|
|
4167
|
+
if (typeof av === "number") return direction === "asc" ? av - bv : bv - av;
|
|
4168
|
+
return direction === "asc" ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
|
|
4166
4169
|
});
|
|
4167
|
-
}, [tableData, sortConfig]);
|
|
4170
|
+
}, [tableData, sortConfig, serverSide]);
|
|
4168
4171
|
|
|
4169
4172
|
// Filtering
|
|
4170
4173
|
var filteredData = React.useMemo(function () {
|
|
4171
|
-
if (!filterable || Object.keys(filters).length
|
|
4172
|
-
var
|
|
4174
|
+
if (serverSide || !filterable || !Object.keys(filters).length) return sortedData;
|
|
4175
|
+
var q = (filters.global || "").toLowerCase();
|
|
4173
4176
|
return sortedData.filter(function (row) {
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
var _ref3 = _slicedToArray(_ref2, 2),
|
|
4177
|
-
key = _ref3[0],
|
|
4178
|
-
value = _ref3[1];
|
|
4179
|
-
if (key === "global") return true;
|
|
4180
|
-
if (!value) return true;
|
|
4181
|
-
var cell = row === null || row === void 0 ? void 0 : row[key];
|
|
4182
|
-
if (cell == null) return false;
|
|
4183
|
-
return String(cell).toLowerCase().includes(String(value).toLowerCase());
|
|
4177
|
+
return Object.values(row || {}).some(function (v) {
|
|
4178
|
+
return String(v).toLowerCase().includes(q);
|
|
4184
4179
|
});
|
|
4185
|
-
if (!perColumnOk) return false;
|
|
4186
|
-
|
|
4187
|
-
// Global filter
|
|
4188
|
-
if (globalQuery) {
|
|
4189
|
-
var matchesVisible = visibleColumns.some(function (col) {
|
|
4190
|
-
var v = row === null || row === void 0 ? void 0 : row[col.key];
|
|
4191
|
-
if (v == null) return false;
|
|
4192
|
-
return String(v).toLowerCase().includes(globalQuery);
|
|
4193
|
-
});
|
|
4194
|
-
if (matchesVisible) return true;
|
|
4195
|
-
return Object.values(row || {}).some(function (v) {
|
|
4196
|
-
return v != null ? String(v).toLowerCase().includes(globalQuery) : false;
|
|
4197
|
-
});
|
|
4198
|
-
}
|
|
4199
|
-
return true;
|
|
4200
4180
|
});
|
|
4201
|
-
}, [sortedData, filters, filterable,
|
|
4202
|
-
|
|
4181
|
+
}, [sortedData, filters, filterable, serverSide]);
|
|
4203
4182
|
// Pagination indices
|
|
4204
4183
|
var startIndex = pagination ? (currentPage - 1) * limit : 0;
|
|
4205
4184
|
var endIndex = pagination ? startIndex + limit : filteredData.length;
|
|
4206
4185
|
|
|
4207
4186
|
// Paginated view
|
|
4208
4187
|
var paginatedData = React.useMemo(function () {
|
|
4209
|
-
if (!pagination) return filteredData;
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4188
|
+
if (!pagination || serverSide) return filteredData;
|
|
4189
|
+
var start = (currentPage - 1) * limit;
|
|
4190
|
+
return filteredData.slice(start, start + limit);
|
|
4191
|
+
}, [filteredData, pagination, serverSide, currentPage, limit]);
|
|
4192
|
+
var totalPages = React.useMemo(function () {
|
|
4193
|
+
if (!pagination) return 1;
|
|
4194
|
+
return serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
|
|
4195
|
+
}, [pagination, serverSide, totalRecords, filteredData.length, limit]);
|
|
4213
4196
|
|
|
4214
4197
|
// Sorting handler
|
|
4215
4198
|
var handleSort = function handleSort(key) {
|
|
@@ -4324,17 +4307,19 @@ var Table = function Table(_ref) {
|
|
|
4324
4307
|
React.useEffect(function () {
|
|
4325
4308
|
if (!onFetch) return;
|
|
4326
4309
|
onFetch({
|
|
4327
|
-
setData:
|
|
4328
|
-
|
|
4310
|
+
setData: function setData(rows) {
|
|
4311
|
+
return setTableData(Array.isArray(rows) ? rows : []);
|
|
4312
|
+
},
|
|
4329
4313
|
setLoading: setLoading,
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
nextRecords: paginatedData
|
|
4335
|
-
}
|
|
4314
|
+
filters: filters,
|
|
4315
|
+
page: currentPage,
|
|
4316
|
+
limit: limit,
|
|
4317
|
+
sort: sortConfig
|
|
4336
4318
|
});
|
|
4337
|
-
}, [filters, currentPage, limit]);
|
|
4319
|
+
}, [onFetch, filters, currentPage, limit, sortConfig]);
|
|
4320
|
+
React.useEffect(function () {
|
|
4321
|
+
if (!serverSide) setTableData(data);
|
|
4322
|
+
}, [data, serverSide]);
|
|
4338
4323
|
React.useEffect(function () {
|
|
4339
4324
|
if (!onFetch && isValidList(data)) setTableData(data);
|
|
4340
4325
|
}, [data, onFetch]);
|
|
@@ -4352,13 +4337,11 @@ var Table = function Table(_ref) {
|
|
|
4352
4337
|
applyGlobalSearch();
|
|
4353
4338
|
}
|
|
4354
4339
|
};
|
|
4355
|
-
React.useEffect(function () {
|
|
4356
|
-
setLimit(pageSize);
|
|
4357
|
-
}, [pageSize]);
|
|
4358
4340
|
var handleLimitChange = function handleLimitChange(nextLimit) {
|
|
4359
4341
|
var parsed = Number(nextLimit);
|
|
4360
4342
|
if (!Number.isFinite(parsed) || parsed <= 0) return;
|
|
4361
4343
|
setLimit(parsed);
|
|
4344
|
+
setCurrentPage(1);
|
|
4362
4345
|
onLimitChange === null || onLimitChange === void 0 || onLimitChange(parsed);
|
|
4363
4346
|
};
|
|
4364
4347
|
|
|
@@ -4701,7 +4684,7 @@ var Table = function Table(_ref) {
|
|
|
4701
4684
|
}, /*#__PURE__*/React.createElement("input", {
|
|
4702
4685
|
type: "text",
|
|
4703
4686
|
placeholder: "Filter ".concat(column.label),
|
|
4704
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm",
|
|
4687
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm font-normal",
|
|
4705
4688
|
value: filters[column.key] || "",
|
|
4706
4689
|
onChange: function onChange(e) {
|
|
4707
4690
|
return handleFilter(column.key, e.target.value);
|
|
@@ -4901,20 +4884,15 @@ var Table = function Table(_ref) {
|
|
|
4901
4884
|
}
|
|
4902
4885
|
}, "Next")))));
|
|
4903
4886
|
};
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
menuRef = _ref4.menuRef;
|
|
4914
|
-
var _useState29 = React.useState(0),
|
|
4915
|
-
_useState30 = _slicedToArray(_useState29, 2),
|
|
4916
|
-
setTick = _useState30[1];
|
|
4917
|
-
var _useState31 = React.useState({
|
|
4887
|
+
function ActionMenuPortal(_ref2) {
|
|
4888
|
+
var anchorElem = _ref2.anchorElem,
|
|
4889
|
+
anchorRow = _ref2.anchorRow,
|
|
4890
|
+
_ref2$actions = _ref2.actions,
|
|
4891
|
+
actions = _ref2$actions === void 0 ? [] : _ref2$actions;
|
|
4892
|
+
_ref2.onClose;
|
|
4893
|
+
var onAction = _ref2.onAction,
|
|
4894
|
+
menuRef = _ref2.menuRef;
|
|
4895
|
+
var _useState29 = React.useState({
|
|
4918
4896
|
left: 0,
|
|
4919
4897
|
top: 0,
|
|
4920
4898
|
transformOrigin: "top right",
|
|
@@ -4922,11 +4900,15 @@ function ActionMenuPortal(_ref4) {
|
|
|
4922
4900
|
width: 180,
|
|
4923
4901
|
opacity: 0
|
|
4924
4902
|
}),
|
|
4925
|
-
|
|
4926
|
-
style =
|
|
4927
|
-
setStyle =
|
|
4903
|
+
_useState30 = _slicedToArray(_useState29, 2),
|
|
4904
|
+
style = _useState30[0],
|
|
4905
|
+
setStyle = _useState30[1];
|
|
4928
4906
|
var menuWidth = 180;
|
|
4929
4907
|
var maxMenuHeight = 320;
|
|
4908
|
+
var margin = 8;
|
|
4909
|
+
var minMenuHeight = 80;
|
|
4910
|
+
|
|
4911
|
+
// compute position using actual menu height (if available) and layout measurements
|
|
4930
4912
|
var computePosition = function computePosition() {
|
|
4931
4913
|
if (!anchorElem) return;
|
|
4932
4914
|
var rect = anchorElem.getBoundingClientRect();
|
|
@@ -4934,52 +4916,95 @@ function ActionMenuPortal(_ref4) {
|
|
|
4934
4916
|
var scrollX = window.scrollX || window.pageXOffset;
|
|
4935
4917
|
var spaceBelow = window.innerHeight - rect.bottom;
|
|
4936
4918
|
var spaceAbove = rect.top;
|
|
4937
|
-
|
|
4919
|
+
|
|
4920
|
+
// allowed max height based on available space
|
|
4921
|
+
var allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, Math.max(spaceBelow - margin, spaceAbove - margin)));
|
|
4922
|
+
|
|
4923
|
+
// choose placement by comparing actual available spaces
|
|
4938
4924
|
var placement = "bottom";
|
|
4939
|
-
var maxHeight = Math.min(maxMenuHeight, Math.max(80, spaceBelow - 16));
|
|
4940
4925
|
if (spaceBelow < 160 && spaceAbove > spaceBelow) {
|
|
4941
4926
|
placement = "top";
|
|
4942
|
-
|
|
4943
|
-
|
|
4927
|
+
// when placing on top we should cap allowedMaxHeight by spaceAbove
|
|
4928
|
+
allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceAbove - margin));
|
|
4944
4929
|
} else {
|
|
4945
|
-
|
|
4930
|
+
// placing bottom: cap by spaceBelow
|
|
4931
|
+
allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceBelow - margin));
|
|
4946
4932
|
}
|
|
4933
|
+
|
|
4934
|
+
// measure the menu's content height if we can, and compute the actual menu height we'll use.
|
|
4935
|
+
var measuredMenuHeight = allowedMaxHeight;
|
|
4936
|
+
var menuEl = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current;
|
|
4937
|
+
if (menuEl) {
|
|
4938
|
+
// scrollHeight is the content height; offsetHeight may reflect current rendered height.
|
|
4939
|
+
var contentHeight = menuEl.scrollHeight || menuEl.offsetHeight || allowedMaxHeight;
|
|
4940
|
+
// actual height will be min(contentHeight, allowedMaxHeight)
|
|
4941
|
+
measuredMenuHeight = Math.min(contentHeight, allowedMaxHeight);
|
|
4942
|
+
}
|
|
4943
|
+
|
|
4944
|
+
// compute top according to placement and measuredMenuHeight
|
|
4945
|
+
var top;
|
|
4946
|
+
if (placement === "top") {
|
|
4947
|
+
// place menu so its bottom sits just above the anchor (rect.top - margin)
|
|
4948
|
+
top = rect.top + scrollY - measuredMenuHeight - margin;
|
|
4949
|
+
} else {
|
|
4950
|
+
// place menu just below the anchor (rect.bottom + margin)
|
|
4951
|
+
top = rect.bottom + scrollY + margin;
|
|
4952
|
+
}
|
|
4953
|
+
|
|
4954
|
+
// clamp top to viewport (so it never goes off-screen)
|
|
4955
|
+
var minTop = margin + scrollY;
|
|
4956
|
+
var maxTop = window.innerHeight + scrollY - measuredMenuHeight - margin;
|
|
4957
|
+
if (top < minTop) top = minTop;
|
|
4958
|
+
if (top > maxTop) top = maxTop;
|
|
4959
|
+
|
|
4960
|
+
// compute left and clamp horizontally
|
|
4947
4961
|
var left = rect.right + scrollX - menuWidth;
|
|
4948
|
-
if (left <
|
|
4949
|
-
if (left + menuWidth > window.innerWidth -
|
|
4962
|
+
if (left < margin) left = margin;
|
|
4963
|
+
if (left + menuWidth > window.innerWidth - margin) {
|
|
4964
|
+
left = Math.max(margin, window.innerWidth - menuWidth - margin);
|
|
4965
|
+
}
|
|
4950
4966
|
var transformOrigin = placement === "bottom" ? "top right" : "bottom right";
|
|
4967
|
+
|
|
4968
|
+
// set style (opacity 1 to fade-in)
|
|
4951
4969
|
setStyle({
|
|
4952
4970
|
left: left,
|
|
4953
4971
|
top: top,
|
|
4954
4972
|
transformOrigin: transformOrigin,
|
|
4955
|
-
maxHeight:
|
|
4973
|
+
maxHeight: allowedMaxHeight,
|
|
4956
4974
|
width: menuWidth,
|
|
4957
4975
|
opacity: 1
|
|
4958
4976
|
});
|
|
4959
4977
|
};
|
|
4960
|
-
|
|
4978
|
+
|
|
4979
|
+
// useLayoutEffect so the position is measured & applied before paint
|
|
4980
|
+
React.useLayoutEffect(function () {
|
|
4981
|
+
// compute once after mount
|
|
4961
4982
|
computePosition();
|
|
4962
4983
|
var onScrollOrResize = function onScrollOrResize() {
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
return
|
|
4984
|
+
// using requestAnimationFrame to avoid layout thrash on fast scroll/resize
|
|
4985
|
+
window.requestAnimationFrame(function () {
|
|
4986
|
+
return computePosition();
|
|
4966
4987
|
});
|
|
4967
4988
|
};
|
|
4968
4989
|
window.addEventListener("resize", onScrollOrResize);
|
|
4990
|
+
// capture scrolls (true) so position updates even when scrolling ancestor elements
|
|
4969
4991
|
window.addEventListener("scroll", onScrollOrResize, true);
|
|
4970
4992
|
return function () {
|
|
4971
4993
|
window.removeEventListener("resize", onScrollOrResize);
|
|
4972
4994
|
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
4973
4995
|
};
|
|
4974
|
-
|
|
4996
|
+
// Recompute when anchor element changes or actions change (content height may change).
|
|
4997
|
+
}, [anchorElem, actions, menuRef]);
|
|
4975
4998
|
return /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
|
|
4976
4999
|
ref: menuRef,
|
|
4977
5000
|
style: {
|
|
5001
|
+
position: "absolute",
|
|
4978
5002
|
top: style.top,
|
|
4979
5003
|
left: style.left,
|
|
4980
5004
|
width: style.width,
|
|
4981
5005
|
maxHeight: style.maxHeight,
|
|
4982
|
-
transformOrigin: style.transformOrigin
|
|
5006
|
+
transformOrigin: style.transformOrigin,
|
|
5007
|
+
opacity: style.opacity
|
|
4983
5008
|
},
|
|
4984
5009
|
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",
|
|
4985
5010
|
onClick: function onClick(e) {
|
|
@@ -10370,7 +10395,12 @@ var DatePicker = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
10370
10395
|
currentMonth = _useState4[0],
|
|
10371
10396
|
setCurrentMonth = _useState4[1];
|
|
10372
10397
|
var datePickerRef = React.useRef(null);
|
|
10398
|
+
var popupRef = React.useRef(null);
|
|
10373
10399
|
var gridButtonRefs = React.useRef([]);
|
|
10400
|
+
var _useState5 = React.useState({}),
|
|
10401
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
10402
|
+
popupStyle = _useState6[0],
|
|
10403
|
+
setPopupStyle = _useState6[1];
|
|
10374
10404
|
React.useImperativeHandle(forwardedRef, function () {
|
|
10375
10405
|
return datePickerRef.current;
|
|
10376
10406
|
}, []);
|
|
@@ -10383,7 +10413,7 @@ var DatePicker = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
10383
10413
|
// Close on outside click
|
|
10384
10414
|
React.useEffect(function () {
|
|
10385
10415
|
var handleClickOutside = function handleClickOutside(e) {
|
|
10386
|
-
if (datePickerRef.current && !datePickerRef.current.contains(e.target)) {
|
|
10416
|
+
if (datePickerRef.current && !datePickerRef.current.contains(e.target) && popupRef.current && !popupRef.current.contains(e.target)) {
|
|
10387
10417
|
setIsOpen(false);
|
|
10388
10418
|
}
|
|
10389
10419
|
};
|
|
@@ -10499,6 +10529,75 @@ var DatePicker = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
10499
10529
|
if (idx >= 0) focusDayAtIndex(idx);
|
|
10500
10530
|
}, 0);
|
|
10501
10531
|
};
|
|
10532
|
+
|
|
10533
|
+
// compute popup position so it's aware of viewport edges (top/bottom/left/right)
|
|
10534
|
+
var computePopupPosition = function computePopupPosition() {
|
|
10535
|
+
var margin = 8;
|
|
10536
|
+
var trigger = datePickerRef.current;
|
|
10537
|
+
var popup = popupRef.current;
|
|
10538
|
+
if (!trigger || !popup) return;
|
|
10539
|
+
var triggerRect = trigger.getBoundingClientRect();
|
|
10540
|
+
// measure popup by temporarily making it visible if hidden
|
|
10541
|
+
var popupRect = popup.getBoundingClientRect();
|
|
10542
|
+
|
|
10543
|
+
// If the popup is not yet fully measured (width/height 0), try to read offsetWidth/Height
|
|
10544
|
+
if (popupRect.width === 0 || popupRect.height === 0) {
|
|
10545
|
+
popupRect = {
|
|
10546
|
+
width: popup.offsetWidth || 240,
|
|
10547
|
+
height: popup.offsetHeight || 300
|
|
10548
|
+
};
|
|
10549
|
+
}
|
|
10550
|
+
|
|
10551
|
+
// Decide vertical placement
|
|
10552
|
+
var spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
10553
|
+
var spaceAbove = triggerRect.top;
|
|
10554
|
+
var placeBelow = spaceBelow >= popupRect.height + margin;
|
|
10555
|
+
if (!placeBelow && spaceAbove >= popupRect.height + margin) placeBelow = false;
|
|
10556
|
+
// If neither side has full space, pick the side with more space
|
|
10557
|
+
if (!placeBelow && spaceBelow < popupRect.height + margin && spaceAbove < popupRect.height + margin) {
|
|
10558
|
+
placeBelow = spaceBelow >= spaceAbove;
|
|
10559
|
+
}
|
|
10560
|
+
|
|
10561
|
+
// compute top coordinate (fixed positioning)
|
|
10562
|
+
var top;
|
|
10563
|
+
if (placeBelow) {
|
|
10564
|
+
top = Math.min(window.innerHeight - margin - popupRect.height, triggerRect.bottom + margin);
|
|
10565
|
+
} else {
|
|
10566
|
+
top = Math.max(margin, triggerRect.top - popupRect.height - margin);
|
|
10567
|
+
}
|
|
10568
|
+
|
|
10569
|
+
// Decide horizontal placement (try align left to trigger)
|
|
10570
|
+
var left = triggerRect.left;
|
|
10571
|
+
// If overflowing right, shift left
|
|
10572
|
+
if (left + popupRect.width > window.innerWidth - margin) {
|
|
10573
|
+
left = Math.max(margin, window.innerWidth - margin - popupRect.width);
|
|
10574
|
+
}
|
|
10575
|
+
// If overflowing left, clamp
|
|
10576
|
+
if (left < margin) left = margin;
|
|
10577
|
+
var transformOrigin = placeBelow ? "top left" : "bottom left";
|
|
10578
|
+
setPopupStyle({
|
|
10579
|
+
position: "fixed",
|
|
10580
|
+
top: "".concat(Math.round(top), "px"),
|
|
10581
|
+
left: "".concat(Math.round(left), "px"),
|
|
10582
|
+
zIndex: 9999,
|
|
10583
|
+
transformOrigin: transformOrigin
|
|
10584
|
+
});
|
|
10585
|
+
};
|
|
10586
|
+
|
|
10587
|
+
// recompute on open, on resize/scroll, and when popup content changes (currentMonth)
|
|
10588
|
+
React.useLayoutEffect(function () {
|
|
10589
|
+
if (!isOpen) return;
|
|
10590
|
+
computePopupPosition();
|
|
10591
|
+
var handleResize = function handleResize() {
|
|
10592
|
+
return computePopupPosition();
|
|
10593
|
+
};
|
|
10594
|
+
window.addEventListener("resize", handleResize);
|
|
10595
|
+
window.addEventListener("scroll", handleResize, true); // capture scrolling in ancestors
|
|
10596
|
+
return function () {
|
|
10597
|
+
window.removeEventListener("resize", handleResize);
|
|
10598
|
+
window.removeEventListener("scroll", handleResize, true);
|
|
10599
|
+
};
|
|
10600
|
+
}, [isOpen, currentMonth]);
|
|
10502
10601
|
var header = /*#__PURE__*/React.createElement("div", {
|
|
10503
10602
|
className: "mb-4 flex items-center justify-between"
|
|
10504
10603
|
}, /*#__PURE__*/React.createElement("button", {
|
|
@@ -10523,9 +10622,11 @@ var DatePicker = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
10523
10622
|
className: "h-4 w-4"
|
|
10524
10623
|
})));
|
|
10525
10624
|
var calendarPopup = /*#__PURE__*/React.createElement("div", {
|
|
10526
|
-
|
|
10625
|
+
ref: popupRef,
|
|
10626
|
+
className: "w-80 rounded-md border border-gray-300 bg-white p-4 shadow-lg",
|
|
10527
10627
|
role: "dialog",
|
|
10528
|
-
"aria-modal": "false"
|
|
10628
|
+
"aria-modal": "false",
|
|
10629
|
+
style: popupStyle
|
|
10529
10630
|
}, header, /*#__PURE__*/React.createElement("div", {
|
|
10530
10631
|
className: "mb-2 grid grid-cols-7 gap-1"
|
|
10531
10632
|
}, Array.from({
|
|
@@ -11874,11 +11975,10 @@ function Slider(_ref6) {
|
|
|
11874
11975
|
var _excluded$g = ["value", "onChange", "placeholder", "label", "error", "disabled", "required", "minDate", "maxDate", "className", "weekStartsOn", "portal", "displayFormat", "locale", "showClear", "closeOnSelect"];
|
|
11875
11976
|
|
|
11876
11977
|
/*
|
|
11877
|
-
Single-calendar DateRangePicker with hover-preview
|
|
11878
|
-
- Enforces mandatory range selection
|
|
11879
|
-
|
|
11880
|
-
- Popup
|
|
11881
|
-
a start date is selected. Use Clear to cancel the in-progress selection.
|
|
11978
|
+
Single-calendar DateRangePicker with hover-preview and space-aware popup positioning
|
|
11979
|
+
- Enforces mandatory range selection until both start and end are chosen.
|
|
11980
|
+
- Popup flips above/below and clamps horizontally to avoid clipping.
|
|
11981
|
+
- Popup won't close while only a start date is selected (Clear cancels in-progress selection).
|
|
11882
11982
|
*/
|
|
11883
11983
|
|
|
11884
11984
|
var normalizeDate = function normalizeDate(d) {
|
|
@@ -11952,11 +12052,16 @@ var DateRangePicker = function DateRangePicker(_ref) {
|
|
|
11952
12052
|
if (start) setCurrentMonth(start);
|
|
11953
12053
|
}, [start, end]);
|
|
11954
12054
|
var datePickerRef = React.useRef(null);
|
|
12055
|
+
var popupRef = React.useRef(null);
|
|
12056
|
+
var _useState1 = React.useState({}),
|
|
12057
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
12058
|
+
popupStyle = _useState10[0],
|
|
12059
|
+
setPopupStyle = _useState10[1];
|
|
11955
12060
|
|
|
11956
12061
|
// Outside click: only close if there is NOT an in-progress single-date selection
|
|
11957
12062
|
React.useEffect(function () {
|
|
11958
12063
|
var handleClickOutside = function handleClickOutside(e) {
|
|
11959
|
-
if (datePickerRef.current && !datePickerRef.current.contains(e.target)) {
|
|
12064
|
+
if (datePickerRef.current && !datePickerRef.current.contains(e.target) && (!popupRef.current || !popupRef.current.contains(e.target))) {
|
|
11960
12065
|
// If user has selected a start but no end, prevent closing to force range selection
|
|
11961
12066
|
if (localStart && !localEnd) {
|
|
11962
12067
|
return;
|
|
@@ -12112,10 +12217,82 @@ var DateRangePicker = function DateRangePicker(_ref) {
|
|
|
12112
12217
|
}, /*#__PURE__*/React.createElement(ChevronRight, {
|
|
12113
12218
|
className: "h-4 w-4"
|
|
12114
12219
|
})));
|
|
12220
|
+
|
|
12221
|
+
// compute popup position so it's aware of viewport edges (top/bottom/left/right)
|
|
12222
|
+
var computePopupPosition = function computePopupPosition() {
|
|
12223
|
+
var margin = 8;
|
|
12224
|
+
var trigger = datePickerRef.current;
|
|
12225
|
+
var popup = popupRef.current;
|
|
12226
|
+
if (!trigger || !popup) return;
|
|
12227
|
+
var triggerRect = trigger.getBoundingClientRect();
|
|
12228
|
+
// measure popup by temporarily making it visible if hidden
|
|
12229
|
+
var popupRect = popup.getBoundingClientRect();
|
|
12230
|
+
|
|
12231
|
+
// If the popup is not yet fully measured (width/height 0), try to read offsetWidth/Height
|
|
12232
|
+
if (popupRect.width === 0 || popupRect.height === 0) {
|
|
12233
|
+
popupRect = {
|
|
12234
|
+
width: popup.offsetWidth || 320,
|
|
12235
|
+
height: popup.offsetHeight || 300
|
|
12236
|
+
};
|
|
12237
|
+
}
|
|
12238
|
+
|
|
12239
|
+
// Decide vertical placement
|
|
12240
|
+
var spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
12241
|
+
var spaceAbove = triggerRect.top;
|
|
12242
|
+
var placeBelow = spaceBelow >= popupRect.height + margin;
|
|
12243
|
+
if (!placeBelow && spaceAbove >= popupRect.height + margin) placeBelow = false;
|
|
12244
|
+
// If neither side has full space, pick the side with more space
|
|
12245
|
+
if (!placeBelow && spaceBelow < popupRect.height + margin && spaceAbove < popupRect.height + margin) {
|
|
12246
|
+
placeBelow = spaceBelow >= spaceAbove;
|
|
12247
|
+
}
|
|
12248
|
+
|
|
12249
|
+
// compute top coordinate (fixed positioning)
|
|
12250
|
+
var top;
|
|
12251
|
+
if (placeBelow) {
|
|
12252
|
+
top = Math.min(window.innerHeight - margin - popupRect.height, triggerRect.bottom + margin);
|
|
12253
|
+
} else {
|
|
12254
|
+
top = Math.max(margin, triggerRect.top - popupRect.height - margin);
|
|
12255
|
+
}
|
|
12256
|
+
|
|
12257
|
+
// Decide horizontal placement (try align left to trigger)
|
|
12258
|
+
var left = triggerRect.left;
|
|
12259
|
+
// If overflowing right, shift left
|
|
12260
|
+
if (left + popupRect.width > window.innerWidth - margin) {
|
|
12261
|
+
left = Math.max(margin, window.innerWidth - margin - popupRect.width);
|
|
12262
|
+
}
|
|
12263
|
+
// If overflowing left, clamp
|
|
12264
|
+
if (left < margin) left = margin;
|
|
12265
|
+
var transformOrigin = placeBelow ? "top left" : "bottom left";
|
|
12266
|
+
setPopupStyle({
|
|
12267
|
+
position: "fixed",
|
|
12268
|
+
top: "".concat(Math.round(top), "px"),
|
|
12269
|
+
left: "".concat(Math.round(left), "px"),
|
|
12270
|
+
zIndex: 9999,
|
|
12271
|
+
transformOrigin: transformOrigin
|
|
12272
|
+
});
|
|
12273
|
+
};
|
|
12274
|
+
|
|
12275
|
+
// recompute on open, on resize/scroll, and when popup content changes (currentMonth)
|
|
12276
|
+
React.useLayoutEffect(function () {
|
|
12277
|
+
if (!isOpen) return;
|
|
12278
|
+
// compute on next frame to ensure popup ref exists in DOM (especially with portal)
|
|
12279
|
+
computePopupPosition();
|
|
12280
|
+
var handleResize = function handleResize() {
|
|
12281
|
+
return computePopupPosition();
|
|
12282
|
+
};
|
|
12283
|
+
window.addEventListener("resize", handleResize);
|
|
12284
|
+
window.addEventListener("scroll", handleResize, true); // capture scrolling in ancestors
|
|
12285
|
+
return function () {
|
|
12286
|
+
window.removeEventListener("resize", handleResize);
|
|
12287
|
+
window.removeEventListener("scroll", handleResize, true);
|
|
12288
|
+
};
|
|
12289
|
+
}, [isOpen, currentMonth]);
|
|
12115
12290
|
var calendarPopup = /*#__PURE__*/React.createElement("div", {
|
|
12116
|
-
|
|
12291
|
+
ref: popupRef,
|
|
12292
|
+
className: "w-80 rounded-md border border-gray-300 bg-white p-4 shadow-lg",
|
|
12117
12293
|
role: "dialog",
|
|
12118
|
-
"aria-modal": "false"
|
|
12294
|
+
"aria-modal": "false",
|
|
12295
|
+
style: popupStyle
|
|
12119
12296
|
}, header, /*#__PURE__*/React.createElement("div", {
|
|
12120
12297
|
className: "mb-2 grid grid-cols-7 gap-1"
|
|
12121
12298
|
}, Array.from({
|