@expcat/tigercat-react 0.4.0 → 0.4.3

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.
Files changed (34) hide show
  1. package/dist/{chunk-PWZB45Z7.js → chunk-JQK354YN.js} +11 -9
  2. package/dist/{chunk-3577FW3I.mjs → chunk-KBTFBEPE.mjs} +95 -14
  3. package/dist/{chunk-ZGQOYCQT.mjs → chunk-LLHUBM6E.mjs} +1 -1
  4. package/dist/{chunk-IRH2ZVD3.js → chunk-LXX2ZDJN.js} +2 -2
  5. package/dist/chunk-PEGJ2KHC.js +273 -0
  6. package/dist/chunk-RCNTRSUA.mjs +271 -0
  7. package/dist/chunk-SHT4TU3T.mjs +26 -0
  8. package/dist/{chunk-OUAZM7NY.mjs → chunk-SMC2RV3V.mjs} +12 -10
  9. package/dist/{chunk-OESNOOOT.js → chunk-YWTZALG5.js} +8 -4
  10. package/dist/{chunk-ZTVATZB6.js → chunk-ZBVFM3GJ.js} +131 -46
  11. package/dist/components/ActivityFeed.js +4 -4
  12. package/dist/components/ActivityFeed.mjs +2 -2
  13. package/dist/components/DataTableWithToolbar.js +4 -4
  14. package/dist/components/DataTableWithToolbar.mjs +2 -2
  15. package/dist/components/InputNumber.d.mts +24 -0
  16. package/dist/components/InputNumber.d.ts +24 -0
  17. package/dist/components/InputNumber.js +10 -0
  18. package/dist/components/InputNumber.mjs +1 -0
  19. package/dist/components/Sidebar.js +2 -2
  20. package/dist/components/Sidebar.mjs +1 -1
  21. package/dist/components/SubMenu.js +2 -2
  22. package/dist/components/SubMenu.mjs +1 -1
  23. package/dist/components/Table.d.mts +5 -1
  24. package/dist/components/Table.d.ts +5 -1
  25. package/dist/components/Table.js +2 -2
  26. package/dist/components/Table.mjs +1 -1
  27. package/dist/index.d.mts +1 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +45 -40
  30. package/dist/index.mjs +12 -11
  31. package/package.json +2 -2
  32. package/dist/chunk-RITTIFCJ.mjs +0 -22
  33. package/dist/{chunk-IOM7DWWQ.js → chunk-J3HKED4B.js} +1 -1
  34. package/dist/{chunk-FTY2W4L2.mjs → chunk-MTL2QUM3.mjs} +1 -1
@@ -39,9 +39,9 @@ var SubMenu = ({
39
39
  const [isHovered, setIsHovered] = React.useState(false);
40
40
  const [isOpenByKeyboard, setIsOpenByKeyboard] = React.useState(false);
41
41
  const effectiveCollapsed = collapsedOverride ?? (menuContext ? menuContext.collapsed : false);
42
- const isPopup = !!menuContext && menuContext.mode === "vertical" && effectiveCollapsed;
42
+ const isPopup = !!menuContext && (menuContext.mode === "horizontal" || menuContext.mode === "vertical" && effectiveCollapsed);
43
43
  const isOpen = !!menuContext && tigercatCore.isKeyOpen(itemKey, menuContext.openKeys);
44
- const isExpanded = menuContext?.mode === "horizontal" || isPopup ? isHovered || isOpenByKeyboard : isOpen;
44
+ const isExpanded = isPopup ? isHovered || isOpenByKeyboard : isOpen;
45
45
  const isInlineOrVertical = menuContext?.mode !== "horizontal" && !isPopup;
46
46
  const [hasRenderedInline, setHasRenderedInline] = React.useState(
47
47
  () => isInlineOrVertical ? isExpanded : false
@@ -56,11 +56,13 @@ var SubMenu = ({
56
56
  }, [menuContext, disabled, className]);
57
57
  const contentClasses = React.useMemo(() => {
58
58
  if (!menuContext) return "";
59
- if (menuContext.mode === "horizontal") return tigercatCore.submenuContentHorizontalClasses;
59
+ if (menuContext.mode === "horizontal") {
60
+ return level === 0 ? tigercatCore.submenuContentHorizontalClasses : tigercatCore.submenuContentHorizontalNestedClasses;
61
+ }
60
62
  if (isPopup) return tigercatCore.submenuContentPopupClasses;
61
63
  if (menuContext.mode === "inline") return tigercatCore.submenuContentInlineClasses;
62
64
  return tigercatCore.submenuContentVerticalClasses;
63
- }, [menuContext, isPopup]);
65
+ }, [menuContext, isPopup, level]);
64
66
  const handleTitleClick = React.useCallback(() => {
65
67
  if (!menuContext || disabled) return;
66
68
  if (menuContext.mode === "horizontal") return;
@@ -185,19 +187,19 @@ var SubMenu = ({
185
187
  return React__default.default.cloneElement(
186
188
  child,
187
189
  {
188
- level: nextLevel,
189
- collapsed: isPopup ? false : void 0
190
+ level: nextLevel
190
191
  }
191
192
  );
192
193
  }
193
194
  return child;
194
195
  });
195
- if (menuContext.mode === "horizontal" || isPopup) {
196
+ const popupZIndex = isPopup ? tigercatCore.getSubmenuPopupZIndex(level) : {};
197
+ if (isPopup) {
196
198
  return /* @__PURE__ */ jsxRuntime.jsx(
197
199
  "ul",
198
200
  {
199
201
  className: contentClasses,
200
- style: { display: isExpanded ? "block" : "none" },
202
+ style: { display: isExpanded ? "block" : "none", ...popupZIndex },
201
203
  role: "menu",
202
204
  "aria-hidden": isExpanded ? void 0 : "true",
203
205
  children: enhancedChildren
@@ -222,7 +224,7 @@ var SubMenu = ({
222
224
  return /* @__PURE__ */ jsxRuntime.jsxs(
223
225
  "li",
224
226
  {
225
- className: menuContext.mode === "horizontal" || isPopup ? "relative" : "",
227
+ className: isPopup ? "relative" : "",
226
228
  onMouseEnter: handleMouseEnter,
227
229
  onMouseLeave: handleMouseLeave,
228
230
  role: "none",
@@ -1,5 +1,5 @@
1
- import { useState, useEffect, useMemo, useCallback } from 'react';
2
- import { getSpinnerSVG, getFixedColumnOffsets, filterData, sortData, paginateData, getRowKey, calculatePagination, getTableHeaderClasses, getCheckboxCellClasses, classNames, getTableHeaderCellClasses, tableEmptyStateClasses, getTableCellClasses, getTableRowClasses, getSimplePaginationContainerClasses, getSimplePaginationTotalClasses, getSimplePaginationControlsClasses, getSimplePaginationSelectClasses, getSimplePaginationButtonsWrapperClasses, getSimplePaginationButtonClasses, getSimplePaginationPageIndicatorClasses, getTableWrapperClasses, tableBaseClasses, tableLoadingOverlayClasses, icon24ViewBox, lockClosedIcon24PathD, lockOpenIcon24PathD, icon16ViewBox, getSortIconClasses, sortAscIcon16PathD, sortDescIcon16PathD, sortBothIcon16PathD, getLoadingOverlaySpinnerClasses } from '@expcat/tigercat-core';
1
+ import React, { useState, useEffect, useMemo, useCallback } from 'react';
2
+ import { getSpinnerSVG, getFixedColumnOffsets, filterData, sortData, paginateData, getRowKey, calculatePagination, getExpandIconCellClasses, getTableHeaderClasses, getCheckboxCellClasses, classNames, getTableHeaderCellClasses, tableEmptyStateClasses, getTableCellClasses, getTableRowClasses, getExpandedRowClasses, getExpandedRowContentClasses, getSimplePaginationContainerClasses, getSimplePaginationTotalClasses, getSimplePaginationControlsClasses, getSimplePaginationSelectClasses, getSimplePaginationButtonsWrapperClasses, getSimplePaginationButtonClasses, getSimplePaginationPageIndicatorClasses, getTableWrapperClasses, tableBaseClasses, tableLoadingOverlayClasses, icon24ViewBox, lockClosedIcon24PathD, lockOpenIcon24PathD, icon16ViewBox, getSortIconClasses, sortAscIcon16PathD, sortDescIcon16PathD, sortBothIcon16PathD, getExpandIconClasses, expandChevronIcon16PathD, getLoadingOverlaySpinnerClasses } from '@expcat/tigercat-core';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
4
 
5
5
  // src/components/Table.tsx
@@ -22,6 +22,20 @@ var SortIcon = ({ direction }) => {
22
22
  var LockIcon = ({ locked }) => {
23
23
  return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: icon24ViewBox, fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: locked ? lockClosedIcon24PathD : lockOpenIcon24PathD }) });
24
24
  };
25
+ var ExpandIcon = ({ expanded }) => {
26
+ return /* @__PURE__ */ jsx(
27
+ "svg",
28
+ {
29
+ className: getExpandIconClasses(expanded),
30
+ width: "16",
31
+ height: "16",
32
+ viewBox: icon16ViewBox,
33
+ fill: "currentColor",
34
+ "aria-hidden": "true",
35
+ children: /* @__PURE__ */ jsx("path", { d: expandChevronIcon16PathD })
36
+ }
37
+ );
38
+ };
25
39
  var LoadingSpinner = () => /* @__PURE__ */ jsx(
26
40
  "svg",
27
41
  {
@@ -59,6 +73,7 @@ function Table({
59
73
  showTotal: true
60
74
  },
61
75
  rowSelection,
76
+ expandable,
62
77
  rowKey = "id",
63
78
  rowClassName,
64
79
  stickyHeader = false,
@@ -70,6 +85,7 @@ function Table({
70
85
  onSortChange,
71
86
  onFilterChange,
72
87
  onPageChange,
88
+ onExpandChange,
73
89
  className,
74
90
  ...props
75
91
  }) {
@@ -79,6 +95,7 @@ function Table({
79
95
  const isCurrentPageControlled = paginationConfig?.current !== void 0;
80
96
  const isPageSizeControlled = paginationConfig?.pageSize !== void 0;
81
97
  const isSelectionControlled = rowSelection?.selectedRowKeys !== void 0 && Array.isArray(rowSelection.selectedRowKeys);
98
+ const isExpandControlled = expandable?.expandedRowKeys !== void 0 && Array.isArray(expandable.expandedRowKeys);
82
99
  const [uncontrolledSortState, setUncontrolledSortState] = useState(
83
100
  defaultSort ?? { key: null, direction: null }
84
101
  );
@@ -92,11 +109,13 @@ function Table({
92
109
  () => paginationConfig?.defaultPageSize ?? paginationConfig?.pageSize ?? 10
93
110
  );
94
111
  const [uncontrolledSelectedRowKeys, setUncontrolledSelectedRowKeys] = useState(rowSelection?.defaultSelectedRowKeys ?? rowSelection?.selectedRowKeys ?? []);
112
+ const [uncontrolledExpandedRowKeys, setUncontrolledExpandedRowKeys] = useState(expandable?.defaultExpandedRowKeys ?? expandable?.expandedRowKeys ?? []);
95
113
  const sortState = isSortControlled ? sort : uncontrolledSortState;
96
114
  const filterState = isFiltersControlled ? filters : uncontrolledFilterState;
97
115
  const currentPage = isCurrentPageControlled ? paginationConfig.current : uncontrolledCurrentPage;
98
116
  const currentPageSize = isPageSizeControlled ? paginationConfig.pageSize : uncontrolledCurrentPageSize;
99
117
  const selectedRowKeys = isSelectionControlled ? rowSelection.selectedRowKeys : uncontrolledSelectedRowKeys;
118
+ const expandedRowKeys = isExpandControlled ? expandable.expandedRowKeys : uncontrolledExpandedRowKeys;
100
119
  useEffect(() => {
101
120
  if (isSortControlled && sort) {
102
121
  setUncontrolledSortState(sort);
@@ -122,6 +141,11 @@ function Table({
122
141
  setUncontrolledSelectedRowKeys(rowSelection?.selectedRowKeys ?? []);
123
142
  }
124
143
  }, [isSelectionControlled, rowSelection?.selectedRowKeys]);
144
+ useEffect(() => {
145
+ if (isExpandControlled) {
146
+ setUncontrolledExpandedRowKeys(expandable?.expandedRowKeys ?? []);
147
+ }
148
+ }, [isExpandControlled, expandable?.expandedRowKeys]);
125
149
  const [fixedOverrides, setFixedOverrides] = useState({});
126
150
  const displayColumns = useMemo(() => {
127
151
  return columns.map((column) => {
@@ -132,6 +156,12 @@ function Table({
132
156
  };
133
157
  });
134
158
  }, [columns, fixedOverrides]);
159
+ const totalColumnCount = useMemo(() => {
160
+ let count = displayColumns.length;
161
+ if (rowSelection && rowSelection.showCheckbox !== false) count++;
162
+ if (expandable) count++;
163
+ return count;
164
+ }, [displayColumns.length, rowSelection, expandable]);
135
165
  const columnByKey = useMemo(() => {
136
166
  const map = {};
137
167
  for (const column of displayColumns) {
@@ -179,6 +209,10 @@ function Table({
179
209
  () => new Set(selectedRowKeys),
180
210
  [selectedRowKeys]
181
211
  );
212
+ const expandedRowKeySet = useMemo(
213
+ () => new Set(expandedRowKeys),
214
+ [expandedRowKeys]
215
+ );
182
216
  const paginationInfo = useMemo(() => {
183
217
  if (pagination === false) {
184
218
  return null;
@@ -290,11 +324,29 @@ function Table({
290
324
  },
291
325
  [sortState, filterState, onPageChange, onChange]
292
326
  );
327
+ const handleToggleExpand = useCallback(
328
+ (key, record) => {
329
+ const isExpanded = expandedRowKeySet.has(key);
330
+ const newKeys = isExpanded ? expandedRowKeys.filter((k) => k !== key) : [...expandedRowKeys, key];
331
+ if (!isExpandControlled) {
332
+ setUncontrolledExpandedRowKeys(newKeys);
333
+ }
334
+ onExpandChange?.(newKeys, record, !isExpanded);
335
+ },
336
+ [expandedRowKeySet, expandedRowKeys, isExpandControlled, onExpandChange]
337
+ );
293
338
  const handleRowClick = useCallback(
294
339
  (record, index) => {
295
340
  onRowClick?.(record, index);
341
+ if (expandable?.expandRowByClick) {
342
+ const key = getRowKey(record, rowKey, index);
343
+ const isExpandableRow = expandable?.rowExpandable ? expandable.rowExpandable(record) : true;
344
+ if (isExpandableRow) {
345
+ handleToggleExpand(key, record);
346
+ }
347
+ }
296
348
  },
297
- [onRowClick]
349
+ [onRowClick, expandable, rowKey, handleToggleExpand]
298
350
  );
299
351
  const handleSelectRow = useCallback(
300
352
  (key, checked) => {
@@ -342,7 +394,10 @@ function Table({
342
394
  return selectedRowKeys.length > 0 && !allSelected;
343
395
  }, [selectedRowKeys.length, allSelected]);
344
396
  const renderTableHeader = useCallback(() => {
397
+ const expandHeaderTh = expandable ? /* @__PURE__ */ jsx("th", { className: getExpandIconCellClasses(size), "aria-label": "Expand" }) : null;
398
+ const expandAtStart = expandable?.expandIconPosition !== "end";
345
399
  return /* @__PURE__ */ jsx("thead", { className: getTableHeaderClasses(stickyHeader), children: /* @__PURE__ */ jsxs("tr", { children: [
400
+ expandAtStart && expandHeaderTh,
346
401
  rowSelection && rowSelection.showCheckbox !== false && rowSelection.type !== "radio" && /* @__PURE__ */ jsx("th", { className: getCheckboxCellClasses(size), children: /* @__PURE__ */ jsx(
347
402
  "input",
348
403
  {
@@ -435,7 +490,8 @@ function Table({
435
490
  },
436
491
  column.key
437
492
  );
438
- })
493
+ }),
494
+ !expandAtStart && expandHeaderTh
439
495
  ] }) });
440
496
  }, [
441
497
  displayColumns,
@@ -443,6 +499,7 @@ function Table({
443
499
  stickyHeader,
444
500
  sortState,
445
501
  rowSelection,
502
+ expandable,
446
503
  allSelected,
447
504
  someSelected,
448
505
  handleSort,
@@ -457,20 +514,30 @@ function Table({
457
514
  return null;
458
515
  }
459
516
  if (paginatedData.length === 0) {
460
- return /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
461
- "td",
462
- {
463
- colSpan: displayColumns.length + (rowSelection ? 1 : 0),
464
- className: tableEmptyStateClasses,
465
- children: /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", children: emptyText })
466
- }
467
- ) }) });
517
+ return /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: totalColumnCount, className: tableEmptyStateClasses, children: /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", children: emptyText }) }) }) });
468
518
  }
469
519
  return /* @__PURE__ */ jsx("tbody", { children: paginatedData.map((record, index) => {
470
520
  const key = pageRowKeys[index];
471
521
  const isSelected = selectedRowKeySet.has(key);
522
+ const isExpanded = expandedRowKeySet.has(key);
523
+ const isRowExpandable = expandable ? expandable.rowExpandable ? expandable.rowExpandable(record) : true : false;
472
524
  const rowClass = typeof rowClassName === "function" ? rowClassName(record, index) : rowClassName;
473
- return /* @__PURE__ */ jsxs(
525
+ const expandToggleCell = expandable ? /* @__PURE__ */ jsx("td", { className: getExpandIconCellClasses(size), children: isRowExpandable && /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ className: "inline-flex items-center justify-center",
530
+ "aria-label": isExpanded ? "Collapse row" : "Expand row",
531
+ "aria-expanded": isExpanded,
532
+ onClick: (e) => {
533
+ e.stopPropagation();
534
+ handleToggleExpand(key, record);
535
+ },
536
+ children: /* @__PURE__ */ jsx(ExpandIcon, { expanded: isExpanded })
537
+ }
538
+ ) }) : null;
539
+ const expandAtStart = expandable?.expandIconPosition !== "end";
540
+ const rowNode = /* @__PURE__ */ jsxs(
474
541
  "tr",
475
542
  {
476
543
  className: classNames(
@@ -479,6 +546,7 @@ function Table({
479
546
  ),
480
547
  onClick: () => handleRowClick(record, index),
481
548
  children: [
549
+ expandAtStart && expandToggleCell,
482
550
  rowSelection && rowSelection.showCheckbox !== false && /* @__PURE__ */ jsx("td", { className: getCheckboxCellClasses(size), children: /* @__PURE__ */ jsx(
483
551
  "input",
484
552
  {
@@ -525,26 +593,39 @@ function Table({
525
593
  },
526
594
  column.key
527
595
  );
528
- })
596
+ }),
597
+ !expandAtStart && expandToggleCell
529
598
  ]
530
599
  },
531
600
  key
532
601
  );
602
+ if (expandable && isExpanded && isRowExpandable) {
603
+ const expandedContent = expandable.expandedRowRender ? expandable.expandedRowRender(record, index) : null;
604
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
605
+ rowNode,
606
+ /* @__PURE__ */ jsx("tr", { className: getExpandedRowClasses(), children: /* @__PURE__ */ jsx("td", { colSpan: totalColumnCount, className: getExpandedRowContentClasses(size), children: expandedContent }) }, `${key}-expanded`)
607
+ ] }, key);
608
+ }
609
+ return rowNode;
533
610
  }) });
534
611
  }, [
535
612
  loading,
536
613
  paginatedData,
537
614
  displayColumns,
538
615
  rowSelection,
616
+ expandable,
539
617
  emptyText,
540
618
  pageRowKeys,
541
619
  selectedRowKeySet,
620
+ expandedRowKeySet,
621
+ totalColumnCount,
542
622
  rowClassName,
543
623
  hoverable,
544
624
  striped,
545
625
  size,
546
626
  handleRowClick,
547
627
  handleSelectRow,
628
+ handleToggleExpand,
548
629
  fixedColumnsInfo
549
630
  ]);
550
631
  const renderPagination = useCallback(() => {
@@ -1,4 +1,4 @@
1
- import { Table } from './chunk-3577FW3I.mjs';
1
+ import { Table } from './chunk-KBTFBEPE.mjs';
2
2
  import { Select } from './chunk-MDZDPGRK.mjs';
3
3
  import { Pagination } from './chunk-NZLOLMT2.mjs';
4
4
  import { Input } from './chunk-RPTLVIBF.mjs';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkZTVATZB6_js = require('./chunk-ZTVATZB6.js');
3
+ var chunkZBVFM3GJ_js = require('./chunk-ZBVFM3GJ.js');
4
4
  var chunkTDRINUMH_js = require('./chunk-TDRINUMH.js');
5
5
  var chunk3GW3UAKB_js = require('./chunk-3GW3UAKB.js');
6
6
  var chunkOYCMGKQ7_js = require('./chunk-OYCMGKQ7.js');
@@ -187,7 +187,7 @@ var DataTableWithToolbar = ({
187
187
  const showPagination = pagination && typeof pagination === "object";
188
188
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClasses, "data-tiger-data-table-with-toolbar": true, children: [
189
189
  renderToolbar(),
190
- /* @__PURE__ */ jsxRuntime.jsx(chunkZTVATZB6_js.Table, { ...tableProps, pagination: false, className: tableClassName }),
190
+ /* @__PURE__ */ jsxRuntime.jsx(chunkZBVFM3GJ_js.Table, { ...tableProps, pagination: false, className: tableClassName }),
191
191
  showPagination ? /* @__PURE__ */ jsxRuntime.jsx(chunk3GW3UAKB_js.Pagination, { ...pagination, onChange: onPageChange, onPageSizeChange }) : null
192
192
  ] });
193
193
  };
@@ -0,0 +1,273 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var tigercatCore = require('@expcat/tigercat-core');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/components/InputNumber.tsx
8
+ var InputNumber = ({
9
+ value: controlledValue,
10
+ defaultValue,
11
+ size = "md",
12
+ status = "default",
13
+ min = -Infinity,
14
+ max = Infinity,
15
+ step = 1,
16
+ precision,
17
+ disabled = false,
18
+ readonly = false,
19
+ placeholder,
20
+ name,
21
+ id,
22
+ keyboard = true,
23
+ controls = true,
24
+ controlsPosition = "right",
25
+ formatter,
26
+ parser,
27
+ autoFocus = false,
28
+ onChange,
29
+ onFocus,
30
+ onBlur,
31
+ className
32
+ }) => {
33
+ const isControlled = controlledValue !== void 0;
34
+ const inputRef = react.useRef(null);
35
+ const [focused, setFocused] = react.useState(false);
36
+ const [internalValue, setInternalValue] = react.useState(
37
+ defaultValue ?? controlledValue ?? null
38
+ );
39
+ const [displayValue, setDisplayValue] = react.useState("");
40
+ const currentValue = isControlled ? controlledValue ?? null : internalValue;
41
+ const toDisplayValue = react.useCallback(
42
+ (val) => {
43
+ if (val === null || val === void 0) return "";
44
+ if (formatter) return formatter(val);
45
+ if (precision !== void 0) return val.toFixed(precision);
46
+ return String(val);
47
+ },
48
+ [formatter, precision]
49
+ );
50
+ const parseValue = react.useCallback(
51
+ (str) => {
52
+ if (str === "" || str === "-") return null;
53
+ if (parser) return parser(str);
54
+ const num = Number(str);
55
+ return Number.isNaN(num) ? null : num;
56
+ },
57
+ [parser]
58
+ );
59
+ react.useEffect(() => {
60
+ if (!focused) {
61
+ setDisplayValue(toDisplayValue(currentValue));
62
+ }
63
+ }, [currentValue, focused, toDisplayValue]);
64
+ react.useEffect(() => {
65
+ if (autoFocus && inputRef.current) {
66
+ inputRef.current.focus();
67
+ }
68
+ }, [autoFocus]);
69
+ const commitValue = react.useCallback(
70
+ (val) => {
71
+ let finalVal = val;
72
+ if (finalVal !== null) {
73
+ finalVal = tigercatCore.clampValue(finalVal, min, max);
74
+ if (precision !== void 0) {
75
+ finalVal = tigercatCore.formatPrecision(finalVal, precision);
76
+ }
77
+ }
78
+ if (!isControlled) {
79
+ setInternalValue(finalVal);
80
+ }
81
+ onChange?.(finalVal);
82
+ setDisplayValue(toDisplayValue(finalVal));
83
+ },
84
+ [min, max, precision, isControlled, onChange, toDisplayValue]
85
+ );
86
+ const handleStep = react.useCallback(
87
+ (direction) => {
88
+ if (disabled || readonly) return;
89
+ const next = tigercatCore.stepValue(currentValue, step, direction, min, max, precision);
90
+ commitValue(next);
91
+ },
92
+ [currentValue, step, min, max, precision, disabled, readonly, commitValue]
93
+ );
94
+ const handleInput = react.useCallback((e) => {
95
+ setDisplayValue(e.target.value);
96
+ }, []);
97
+ const handleBlur = react.useCallback(
98
+ (e) => {
99
+ setFocused(false);
100
+ const parsed = parseValue(displayValue);
101
+ commitValue(parsed);
102
+ onBlur?.(e);
103
+ },
104
+ [displayValue, parseValue, commitValue, onBlur]
105
+ );
106
+ const handleFocus = react.useCallback(
107
+ (e) => {
108
+ setFocused(true);
109
+ if (formatter && currentValue !== null) {
110
+ setDisplayValue(String(currentValue));
111
+ }
112
+ onFocus?.(e);
113
+ },
114
+ [formatter, currentValue, onFocus]
115
+ );
116
+ const handleKeyDown = react.useCallback(
117
+ (e) => {
118
+ if (!keyboard || disabled || readonly) return;
119
+ if (e.key === "ArrowUp") {
120
+ e.preventDefault();
121
+ handleStep("up");
122
+ } else if (e.key === "ArrowDown") {
123
+ e.preventDefault();
124
+ handleStep("down");
125
+ } else if (e.key === "Enter") {
126
+ const parsed = parseValue(displayValue);
127
+ commitValue(parsed);
128
+ }
129
+ },
130
+ [keyboard, disabled, readonly, handleStep, parseValue, displayValue, commitValue]
131
+ );
132
+ const atMin = tigercatCore.isAtMin(currentValue, min);
133
+ const atMax = tigercatCore.isAtMax(currentValue, max);
134
+ const wrapperClasses = react.useMemo(
135
+ () => tigercatCore.classNames(
136
+ tigercatCore.getInputNumberWrapperClasses(disabled),
137
+ tigercatCore.getInputNumberStatusClasses(status),
138
+ tigercatCore.getInputNumberSizeClasses(size),
139
+ focused && `ring-2 ${tigercatCore.getInputNumberFocusRingColor(status)}`,
140
+ className
141
+ ),
142
+ [disabled, status, size, focused, className]
143
+ );
144
+ const inputClasses = react.useMemo(
145
+ () => tigercatCore.getInputNumberInputClasses(
146
+ size,
147
+ controls && controlsPosition === "right",
148
+ controls && controlsPosition === "both"
149
+ ),
150
+ [size, controls, controlsPosition]
151
+ );
152
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClasses, children: [
153
+ controls && controlsPosition === "both" && /* @__PURE__ */ jsxRuntime.jsx(
154
+ "button",
155
+ {
156
+ type: "button",
157
+ tabIndex: -1,
158
+ "aria-label": "Decrease",
159
+ className: tigercatCore.getInputNumberSideButtonClasses("left", disabled || atMin),
160
+ disabled: disabled || atMin,
161
+ onMouseDown: (e) => e.preventDefault(),
162
+ onClick: () => handleStep("down"),
163
+ children: /* @__PURE__ */ jsxRuntime.jsx(
164
+ "svg",
165
+ {
166
+ xmlns: "http://www.w3.org/2000/svg",
167
+ viewBox: "0 0 24 24",
168
+ fill: "none",
169
+ stroke: "currentColor",
170
+ strokeWidth: "2",
171
+ className: "w-4 h-4",
172
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.inputNumberMinusIconPathD })
173
+ }
174
+ )
175
+ }
176
+ ),
177
+ /* @__PURE__ */ jsxRuntime.jsx(
178
+ "input",
179
+ {
180
+ ref: inputRef,
181
+ type: "text",
182
+ inputMode: "decimal",
183
+ role: "spinbutton",
184
+ "aria-valuemin": min === -Infinity ? void 0 : min,
185
+ "aria-valuemax": max === Infinity ? void 0 : max,
186
+ "aria-valuenow": currentValue ?? void 0,
187
+ className: inputClasses,
188
+ value: displayValue,
189
+ placeholder,
190
+ disabled,
191
+ readOnly: readonly,
192
+ name,
193
+ id,
194
+ onChange: handleInput,
195
+ onBlur: handleBlur,
196
+ onFocus: handleFocus,
197
+ onKeyDown: handleKeyDown
198
+ }
199
+ ),
200
+ controls && controlsPosition === "both" && /* @__PURE__ */ jsxRuntime.jsx(
201
+ "button",
202
+ {
203
+ type: "button",
204
+ tabIndex: -1,
205
+ "aria-label": "Increase",
206
+ className: tigercatCore.getInputNumberSideButtonClasses("right", disabled || atMax),
207
+ disabled: disabled || atMax,
208
+ onMouseDown: (e) => e.preventDefault(),
209
+ onClick: () => handleStep("up"),
210
+ children: /* @__PURE__ */ jsxRuntime.jsx(
211
+ "svg",
212
+ {
213
+ xmlns: "http://www.w3.org/2000/svg",
214
+ viewBox: "0 0 24 24",
215
+ fill: "none",
216
+ stroke: "currentColor",
217
+ strokeWidth: "2",
218
+ className: "w-4 h-4",
219
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.inputNumberPlusIconPathD })
220
+ }
221
+ )
222
+ }
223
+ ),
224
+ controls && controlsPosition === "right" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tigercatCore.inputNumberControlsRightClasses, children: [
225
+ /* @__PURE__ */ jsxRuntime.jsx(
226
+ "button",
227
+ {
228
+ type: "button",
229
+ tabIndex: -1,
230
+ "aria-label": "Increase",
231
+ className: tigercatCore.getInputNumberStepButtonClasses("up", disabled || atMax),
232
+ disabled: disabled || atMax,
233
+ onMouseDown: (e) => e.preventDefault(),
234
+ onClick: () => handleStep("up"),
235
+ children: /* @__PURE__ */ jsxRuntime.jsx(
236
+ "svg",
237
+ {
238
+ xmlns: "http://www.w3.org/2000/svg",
239
+ viewBox: "0 0 24 24",
240
+ fill: "currentColor",
241
+ className: "w-3 h-3",
242
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.inputNumberUpIconPathD })
243
+ }
244
+ )
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsxRuntime.jsx(
248
+ "button",
249
+ {
250
+ type: "button",
251
+ tabIndex: -1,
252
+ "aria-label": "Decrease",
253
+ className: tigercatCore.getInputNumberStepButtonClasses("down", disabled || atMin),
254
+ disabled: disabled || atMin,
255
+ onMouseDown: (e) => e.preventDefault(),
256
+ onClick: () => handleStep("down"),
257
+ children: /* @__PURE__ */ jsxRuntime.jsx(
258
+ "svg",
259
+ {
260
+ xmlns: "http://www.w3.org/2000/svg",
261
+ viewBox: "0 0 24 24",
262
+ fill: "currentColor",
263
+ className: "w-3 h-3",
264
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.inputNumberDownIconPathD })
265
+ }
266
+ )
267
+ }
268
+ )
269
+ ] })
270
+ ] });
271
+ };
272
+
273
+ exports.InputNumber = InputNumber;